#include "global.h" #include "dma3.h" void ClearDma3Requests(void) { int i; gDma3ManagerLocked = TRUE; gDma3RequestCursor = FALSE; for(i = 0; i < (u8)ARRAY_COUNT(gDma3Requests); i++) { gDma3Requests[i].size = 0; gDma3Requests[i].src = 0; gDma3Requests[i].dest = 0; } gDma3ManagerLocked = FALSE; } #ifdef NONMATCHING void ProcessDma3Requests(void) { // NOTE: the fillerA member of the DMA struct is actually u32 value; // NOTE: gUnknown_0300001C is just a pointer inside the gDma3Requests structure, not a true symbol; feel free to remove u16 total_size; if (gDma3ManagerLocked) return; total_size = 0; // as long as there are DMA requests to process (unless size or vblank is an issue), do not exit while (gDma3Requests[gDma3RequestCursor].size) { total_size += gDma3Requests[gDma3RequestCursor].size; if (total_size > 0xA000) return; // don't do too much at once if (REG_VCOUNT > 224) return;// we're about to leave vblank, stop switch (gDma3Requests[gDma3RequestCursor].mode) { case 1: // regular 32-bit copy // _08000C8C if(gDma3Requests[gDma3RequestCursor].size <= 0x1000) { DmaCopy32(3, gDma3Requests[gDma3RequestCursor].src, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size); break; } while (gDma3Requests[gDma3RequestCursor].size > 0x1000) { DmaCopy32(3, gDma3Requests[gDma3RequestCursor].src, gDma3Requests[gDma3RequestCursor].dest, 0x1000); gDma3Requests[gDma3RequestCursor].src += 0x1000; gDma3Requests[gDma3RequestCursor].dest += 0x1000; gDma3Requests[gDma3RequestCursor].size -= 0x1000; } DmaCopy32(3, gDma3Requests[gDma3RequestCursor].src, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size); break; case 2: // repeat a single 32-bit value across RAM // _08000CD0 while (gDma3Requests[gDma3RequestCursor].size > 0x1000) { DmaFill32(3, gDma3Requests[gDma3RequestCursor].value, gDma3Requests[gDma3RequestCursor].dest, 0x1000); gDma3Requests[gDma3RequestCursor].dest += 0x1000; gDma3Requests[gDma3RequestCursor].size -= 0x1000; } DmaFill32(3, gDma3Requests[gDma3RequestCursor].value, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size); break; case 3: // regular 16-bit copy // _08000D3C while (gDma3Requests[gDma3RequestCursor].size > 0x1000) { DmaCopy16(3, gDma3Requests[gDma3RequestCursor].src, gDma3Requests[gDma3RequestCursor].dest, 0x1000); gDma3Requests[gDma3RequestCursor].src += 0x1000; gDma3Requests[gDma3RequestCursor].dest += 0x1000; gDma3Requests[gDma3RequestCursor].size -= 0x1000; } DmaCopy16(3, gDma3Requests[gDma3RequestCursor].src, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size); break; case 4: // repeat a single 16-bit value across RAM // _08000D88 while (gDma3Requests[gDma3RequestCursor].size > 0x1000) { DmaFill16(3, gDma3Requests[gDma3RequestCursor].value, gDma3Requests[gDma3RequestCursor].dest, 0x1000); gDma3Requests[gDma3RequestCursor].dest += 0x1000; gDma3Requests[gDma3RequestCursor].size -= 0x1000; } DmaFill16(3, gDma3Requests[gDma3RequestCursor].value, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size); break; } gDma3Requests[gDma3RequestCursor].src = 0; gDma3Requests[gDma3RequestCursor].dest = 0; gDma3Requests[gDma3RequestCursor].size = 0; gDma3Requests[gDma3RequestCursor].mode = 0; gDma3Requests[gDma3RequestCursor].value = 0; gDma3RequestCursor++; if (gDma3RequestCursor >= 128) // loop back to the first DMA request gDma3RequestCursor = 0; } } #else __attribute__((naked)) void ProcessDma3Requests(void) { asm(".syntax unified\n\ push {r4-r7,lr}\n\ mov r7, r10\n\ mov r6, r9\n\ mov r5, r8\n\ push {r5-r7}\n\ sub sp, 0xC\n\ ldr r0, =gDma3ManagerLocked\n\ ldrb r0, [r0]\n\ cmp r0, 0\n\ beq _08000C06\n\ b _08000E46\n\ _08000C06:\n\ movs r0, 0\n\ str r0, [sp, 0x8]\n\ ldr r1, =gDma3Requests\n\ ldr r2, =gDma3RequestCursor\n\ ldrb r0, [r2]\n\ lsls r0, 4\n\ adds r0, r1\n\ ldrh r0, [r0, 0x8]\n\ mov r12, r2\n\ cmp r0, 0\n\ bne _08000C1E\n\ b _08000E46\n\ _08000C1E:\n\ mov r8, r1\n\ adds r1, 0x4\n\ mov r10, r1\n\ movs r6, 0x80\n\ lsls r6, 5\n\ ldr r7, =0x040000D4 @REG_DMA3\n\ movs r2, 0\n\ mov r9, r2\n\ _08000C2E:\n\ mov r3, r12 @ gDma3RequestCursor\n\ ldrb r0, [r3]\n\ lsls r5, r0, 4\n\ mov r0, r8 @ gDma3Requests\n\ adds r1, r5, r0 @ gDma3Requests[gDma3RequestCursor]\n\ ldrh r0, [r1, 0x8] @ gDma3Requests[gDma3RequestCursor].size\n\ ldr r2, [sp, 0x8]\n\ adds r0, r2, r0\n\ lsls r0, 16\n\ lsrs r0, 16\n\ str r0, [sp, 0x8]\n\ movs r0, 0xA0\n\ lsls r0, 8\n\ ldr r3, [sp, 0x8]\n\ cmp r3, r0\n\ bls _08000C50\n\ b _08000E46\n\ _08000C50:\n\ ldr r0, =0x04000006 @REG_VCOUNT\n\ ldrb r0, [r0]\n\ cmp r0, 0xE0\n\ bls _08000C5A\n\ b _08000E46\n\ _08000C5A:\n\ ldrh r0, [r1, 0xA]\n\ cmp r0, 0x2\n\ beq _08000CD0\n\ cmp r0, 0x2\n\ bgt _08000C80\n\ cmp r0, 0x1\n\ beq _08000C8C\n\ b _08000DF0\n\ .pool\n\ _08000C80:\n\ cmp r0, 0x3\n\ beq _08000D3C\n\ cmp r0, 0x4\n\ bne _08000C8A\n\ b _08000D88\n\ _08000C8A:\n\ b _08000DF0\n\ _08000C8C:\n\ ldr r3, [r1]\n\ mov r2, r10\n\ adds r0, r5, r2\n\ ldr r2, [r0]\n\ ldrh r1, [r1, 0x8]\n\ cmp r1, r6\n\ bhi _08000CA6\n\ str r3, [r7]\n\ str r2, [r7, 0x4]\n\ lsrs r0, r1, 2\n\ movs r1, 0x84\n\ lsls r1, 24\n\ b _08000DAA\n\ _08000CA6:\n\ ldr r4, =0x040000D4 @REG_DMA3\n\ str r3, [r4]\n\ str r2, [r4, 0x4]\n\ ldr r0, =0x84000400\n\ str r0, [r4, 0x8]\n\ ldr r0, [r4, 0x8]\n\ adds r3, r6\n\ adds r2, r6\n\ subs r1, r6\n\ cmp r1, r6\n\ bhi _08000CA6\n\ str r3, [r4]\n\ str r2, [r4, 0x4]\n\ lsrs r0, r1, 2\n\ movs r1, 0x84\n\ lsls r1, 24\n\ b _08000D76\n\ .pool\n\ _08000CD0:\n\ mov r3, r10\n\ adds r0, r5, r3\n\ ldr r4, [r0]\n\ ldrh r1, [r1, 0x8]\n\ cmp r1, r6\n\ bhi _08000CF4\n\ mov r0, r8\n\ adds r0, 0xC\n\ adds r0, r5, r0\n\ ldr r0, [r0]\n\ str r0, [sp]\n\ mov r5, sp\n\ str r5, [r7]\n\ str r4, [r7, 0x4]\n\ lsrs r0, r1, 2\n\ movs r1, 0x85\n\ lsls r1, 24\n\ b _08000DAA\n\ _08000CF4:\n\ mov r2, r12\n\ ldrb r0, [r2]\n\ lsls r0, 4\n\ mov r5, r8\n\ adds r5, 0xC\n\ adds r0, r5\n\ ldr r0, [r0]\n\ str r0, [sp]\n\ ldr r3, =0x040000D4 @REG_DMA3\n\ mov r0, sp\n\ str r0, [r3]\n\ str r4, [r3, 0x4]\n\ ldr r0, =0x85000400\n\ str r0, [r3, 0x8]\n\ ldr r0, [r3, 0x8]\n\ adds r4, r6\n\ subs r1, r6\n\ cmp r1, r6\n\ bhi _08000CF4\n\ ldrb r0, [r2]\n\ lsls r0, 4\n\ adds r0, r5\n\ ldr r0, [r0]\n\ str r0, [sp]\n\ mov r2, sp\n\ str r2, [r3]\n\ str r4, [r3, 0x4]\n\ lsrs r0, r1, 2\n\ movs r1, 0x85\n\ lsls r1, 24\n\ b _08000DEA\n\ .pool\n\ _08000D3C:\n\ ldr r3, [r1]\n\ mov r2, r10\n\ adds r0, r5, r2\n\ ldr r2, [r0]\n\ ldrh r1, [r1, 0x8]\n\ cmp r1, r6\n\ bhi _08000D56\n\ str r3, [r7]\n\ str r2, [r7, 0x4]\n\ lsrs r0, r1, 1\n\ movs r1, 0x80\n\ lsls r1, 24\n\ b _08000DAA\n\ _08000D56:\n\ ldr r4, =0x040000D4 @REG_DMA3\n\ str r3, [r4]\n\ str r2, [r4, 0x4]\n\ ldr r0, =0x80000800\n\ str r0, [r4, 0x8]\n\ ldr r0, [r4, 0x8]\n\ adds r3, r6\n\ adds r2, r6\n\ subs r1, r6\n\ cmp r1, r6\n\ bhi _08000D56\n\ str r3, [r4]\n\ str r2, [r4, 0x4]\n\ lsrs r0, r1, 1\n\ movs r1, 0x80\n\ lsls r1, 24\n\ _08000D76:\n\ orrs r0, r1\n\ str r0, [r4, 0x8]\n\ ldr r0, [r4, 0x8]\n\ b _08000DF0\n\ .pool\n\ _08000D88:\n\ mov r3, r10\n\ adds r0, r5, r3\n\ ldr r2, [r0]\n\ ldrh r4, [r1, 0x8]\n\ add r1, sp, 0x4\n\ cmp r4, r6\n\ bhi _08000DB2\n\ mov r0, r8\n\ adds r0, 0xC\n\ adds r0, r5, r0\n\ ldr r0, [r0]\n\ strh r0, [r1]\n\ str r1, [r7]\n\ str r2, [r7, 0x4]\n\ lsrs r0, r4, 1\n\ movs r1, 0x81\n\ lsls r1, 24\n\ _08000DAA:\n\ orrs r0, r1\n\ str r0, [r7, 0x8]\n\ ldr r0, [r7, 0x8]\n\ b _08000DF0\n\ _08000DB2:\n\ mov r5, r12\n\ ldrb r0, [r5]\n\ lsls r0, 4\n\ ldr r3, =gUnknown_0300001C\n\ adds r0, r3\n\ ldr r0, [r0]\n\ strh r0, [r1]\n\ ldr r3, =0x040000D4 @REG_DMA3\n\ str r1, [r3]\n\ str r2, [r3, 0x4]\n\ ldr r0, =0x81000800\n\ str r0, [r3, 0x8]\n\ ldr r0, [r3, 0x8]\n\ adds r2, r6\n\ subs r4, r6\n\ cmp r4, r6\n\ bhi _08000DB2\n\ ldrb r0, [r5]\n\ lsls r0, 4\n\ ldr r5, =gUnknown_0300001C\n\ adds r0, r5\n\ ldr r0, [r0]\n\ strh r0, [r1]\n\ str r1, [r3]\n\ str r2, [r3, 0x4]\n\ lsrs r0, r4, 1\n\ movs r1, 0x81\n\ lsls r1, 24\n\ _08000DEA:\n\ orrs r0, r1\n\ str r0, [r3, 0x8]\n\ ldr r0, [r3, 0x8]\n\ _08000DF0:\n\ ldr r1, =gDma3Requests\n\ mov r3, r12\n\ ldrb r0, [r3]\n\ lsls r0, 4\n\ adds r0, r1\n\ mov r2, r9\n\ str r2, [r0]\n\ ldrb r0, [r3]\n\ lsls r0, 4\n\ add r0, r10\n\ str r2, [r0]\n\ ldrb r0, [r3]\n\ lsls r0, 4\n\ adds r0, r1\n\ movs r4, 0\n\ strh r2, [r0, 0x8]\n\ ldrb r0, [r3]\n\ lsls r0, 4\n\ adds r0, r1\n\ mov r5, r9\n\ strh r5, [r0, 0xA]\n\ ldrb r0, [r3]\n\ lsls r0, 4\n\ adds r1, 0xC\n\ adds r0, r1\n\ mov r1, r9\n\ str r1, [r0]\n\ ldrb r0, [r3]\n\ adds r0, 0x1\n\ strb r0, [r3]\n\ lsls r0, 24\n\ cmp r0, 0\n\ bge _08000E34\n\ strb r4, [r3]\n\ _08000E34:\n\ mov r2, r12\n\ ldrb r0, [r2]\n\ lsls r0, 4\n\ ldr r3, =gDma3Requests\n\ adds r0, r3\n\ ldrh r0, [r0, 0x8]\n\ cmp r0, 0\n\ beq _08000E46\n\ b _08000C2E\n\ _08000E46:\n\ add sp, 0xC\n\ pop {r3-r5}\n\ mov r8, r3\n\ mov r9, r4\n\ mov r10, r5\n\ pop {r4-r7}\n\ pop {r0}\n\ bx r0\n\ .pool\n\ .syntax divided"); } #endif int RequestDma3Copy(void *src, void *dest, u16 size, u8 mode) { int cursor; int var = 0; gDma3ManagerLocked = 1; cursor = gDma3RequestCursor; while(1) { if(!gDma3Requests[cursor].size) // an empty copy was found and the current cursor will be returned. { gDma3Requests[cursor].src = src; gDma3Requests[cursor].dest = dest; gDma3Requests[cursor].size = size; if(mode == 1) gDma3Requests[cursor].mode = mode; else gDma3Requests[cursor].mode = 3; gDma3ManagerLocked = FALSE; return (s16)cursor; } if(++cursor >= 0x80) // loop back to start. { cursor = 0; } if(++var >= 0x80) // max checks were made. all resulted in failure. { break; } } gDma3ManagerLocked = FALSE; return -1; } int RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode) { int cursor; int var = 0; cursor = gDma3RequestCursor; gDma3ManagerLocked = 1; while(1) { if(!gDma3Requests[cursor].size) { gDma3Requests[cursor].dest = dest; gDma3Requests[cursor].size = size; gDma3Requests[cursor].mode = mode; gDma3Requests[cursor].value = value; if(mode == 1) gDma3Requests[cursor].mode = 2; else gDma3Requests[cursor].mode = 4; gDma3ManagerLocked = FALSE; return (s16)cursor; } if(++cursor >= 0x80) // loop back to start. { cursor = 0; } if(++var >= 0x80) // max checks were made. all resulted in failure. { break; } } gDma3ManagerLocked = FALSE; return -1; } int CheckForSpaceForDma3Request(s16 index) { int current = 0; if (index == -1) { for (; current < 0x80; current ++) if (gDma3Requests[current].size) return -1; return 0; } if (gDma3Requests[index].size) return -1; return 0; }