From d7c1d2a2cdb39c5e0bc6c3711968b876485d758a Mon Sep 17 00:00:00 2001 From: StapleButter Date: Wed, 18 Jan 2017 17:57:12 +0100 Subject: [PATCH] * start GPU shit: draw BG0 16-color. * fix a few DMA bugs. * fix a bug where some code could still run right after a halt instruction. * fix VRAM mapping, too. I'm an idiot. --- ARM.cpp | 3 +- DMA.cpp | 20 +++--- GPU.cpp | 24 +------ GPU.h | 1 + GPU2D.cpp | 182 +++++++++++++++++++++++++++++++++++++++++++++++-- GPU2D.h | 6 ++ NDS.cpp | 39 +++++++---- NDS.h | 2 + main.cpp | 8 +++ melonDS.depend | 24 +++---- 10 files changed, 244 insertions(+), 65 deletions(-) diff --git a/ARM.cpp b/ARM.cpp index ba29991f..3166fb85 100644 --- a/ARM.cpp +++ b/ARM.cpp @@ -228,7 +228,7 @@ s32 ARM::Execute(s32 cycles) if (Halted) { if (NDS::HaltInterrupted(Num)) - Halted = false; + Halted = 0; else return cycles; } @@ -283,6 +283,7 @@ s32 ARM::Execute(s32 cycles) } // TODO optimize this shit!!! + if (Halted) return cycles; if (NDS::HaltInterrupted(Num)) { if (NDS::IME[Num]&1) diff --git a/DMA.cpp b/DMA.cpp index 0cb47576..4b97b2fb 100644 --- a/DMA.cpp +++ b/DMA.cpp @@ -63,20 +63,20 @@ void DMA::WriteCnt(u32 val) CurSrcAddr = SrcAddr; CurDstAddr = DstAddr; - switch (Cnt & 0x00060000) + switch (Cnt & 0x00600000) { case 0x00000000: DstAddrInc = 1; break; - case 0x00020000: DstAddrInc = -1; break; - case 0x00040000: DstAddrInc = 0; break; - case 0x00060000: DstAddrInc = 1; break; + case 0x00200000: DstAddrInc = -1; break; + case 0x00400000: DstAddrInc = 0; break; + case 0x00600000: DstAddrInc = 1; break; } - switch (Cnt & 0x00180000) + switch (Cnt & 0x01800000) { case 0x00000000: SrcAddrInc = 1; break; - case 0x00080000: SrcAddrInc = -1; break; - case 0x00100000: SrcAddrInc = 0; break; - case 0x00180000: SrcAddrInc = 1; printf("BAD DMA SRC INC MODE 3\n"); break; + case 0x00800000: SrcAddrInc = -1; break; + case 0x01000000: SrcAddrInc = 0; break; + case 0x01800000: SrcAddrInc = 1; printf("BAD DMA SRC INC MODE 3\n"); break; } if (CPU == 0) @@ -106,10 +106,10 @@ void DMA::Start() if ((Cnt & 0x00060000) == 0x00060000) CurDstAddr = DstAddr; - printf("ARM%d DMA%d %08X->%08X %d units %dbit\n", CPU?7:9, Num, CurSrcAddr, CurDstAddr, RemCount, (Cnt & 0x04000000)?16:32); + printf("ARM%d DMA%d %08X %08X->%08X %d bytes %dbit\n", CPU?7:9, Num, Cnt, CurSrcAddr, CurDstAddr, RemCount*((Cnt & 0x04000000)?2:4), (Cnt & 0x04000000)?16:32); // TODO: NOT MAKE THE DMA INSTANT!! - if (Cnt & 0x04000000) + if (!(Cnt & 0x04000000)) { u16 (*readfn)(u32) = CPU ? NDS::ARM7Read16 : NDS::ARM9Read16; void (*writefn)(u32,u16) = CPU ? NDS::ARM7Write16 : NDS::ARM9Write16; diff --git a/GPU.cpp b/GPU.cpp index a640d49c..4bf55694 100644 --- a/GPU.cpp +++ b/GPU.cpp @@ -108,7 +108,7 @@ void Reset() GPU2D_A->Reset(); GPU2D_B->Reset(); - GPU2D_A->SetFramebuffer(&Framebuffer[0*192]); + GPU2D_A->SetFramebuffer(&Framebuffer[256*0]); GPU2D_B->SetFramebuffer(&Framebuffer[256*192]); } @@ -682,24 +682,6 @@ void MapVRAM_I(u32 bank, u8 cnt) } -void DrawScanline(u32 screen, u32 line) -{ - u16* dst = &Framebuffer[256 * ((192*screen) + line)]; - - if (screen==0) - { - u16* src = &((u16*)VRAM_A)[256*line]; - for (int i = 0; i < 256; i++) - dst[i] = src[i]; - } - else - { - for (int i = 0; i < 256; i++) - dst[i] = 0x7FFF; - } -} - - void StartFrame() { StartScanline(0); @@ -730,8 +712,8 @@ void StartScanline(u32 line) if (line < 192) { // draw - DrawScanline(0, line); - DrawScanline(1, line); + GPU2D_A->DrawScanline(line); + GPU2D_B->DrawScanline(line); NDS::ScheduleEvent(LINE_CYCLES, StartScanline, line+1); } diff --git a/GPU.h b/GPU.h index 915f44dd..dda33e5e 100644 --- a/GPU.h +++ b/GPU.h @@ -34,6 +34,7 @@ extern u8 VRAMSTAT; extern u8 Palette[2*1024]; extern u8 OAM[2*1024]; +extern u8* VRAM[9]; extern u8* VRAM_ABG[128]; extern u8* VRAM_AOBJ[128]; extern u8* VRAM_BBG[128]; diff --git a/GPU2D.cpp b/GPU2D.cpp index f6da8d05..6b954bf8 100644 --- a/GPU2D.cpp +++ b/GPU2D.cpp @@ -17,9 +17,9 @@ */ #include +#include #include "NDS.h" #include "GPU.h" -#include "GPU2D.h" GPU2D::GPU2D(u32 num) @@ -33,7 +33,8 @@ GPU2D::~GPU2D() void GPU2D::Reset() { - // + DispCnt = 0; + memset(BGCnt, 0, 4*2); } void GPU2D::SetFramebuffer(u16* buf) @@ -47,21 +48,31 @@ void GPU2D::SetFramebuffer(u16* buf) u8 GPU2D::Read8(u32 addr) { printf("!! GPU2D READ8 %08X\n", addr); + return 0; } u16 GPU2D::Read16(u32 addr) { switch (addr & 0x00000FFF) { - // + case 0x000: return DispCnt&0xFFFF; + case 0x002: return DispCnt>>16; + + case 0x008: return BGCnt[0]; + case 0x00A: return BGCnt[1]; + case 0x00C: return BGCnt[2]; + case 0x00E: return BGCnt[3]; } + + printf("unknown GPU read16 %08X\n", addr); + return 0; } u32 GPU2D::Read32(u32 addr) { switch (addr & 0x00000FFF) { - // + case 0x000: return DispCnt; } return Read16(addr) | (Read16(addr+2) << 16); @@ -76,15 +87,29 @@ void GPU2D::Write16(u32 addr, u16 val) { switch (addr & 0x00000FFF) { - // + case 0x000: + DispCnt = (DispCnt & 0xFFFF0000) | val; + return; + case 0x002: + DispCnt = (DispCnt & 0x0000FFFF) | (val << 16); + return; + + case 0x008: BGCnt[0] = val; return; + case 0x00A: BGCnt[1] = val; return; + case 0x00C: BGCnt[2] = val; return; + case 0x00E: BGCnt[3] = val; return; } + + printf("unknown GPU write16 %08X %04X\n", addr, val); } void GPU2D::Write32(u32 addr, u32 val) { switch (addr & 0x00000FFF) { - // + case 0x000: + DispCnt = val; + return; } Write16(addr, val&0xFFFF); @@ -94,5 +119,148 @@ void GPU2D::Write32(u32 addr, u32 val) void GPU2D::DrawScanline(u32 line) { - // + u16* dst = &Framebuffer[256*line]; + + u32 dispmode = DispCnt >> 16; + dispmode &= (Num ? 0x1 : 0x3); + + switch (dispmode) + { + case 0: // screen off + { + for (int i = 0; i < 256>>1; i++) + ((u32*)dst)[i] = 0x7FFF7FFF; + } + break; + + case 1: // regular display + { + DrawScanline_Mode1(line, dst); + } + break; + + case 2: // VRAM display + { + u32* vram = (u32*)GPU::VRAM[(DispCnt >> 18) & 0x3]; + vram = &vram[line << 7]; + + for (int i = 0; i < 256>>1; i++) + ((u32*)dst)[i] = vram[i]; + } + break; + + case 3: // FIFO display + { + // uh, is there even anything that uses this? + } + break; + } +} + +void GPU2D::DrawScanline_Mode1(u32 line, u16* dst) +{ + for (int i = 0; i < 256>>1; i++) + ((u32*)dst)[i] = 0; // TODO: backdrop + + switch (DispCnt & 0x7) + { + case 0: + for (int i = 3; i >= 0; i--) + { + // TODO other BGs + if ((BGCnt[0] & 0x3) == i) + { + DrawBG_Text_4bpp(line, dst, 0); + // todo: sprites + } + } + break; + } +} + +// char 06218000 +// screen 06208000 +void GPU2D::DrawBG_Text_4bpp(u32 line, u16* dst, u32 bgnum) +{ + u16 bgcnt = BGCnt[bgnum]; + + u8* tileset; + u16* tilemap; + u16* pal; + + // TODO scroll + u16 xoff = 0; + u16 yoff = line; + + u32 widexmask = (bgcnt & 0x4000) ? 0x100 : 0; + //u32 ymask = (bgcnt & 0x8000) ? 0x1FF : 0xFF; + + if (Num) + { + tileset = (u8*)GPU::VRAM_BBG[((bgcnt & 0x000C) >> 2)]; + tilemap = (u16*)GPU::VRAM_BBG[((bgcnt & 0x1800) >> 11)]; + tilemap += ((bgcnt & 0x0700) << 2); + + pal = (u16*)&GPU::Palette[0x400]; + } + else + { + tileset = (u8*)GPU::VRAM_ABG[((DispCnt & 0x07000000) >> 22) + ((bgcnt & 0x003C) >> 2)]; + tilemap = (u16*)GPU::VRAM_ABG[((DispCnt & 0x38000000) >> 27) + ((bgcnt & 0x1800) >> 11)]; + tilemap += ((bgcnt & 0x0700) << 2); + + pal = (u16*)&GPU::Palette[0]; + } + + // adjust Y position in tilemap + if (bgcnt & 0x8000) + { + tilemap += ((yoff & 0x1F8) << 2); + if (bgcnt & 0x4000) + tilemap += ((yoff & 0x100) << 2); + } + else + tilemap += ((yoff & 0xF8) << 2); + + u16 curtile; + u16* curpal; + u8* pixels; + + // preload shit as needed + if (xoff & 0x7) + { + // load a new tile + curtile = tilemap[((xoff & 0xFF) >> 3) + ((xoff & widexmask) << 2)]; + curpal = pal + ((curtile & 0xF000) >> 8); + pixels = tileset + ((curtile & 0x01FF) << 5) + ((yoff & 0x7) << 2); + pixels += ((xoff & 0x7) >> 1); + } + + for (int i = 0; i < 256; i++) + { + if (!(xoff & 0x7)) + { + // load a new tile + curtile = tilemap[((xoff & 0xFF) >> 3) + ((xoff & widexmask) << 2)]; + curpal = pal + ((curtile & 0xF000) >> 8); + pixels = tileset + ((curtile & 0x01FF) << 5) + ((yoff & 0x7) << 2); + } + + // draw pixel + u8 color; + if (xoff & 0x1) + { + color = *pixels >> 4; + pixels++; + } + else + { + color = *pixels & 0x0F; + } + //color = (i >> 4) + ((line >> 4) << 4); + //if (Num) color = 0; + dst[i] = curpal[color]; + + xoff++; + } } diff --git a/GPU2D.h b/GPU2D.h index abf5cc93..cbc3fb5c 100644 --- a/GPU2D.h +++ b/GPU2D.h @@ -41,6 +41,12 @@ public: private: u32 Num; u16* Framebuffer; + + u32 DispCnt; + u16 BGCnt[4]; + + void DrawScanline_Mode1(u32 line, u16* dst); + void DrawBG_Text_4bpp(u32 line, u16* dst, u32 num); }; #endif diff --git a/NDS.cpp b/NDS.cpp index fde36ac1..d0fcbb7e 100644 --- a/NDS.cpp +++ b/NDS.cpp @@ -484,10 +484,9 @@ void MapSharedWRAM(u8 val) void TriggerIRQ(u32 cpu, u32 irq) { irq = 1 << irq; - //if (!(IE[cpu] & irq)) return; - IF[cpu] |= irq; + // this is redundant if (!(IME[cpu] & 0x1)) return; (cpu?ARM7:ARM9)->TriggerIRQ(); } @@ -772,8 +771,8 @@ u8 ARM9Read8(u32 addr) switch (addr & 0x00E00000) { case 0x00000000: vram = GPU::VRAM_ABG[chunk]; break; - case 0x00200000: vram = GPU::VRAM_AOBJ[chunk]; break; - case 0x00400000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00200000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00400000: vram = GPU::VRAM_AOBJ[chunk]; break; case 0x00600000: vram = GPU::VRAM_BOBJ[chunk]; break; case 0x00800000: vram = GPU::VRAM_LCD[chunk]; break; } @@ -784,6 +783,10 @@ u8 ARM9Read8(u32 addr) case 0x07000000: return *(u8*)&GPU::OAM[addr & 0x7FF]; + + case 0x08000000: + case 0x09000000: + return 0xFF; } printf("unknown arm9 read8 %08X\n", addr); @@ -827,8 +830,8 @@ u16 ARM9Read16(u32 addr) switch (addr & 0x00E00000) { case 0x00000000: vram = GPU::VRAM_ABG[chunk]; break; - case 0x00200000: vram = GPU::VRAM_AOBJ[chunk]; break; - case 0x00400000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00200000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00400000: vram = GPU::VRAM_AOBJ[chunk]; break; case 0x00600000: vram = GPU::VRAM_BOBJ[chunk]; break; case 0x00800000: vram = GPU::VRAM_LCD[chunk]; break; } @@ -839,6 +842,10 @@ u16 ARM9Read16(u32 addr) case 0x07000000: return *(u16*)&GPU::OAM[addr & 0x7FF]; + + case 0x08000000: + case 0x09000000: + return 0xFFFF; } printf("unknown arm9 read16 %08X\n", addr); @@ -897,8 +904,8 @@ u32 ARM9Read32(u32 addr) switch (addr & 0x00E00000) { case 0x00000000: vram = GPU::VRAM_ABG[chunk]; break; - case 0x00200000: vram = GPU::VRAM_AOBJ[chunk]; break; - case 0x00400000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00200000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00400000: vram = GPU::VRAM_AOBJ[chunk]; break; case 0x00600000: vram = GPU::VRAM_BOBJ[chunk]; break; case 0x00800000: vram = GPU::VRAM_LCD[chunk]; break; } @@ -909,6 +916,10 @@ u32 ARM9Read32(u32 addr) case 0x07000000: return *(u32*)&GPU::OAM[addr & 0x7FF]; + + case 0x08000000: + case 0x09000000: + return 0xFFFFFFFF; } printf("unknown arm9 read32 %08X | %08X %08X %08X\n", addr, ARM9->R[15], ARM9->R[12], ARM9Read32(0x027FF820)); @@ -990,8 +1001,8 @@ void ARM9Write16(u32 addr, u16 val) switch (addr & 0x00E00000) { case 0x00000000: vram = GPU::VRAM_ABG[chunk]; break; - case 0x00200000: vram = GPU::VRAM_AOBJ[chunk]; break; - case 0x00400000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00200000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00400000: vram = GPU::VRAM_AOBJ[chunk]; break; case 0x00600000: vram = GPU::VRAM_BOBJ[chunk]; break; case 0x00800000: vram = GPU::VRAM_LCD[chunk]; break; } @@ -1047,8 +1058,8 @@ void ARM9Write32(u32 addr, u32 val) switch (addr & 0x00E00000) { case 0x00000000: vram = GPU::VRAM_ABG[chunk]; break; - case 0x00200000: vram = GPU::VRAM_AOBJ[chunk]; break; - case 0x00400000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00200000: vram = GPU::VRAM_BBG[chunk]; break; + case 0x00400000: vram = GPU::VRAM_AOBJ[chunk]; break; case 0x00600000: vram = GPU::VRAM_BOBJ[chunk]; break; case 0x00800000: vram = GPU::VRAM_LCD[chunk]; break; } @@ -1396,7 +1407,7 @@ u16 ARM9IORead16(u32 addr) return GPU::GPU2D_B->Read16(addr); } - printf("unknown ARM9 IO read16 %08X\n", addr); + printf("unknown ARM9 IO read16 %08X %08X\n", addr, ARM9->R[15]); return 0; } @@ -1792,7 +1803,7 @@ u16 ARM7IORead16(u32 addr) case 0x04000504: return _soundbias; } - printf("unknown ARM7 IO read16 %08X\n", addr); + printf("unknown ARM7 IO read16 %08X %08X\n", addr, ARM9->R[15]); return 0; } diff --git a/NDS.h b/NDS.h index 95a95c6a..a7073bbc 100644 --- a/NDS.h +++ b/NDS.h @@ -76,6 +76,8 @@ typedef struct // hax extern u32 IME[2]; +extern u32 IE[2]; +extern u32 IF[2]; extern Timer Timers[8]; extern u32 ARM9ITCMSize; diff --git a/main.cpp b/main.cpp index 56ef7a7f..8e40f891 100644 --- a/main.cpp +++ b/main.cpp @@ -34,6 +34,12 @@ LRESULT CALLBACK derpo(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) { case WM_CLOSE: printf("close\n"); + { + FILE* f = fopen("vram.bin", "wb"); + for (int i = 0; i < 128; i++) + fwrite(GPU::VRAM_BBG[i], 16384, 1, f); + fclose(f); + } PostQuitMessage(0); return 0; @@ -46,6 +52,7 @@ LRESULT CALLBACK derpo(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) case VK_DOWN: NDS::PressKey(7); break; case VK_LEFT: NDS::PressKey(5); break; case VK_RIGHT: NDS::PressKey(4); break; + case 'P': NDS::PressKey(16+6); break; } return 0; @@ -58,6 +65,7 @@ LRESULT CALLBACK derpo(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) case VK_DOWN: NDS::ReleaseKey(7); break; case VK_LEFT: NDS::ReleaseKey(5); break; case VK_RIGHT: NDS::ReleaseKey(4); break; + case 'P': NDS::ReleaseKey(16+6); break; } return 0; diff --git a/melonDS.depend b/melonDS.depend index 076a607f..88c83024 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -1,16 +1,16 @@ # depslib dependency file v1.0 -1484707090 source:c:\documents\sources\melonds\main.cpp +1484751556 source:c:\documents\sources\melonds\main.cpp "NDS.h" "GPU.h" -1484615598 c:\documents\sources\melonds\nds.h +1484752883 c:\documents\sources\melonds\nds.h "types.h" 1481161027 c:\documents\sources\melonds\types.h -1484708424 source:c:\documents\sources\melonds\nds.cpp +1484758082 source:c:\documents\sources\melonds\nds.cpp "NDS.h" @@ -22,7 +22,7 @@ "SPI.h" "Wifi.h" -1484705354 source:c:\documents\sources\melonds\arm.cpp +1484754523 source:c:\documents\sources\melonds\arm.cpp "NDS.h" "ARM.h" @@ -38,7 +38,7 @@ "types.h" "ARM.h" -1484705417 source:c:\documents\sources\melonds\arminterpreter.cpp +1484752824 source:c:\documents\sources\melonds\arminterpreter.cpp "NDS.h" "CP15.h" @@ -68,7 +68,7 @@ 1481037554 c:\documents\sources\melonds\cp15.h -1484616493 source:c:\documents\sources\melonds\cp15.cpp +1484754534 source:c:\documents\sources\melonds\cp15.cpp "NDS.h" "ARM.h" @@ -81,13 +81,13 @@ "NDS.h" "SPI.h" -1484708331 source:c:\documents\sources\melonds\gpu2d.cpp +1484758294 source:c:\documents\sources\melonds\gpu2d.cpp + "NDS.h" "GPU.h" - "GPU2D.h" -1484707825 c:\documents\sources\melonds\gpu2d.h +1484711212 c:\documents\sources\melonds\gpu2d.h 1481040524 c:\documents\sources\melonds\wifi.h @@ -103,7 +103,7 @@ 1484612398 c:\documents\sources\melonds\fifo.h "types.h" -1484706353 source:c:\documents\sources\melonds\dma.cpp +1484756268 source:c:\documents\sources\melonds\dma.cpp "NDS.h" "DMA.h" @@ -111,12 +111,12 @@ 1484698068 c:\documents\sources\melonds\dma.h "types.h" -1484708259 source:c:\documents\sources\melonds\gpu.cpp +1484753188 source:c:\documents\sources\melonds\gpu.cpp "NDS.h" "GPU.h" -1484708251 c:\documents\sources\melonds\gpu.h +1484709419 c:\documents\sources\melonds\gpu.h "GPU2D.h"