Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .: N64 Test Cart on iQue :.
- The N64 Test Cart is a derivative of the go/no-go tool, itself derived from a test program used to develop the console and RDB boards. Source for an older variant was leaked in oman (gng), but this example is sourced from a partial dump made some years ago (it lacks some of the audio tests, version unknown).
- It runs a series of RSP/RDP tests and compares them to known good samples. If anything doesn't match up it displays an error on the screen alongside the major & minor test number blown. As of 4/2023, our best low-level video plugins still fail a number of these.
- Depending on the detected memory size--4MB, 6MB, or 8MB--there are some minor differences in certain test results.
- There has been a bit of a question about what the iQue may or may not do, or at what level its video output differs from N64 (it clearly does after all). It is basically one big ASIC.
- tl;dr: iQue passes all RSP/RDP tests, is fussy about certain address ranges, pattern-matches serial commands instead of parsing bytecode, doesn't like sudden video mode changes, and any video out differences are at final output.
- .: List of functions swapped with iQue support :.
- These functions were updated, mostly because they "just worked" and not necessarily because they needed to be. Note there are multiple copies of some of these, like osInitialize. Controller support normally needs to be adapted but it turns out it only uses the "normal" functions once, then completely ignores them >.<
- Essential:
- osInitialize
- __osViSwapContext
- osViSetMode
- osContStartReadData
- whatever 'copy result of SI status request to A1, setting presence flags to A0' is called
- Arguable:
- __osContRamRead
- __osContRamWrite
- osInitialize detects iQue and initializes it. This particular lib version also works with N64. Without this you get very peculiar behavior.
- __osViSwapContext & osViSetMode both ensure pixel advance in VI Status is set to 1, not 3, to prevent damage to hardware. One instance settings are manually written is also patched.
- The controller libs are adapted so the "pak present" flag is tied to Controller Pak data allocations provided in the ticket. It also swaps status & input when __osBbHackFlags is set.
- The factory test version uses a tool called zaru that plugged into *every* port, using an interface on controller port 1 and mapping its data to controller slot addresses usually used by Controller Paks / GB64 data. This could tell you the state of power & grounds and provided a big yellow button, earpiece, DIP switches, and an LED. Detecting it is based on a read/write test to the LED register, so for our purposes it's mostly important that it's indistinguishable from a Controller Pak and needs to be hidden from iQue to prevent a lot of fatal tests tied to it.
- The E/PI special cases are not necessary when access flag 0x20 is set, necessary for 8MB support. The MI hardware interrupts are not used. KeepAlive is removed by the patcher that allows unsigned content. Anything otherwise not mentioned apparently isn't very important either ;*)
- .: Patched Behavior :.
- * RAM tests are completely removed, as well as "rebooting".
- The bootloading sequence at 80200050 normally loaded code similar to an IPL to A4000000 on its first pass. This turned off rdram, then walked through the initialization and addressing portion again. The VI is manually initialized, then it walks through each word of rdram from 80000400 to detected maximum doing a read/write test. It then reloads the bootcode, resets the registers passed in from IPL1/2, and makes a second pass through 80200050.
- Problem #1 is that rdram registers are mapped--and initialized to zero. This test is guaranteed to fail. iQue has its own extended registers, and its own ram works in a fundamentally different way. (The normal rdram range might just be a special mapping of 81000000...)
- iQue
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 00000000 00000000 00000000 00000000
- 000011E0 000011E0 000011E0 000011E0
- 031111E4 031111E4 031111E4 031111E4
- 00000000 00000000 00000000 00000000
- 00000001 00000001 00000001 00000001
- 00000000 00000000 00000000 00000000
- 00000001 00000001 00000001 00000001
- Problem #2 is parts of the remainder also include init code skipped by iQue or requires adaptation (like VI regs). Plus it's long.
- Instead, the whole process is skipped: A0000320=0xDEADBEEF, A0000324=False if rdram isn't faulty.
- * At 80001660, does a read/write test of B0900000. This address is above provided ROM, making it lethal.
- iQue latches all addresses between the end of provided cart data and PIFRAM. If you try to read or write from them it will softlock the system. That's true of a number of other address ranges: A5000000 through B0000000 all appear to lock as well. Open-bus responses are used in early titles to detect 64DD, replaced by IPL reads. Both are lethal to iQues.
- In this case the read & write are both NOP'd and the conditional forced so it doesn't try to throw a cart interrupt later using a write to BF000000.
- * iQue uses pattern-matching for SI devices. It does not parse the bytecode!
- The normal libultra controller code is only used once, at boot. The rest of the serial input/status/reset/read/write code uses a hand-rolled library unique to dev programs.
- What this does is takes a list of five ints--one for each channel. It then copies into the buffer the corresponding bytecode for that command. There's eight of them, depending on how you count:
- 0 ignore channel; pushes a zero into the bytecode
- 1 byte: 00
- 1 device status; returns type of device or presence/error codes
- 6 bytes: 01 03 00 -- -- --
- 2 read controller input
- 7 bytes: 01 04 01 -- -- -- --
- 3 read controller slot
- 38 bytes: 03 21 02 {2 bytes addr|crc} {placeholder 32 bytes data} --
- 4 write controller slot
- 38 bytes: 23 01 03 {2 bytes addr|crc} {32 bytes data} {data crc}
- 5 read eeprom
- 12 bytes: 02 08 04 {addr} -- -- -- -- -- -- -- --
- 6 write eeprom
- 13 bytes: 0A 01 05 {addr} {8 bytes data} {crc}
- -1 reset; resets the device and returns status
- 6 bytes: 01 03 FF -- -- --
- else terminates with an error nothing checks for
- Basically, bytecode works like so: 0 ignores a channel, < 0 is special, > 0 is (count sent, count recieved, bytes sent, bytes received)
- PIF reads channels until it's out of them. -2 marks an explicit endpoint but with a "real" PIF the end is implied as well. Thankfully iQue also behaves this way. Also, commands don't have to be relevant. It simply encodes it, sends it along the port, and it's up to the device if it wants to respond. You can ask the cart eeprom line if it has any controller input (which it can, if you install a port there). iQue is forgiving on that front as well.
- The difference is that the "normal" os variants pad commands so they align nicely at certain addresses. It makes reading results a smidge easier, and you can predict exactly where each channel's data will be found (the hand-rolled one uses a table of pointers). The padding byte is -1, effectively a NOP.
- iQue either doesn't parse the bytecode itself or somebody made a mistake and thought the 0xFF padding bytes were part of the command. *iQue ignores reads* that aren't written as:
- FF 01 04 01 -- -- -- --
- (Note: It's unknown which other commands, if any, are subject to the same bug.)
- To get it to read input three functions were changed to account for aligned data:
- 8002E2FC V0 = p->end of pifram cmd to read input of SI device on channel index A1 using ctrl buffer A0
- This generates the bytecode sequence itself. It now adds the padding and advances 8 bytes instead of 7.
- 80001808 V0 = current buttons on controller 1
- 80035748 8006DE00 = current buttons, 8006DE04 = pressed buttons, 801914E0 = current buttons
- Both of these assumed the "unaligned" versions are in effect; aka. that the pointer to the command actually points at the command, not at a padding byte. In both, the address offset to the data was increased by 1.
- None of the other various functions appear to be used so long as a zaru unit isn't detected.
- * Commandline argument support is restored.
- The RDB version supports commandline arguments. This has been linked back in here by forcing the pointer to the string usually provided by the RDB to point to a copy of the internal ROM name at 0x20 in the header.
- There are two copies of osInitialize, one in the bootloader (80200000 range) and another in the main executable (80000400). The first of them has a short DMA tacked onto the end. It copies the internal name to 800001A0, usually reserved for 64DD disk gameIDs.
- Although not all are valid in this configuration, the available options are:
- -l lines
- -b use black
- -z no zclear
- -----------------------
- -f int frame count = int; default -1
- -m int run module number = int; default -1
- -d route RSP output to RDP through DRAM; default False
- -c calc checksum; default True
- -p print checksum values (allow mismatch); default False
- -s silent mode; default False
- -x show RDP images versus text output; default False
- -r maintain resolution (use with -x); default False
- -F flush RDP mspan? enables 1 primitive mode; default False
- -g using with debugger, dropping back to boostrap; default False
- -i dump images; default False
- -e dump bad frames; default False
- -a dump all frames; default False
- -S dump RSP; default False
- -D dump RDP; default False
- -o str board number; default "100"
- .: Test Results :.
- The ticket was generated with access flag 0x20 to ensure 8MB support. 4MB, 6MB, and 8MB modes were all tested with the same results.
- All RSP & RDP tests passed. Any apparent differences in video output is not within the RCP but occurs when generating the output signal.
- Switching from interlaced mode to progressive causes several frames of color corruption. Switching video modes in general causes graphical errors (lines, flicker, etc.) over several frames. There's ghosting on the left edge of the output and during one test a stray pixel.
- Observed controller range is (appoximately):
- ymax 85, ymin -86, xmax 81, xmin -89
- UR (71,72), UL (-74,72), LR (71,-74), LL (-74,-74)
- -Zoinkity
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement