0x10 Level Command: Loads a block of ROM data into extended memory and assigns a segment ID

This was inspired by Yoshielectron's sucessful tests with extended memory.

This is an hybrid 0x17/0x16 level command. It can load segmented data anywhere in RAM, including extended memory. You have to manage memory manually by assigning the start address of the segment you are loading.

The original level command 0x10 is unused. It only reads the lenght byte and skips.


[10] 00 00 [07] [80 40 40 00 [01 21 00 00] [01 2E 00 00]
00. Command
01-2. Unused (I didn't bother to implement a variable lenght)
03. Target segment
04-07: RAM Address Target
08-11: ROM Block start
12-16: ROM Block end


SW RA, 0x0014 (SP)
LUI T6, 0x8039
LW T6, 0xBE28 (T6)     ; Pointer to command
LW A0, 0x0004 (T6)     ; Target in RAM
LW A1, 0x0008 (T6)     ; Block start
JAL 0x80278504         ; DMA Copy function
LW A2, 0x000C (T6)     ; Block end
LUI T6, 0x8039
LW T6, 0xBE28 (T6)     ; Pointer to command
LW A0, 0x0004 (T6)     ; RAM Target
LUI T7, 0x8000
XOR A0, A0, T7
LBU A3, 0x0003 (T6)    ; Target segment
SLL A3, A3, 0x2        ; segment * 4
LUI T4, 0x8033
ORI T4, T4, 0xB400     ; Segment pointer
ADDU T4, T4, A3        ; T4 = updated pointer acording to segment number
SW A0, 0x0000 (T4)
LUI T7, 0x8039
LW T7, 0xBE28 (T7)     ; pointer to level command
ADDIU T9, T7, 0x0010   ; increment pointer (16 bytes)
LUI AT, 0x8039
SW T9, 0xBE28 (AT)
LW RA, 0x0014 (SP)
ADDIU SP, SP, 0x0018

From Nagra's Mario Resource:

/* 0x80278504 */
DmaCopy(u32 dst, u32 bottom, u32 top)
    u32 block, size;

    size = (top - bottom + 15) & 0xfffffff0;
    osInvalDCache(dst, size);
    if (size) {
        do {
            if (size >= 4096) {
                block = 4096;
            } else {
                block = size;
            osPiStartDma(&dmaIOMessageBug, 0, 0, begin, dst, block, &dmaMessageQ);
            osRecvMesg(&dmaMessageQ, &dummyMessage, 1);
            dst += block;
            begin += block;
            size -= block;
        } while (size);