diff --git a/headers.js b/headers.js index 6a7d0ba..73b2dcf 100644 --- a/headers.js +++ b/headers.js @@ -1,8 +1,79 @@ for (const el of document.querySelectorAll("[id]")) { - el.classList.add("haspara") + el.classList.add("haspara"); const pilcrow = document.createElement("a"); - pilcrow.className = "pilcrow" + pilcrow.className = "pilcrow"; pilcrow.href = "#" + el.id; - pilcrow.innerHTML = "¶" - el.prepend(pilcrow) + pilcrow.innerHTML = "¶"; + el.prepend(pilcrow); } + +const foldable = (root, children) => { + let state = true; + root.addEventListener("click", (e) => { + if (e.target.classList.contains("pilcrow")) state = true; + else state = !state; + + children.style.height = state ? "auto" : "0"; + children.style.overflow = state ? "visible" : "hidden"; + if (state) root.classList.remove("closed"); + else root.classList.add("closed"); + }); + root.classList.add("toggle-root"); +}; + +const make_foldable = (root) => { + const child_stacks = new Array(10).fill(null).map(() => ({ children: [], root: null })); + + const flush_header = (this_level, sibling) => { + for (let level = 9; level >= this_level; level--) { + const stack = child_stacks[level]; + + if (!stack.root) continue; + + const new_e = document.createElement("div"); + for (const old_e of stack.children) { + old_e.remove(); + new_e.appendChild(old_e); + } + + foldable(stack.root, new_e); + let parent_level; + for (parent_level = level - 1; parent_level > 0; parent_level--) if (child_stacks[parent_level].root) break; + + if (parent_level === -1) { + if (sibling) root.insertBefore(new_e, sibling); + else root.appendChild(new_e); + } else { + stack.root.remove(); + child_stacks[parent_level].children.push(stack.root); + child_stacks[parent_level].children.push(new_e); + } + + stack.root = null; + stack.children.length = 0; + } + }; + + for (const child of [...root.children]) { + if (/^H\d$/.test(child.tagName)) { + const this_level = parseInt(child.tagName[1]) - 1; + + flush_header(this_level, child); + + child_stacks[this_level].root = child; + continue; + } + + for (let level = 9; level >= 0; level--) { + if (child_stacks[level].root) { + child_stacks[level].children.push(child); + break; + } + } + } + + for (let level = 9; level >= 0; level--) { + flush_header(level, null); + } +}; +make_foldable(document.body); diff --git a/images/mxstartup.png b/images/mxstartup.png new file mode 100644 index 0000000..8ac1758 Binary files /dev/null and b/images/mxstartup.png differ diff --git a/styles.css b/styles.css index da698bb..69c3c77 100644 --- a/styles.css +++ b/styles.css @@ -144,7 +144,7 @@ table.nav td { .pilcrow { position: absolute; right: calc(100%); - padding-right: 4px; + padding-right: 24px; top: .1em; font-size: .9em; text-decoration: none; @@ -234,6 +234,30 @@ mark { text-underline-offset: 1px; } +.toggle-root { + cursor: pointer; + position: relative; +} +.toggle-root::before { + opacity: .5; + content: ""; + display: block; + border: 4px solid currentColor; + border-left-color: transparent; + border-top-color: transparent; + position: absolute; + left: -18px; + top: 50%; + transform: translateY(-50%) rotate(45deg); + transition: transform 100ms ease-out, opacity 100ms ease-out; +} +.toggle-root:hover::before { + opacity: 1; +} +.toggle-root.closed::before { + transform: translateY(-50%) rotate(-45deg); +} + @media (prefers-color-scheme: dark) { body { background-color: #000; diff --git a/templates/pages/proto/cardmng.html b/templates/pages/proto/cardmng.html index 5f8d720..edc8a36 100644 --- a/templates/pages/proto/cardmng.html +++ b/templates/pages/proto/cardmng.html @@ -50,6 +50,40 @@
  • cardmng.getdatalist
  • +

    dataid? refid?

    +

    Some requests use refid, some use dataid, and some use both. What exactly you use these + values for is largely left up to the server implementer, as the game will echo them back verbatim, however here are + three suggestions:

    + + + + + + + + + +
    refidAn ID that references the user
    dataAn ID that references the game specific data for this user/game combination
    + + + + + + + + + +
    refidA session token issued during card auth
    dataAn ID that references the game specific data for this user/game combination
    + + + + + + + + + +
    refidAn ID that references the user
    dataThe same as refid; we can use database joins for accessing game data

    cardmng.inquire

    Request information about a card that has been inserted or touched against a reader.

    @@ -76,12 +110,11 @@ - + - + @@ -94,12 +127,16 @@ - + + + + +
    refidA reference to this card to be used in other requestsSee section about refid and dataid
    dataidAppears to be set the same as refid; presumably to allow different keys for game state vs - login details.See section about refid and dataid
    newflag
    expired? Just set to 0.? Just set it to 0.
    newflag? Just set it to 0.

    cardmng.getrefid

    -

    Register a new card to this server.

    +

    Register a new card to this server. In the process, we're also going to create a game profile.

    Request:

    {% highlight "cxml" %}
         
    @@ -122,20 +159,21 @@
     
    -        
    +        
    -        
    +        
    -        
    +        
    refidA reference to this card to be used in other requestsSee section about refid and dataid
    dataidAppears to be set the same as refid; presumably to allow different keys for game state vs - login details.See section about refid and dataid
    pcode? Not present in captured data.? Just omit this

    cardmng.bindmodel

    +

    Create a data profile for this card on the current game. Request and response should be fairly self-explanatory.

    +

    Request:

    {% highlight "cxml" %}
         
    diff --git a/templates/pages/protocol.html b/templates/pages/protocol.html
    index 7115d2e..b8d5d24 100644
    --- a/templates/pages/protocol.html
    +++ b/templates/pages/protocol.html
    @@ -219,5 +219,7 @@
     
     

    Possible XRPC requests

    +

    Of which properly documented:
    - cardmng

    + {{ generate_xrpc_list()|safe }} {% endblock %} \ No newline at end of file diff --git a/templates/pages/sega/partition.html b/templates/pages/sega/partition.html new file mode 100644 index 0000000..a4ee57e --- /dev/null +++ b/templates/pages/sega/partition.html @@ -0,0 +1,269 @@ +{% extends "sega.html" %} +{% block title %}SEGA Partition Structure{% endblock %} +{% block body %} +

    SEGA Partition Structure

    + +

    Games on the Ring* series use MBR partitioned drives. The core partition structure is as follows:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PartitionSizeFormatContent
    11.5GiBNTFSWindows XP Embedded 2009
    21.5GiBNTFSWindows recovery partition
    3remaining spaceExtended Partition (LBA)Game data
    4
    + +

    Extended partitions are structed by a linked list of partition headers at the beginning of each partition. These + headers reserve 3Fh blocks for their information, however only use a single block at the start of this + for actual data. SEGA make use of the remaining blocks in the first extended partition header for SEGA boot records. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Partition offset (blocks)Content
    0Extended partition header
    1SEGA Partition Description
    2SEGA Boot Record (1)
    3SEGA Boot Record (2)
    4-63Additional data storage
    64-...Actual partition data
    + +

    Two identical copies of the SEGA Boot Record are present. This is for redundancy; if either is corrupted, an attempt + will be made to restore it from the other copy.

    + +

    SEGA Partition Description

    + +

    The SEGA Partition Description (SPD) largely echos the structure laid out by the extended partition headers, however + is the table SEGA loaders preferentially read. It takes up all 512 bytes of the block; it's structure is as follows: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    0123456789ABCDEF
    00hCRC32Ver
    10hSlot content?Block sizeBlock count
    20hSlot content?Block sizeBlock count
    30hSlot content?Block sizeBlock count
    ...
    F0hSlot content?Block sizeBlock count
    + +

    The slot content types are:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ValueMeaning
    10horiginal0
    11horiginal1
    20hpatch0
    21hpatch1
    30hos
    40happ_data
    + +

    SEGA Boot Record

    + +

    The SEGA Boot Record (SBR) contains detailed information about the content of each slot.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    0123456789ABCDEF
    00hCRC32Ver
    10h
    20hBootslot5x slot status
    30h
    ...
    A0h
    B0h
    C0h
    D0h
    E0h
    F0h
    + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/sega/software/boot.html b/templates/pages/sega/software/boot.html new file mode 100644 index 0000000..e2b5cbf --- /dev/null +++ b/templates/pages/sega/software/boot.html @@ -0,0 +1,13 @@ +{% extends "sega.html" %} +{% block title %}Boot Sequence{% endblock %} +{% block body %} +

    Boot Sequence

    + +

    This page is a stub for now.

    + +
      +
    1. mxprestartup
    2. +
    3. mxstartup
    4. +
    + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/sega/software/mxmaster.html b/templates/pages/sega/software/mxmaster.html new file mode 100644 index 0000000..0085880 --- /dev/null +++ b/templates/pages/sega/software/mxmaster.html @@ -0,0 +1,23 @@ +{% extends "sega.html" %} +{% block title %}mxmaster{% endblock %} +{% block body %} +

    mxmaster

    + +

    mxmaster is the program responsible for orchastrating the entire system.

    + +

    It first spawns the following list of programs:

    + +
      +
    • s:\mxkeychip.exe
    • +
    • s:\mxnetwork.exe -p 40104
    • +
    • s:\mxstorage.exe
    • +
    • s:\mxinstaller.exe -cmdport 40102 -binport 40103 (sometimes with -openmode any appended)
    • +
    • s:\mxgcatcher.exe {appboot.platformid} {appboot.gameid} {appboot.networkaddr} {appboot.keyid}
    • +
    • s:\mxgfetcher.exe {appboot.platformid} {appboot.gameid} {appboot.networkaddr} {appboot.keyid}
    • +
    • s:\mxgdeliver.exe {appboot.platformid} {appboot.gameid} {appboot.networkaddr} {appboot.keyid}
    • +
    • C:\WINDOWS\system32\regini.exe S:\default_regset.txt
    • +
    • c:\System\Execute\mxsegaboot.exe
    • + +
    + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/sega/software/mxprestartup.html b/templates/pages/sega/software/mxprestartup.html new file mode 100644 index 0000000..8f77357 --- /dev/null +++ b/templates/pages/sega/software/mxprestartup.html @@ -0,0 +1,15 @@ +{% extends "sega.html" %} +{% block title %}mxprestartup{% endblock %} +{% block body %} +

    mxprestartup

    + +

    mxprestartup is the first program to run when the AppUser user logs in.

    + +

    This program's sole job is to construct the password for SystemUser, and spawn mxstartup.exe as SystemUser.

    + +

    Micetools contains a full version of this program, with a few additions for ease of use. It + can be found on the micetools repository.

    + +{% endblock %} \ No newline at end of file diff --git a/templates/pages/sega/software/mxstartup.html b/templates/pages/sega/software/mxstartup.html new file mode 100644 index 0000000..ae21b5c --- /dev/null +++ b/templates/pages/sega/software/mxstartup.html @@ -0,0 +1,133 @@ +{% extends "sega.html" %} +{% block title %}mxstartup{% endblock %} +{% block body %} +

    mxstartup

    + +

    mxstartup is responsible for some very initial system checks, loading the S: drive, and handing over to mxmaster.exe.

    + +

    This is the first time anything other than the Windows XP boot screen will be shown.

    + + + +

    mxstartup is responsible for a number of error codes, listed below. This table contains every error mxstartup can + produce, to the best of my knowledge.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Error codeMessageMeaning
    0500SecurityCheck error
    0501CheckEwfState error
    0502GetSystemVersion error
    0503GetsystemKeyFile
    0504SetDiskAccessPrivilege
    0505MountSystem
    0506MountUpdate error
    0507ExecuteMaMaster
    0508GetOSUpdateKeyFile error
    0509ExecuteMxOSUpdate error
    0510ChangeEWFStateEnable error
    0511GetSBRSlotOSState error
    0512Deleate Key File error
    0513MountDriver error
    0514CheckPlatform error
    0540Unmount error
    0541MountRecoveryVolume error
    0543MxChangeActivePartition error
    0545osuSystemReboot error
    0546GetSystemDiskNumber error
    ????SetBackupComputerName failed
    +

    These errors are also reported into the Application event log, under the source mxstartup.

    + +{% endblock %} \ No newline at end of file