From 592e493a7aae701957d1a5c05ef8d31c5187ed8c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 9 Jul 2019 18:39:50 +0200 Subject: [PATCH 01/32] input: don't check modifiers for regular input --- src/NDS.cpp | 3 ++- src/libui_sdl/main.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index 6272f88180..991995d229 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1548,7 +1548,8 @@ void debug(u32 param) // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); FILE* - shit = fopen("debug/manic.bin", "wb"); + shit = fopen("debug/party.bin", "wb"); + fwrite(ARM9->ITCM, 0x8000, 1, shit); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { u32 val = ARM7Read32(i); diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 99d4e3f040..e2d50ff8d0 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1168,13 +1168,13 @@ void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) { } -bool EventMatchesKey(uiAreaKeyEvent* evt, int val) +bool EventMatchesKey(uiAreaKeyEvent* evt, int val, bool checkmod) { if (val == -1) return false; int key = val & 0xFFFF; int mod = val >> 16; - return evt->Scancode == key && evt->Modifiers == mod; + return evt->Scancode == key && (!checkmod || evt->Modifiers == mod); } int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) @@ -1188,11 +1188,11 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (evt->Up) { for (int i = 0; i < 12; i++) - if (EventMatchesKey(evt, Config::KeyMapping[i])) + if (EventMatchesKey(evt, Config::KeyMapping[i], false)) KeyInputMask |= (1<Repeat) @@ -1215,11 +1215,11 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) } for (int i = 0; i < 12; i++) - if (EventMatchesKey(evt, Config::KeyMapping[i])) + if (EventMatchesKey(evt, Config::KeyMapping[i], false)) KeyInputMask &= ~(1< Date: Tue, 9 Jul 2019 18:41:44 +0200 Subject: [PATCH 02/32] don't allow modifier mappings in input config dialog, either --- src/libui_sdl/DlgInputConfig.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp index 3818c0480e..a80e2ec768 100644 --- a/src/libui_sdl/DlgInputConfig.cpp +++ b/src/libui_sdl/DlgInputConfig.cpp @@ -232,10 +232,12 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) // set key. if (evt->Scancode != 0x1 || evt->Modifiers != 0) // ESC { + int mod = (dlg->type == 0) ? 0 : evt->Modifiers; + if (evt->Scancode == 0xE && evt->Modifiers == 0) // backspace dlg->keymap[dlg->pollid] = -1; else - dlg->keymap[dlg->pollid] = evt->Scancode | (evt->Modifiers << 16); + dlg->keymap[dlg->pollid] = evt->Scancode | (mod << 16); } char keyname[64]; From ff27036b3566d0c4215cacf09d44486d46cfc049 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 12 Jul 2019 22:04:55 +0200 Subject: [PATCH 03/32] start botching the FPS limiter results in shitty audio because it's overflowing the buffer --- src/SPU.cpp | 1 + src/libui_sdl/main.cpp | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index ee9237f92d..2dfdf441f5 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -734,6 +734,7 @@ void Mix(u32 samples) OutputBuffer[OutputWriteOffset + 1] = r >> 1; OutputWriteOffset += 2; OutputWriteOffset &= ((2*OutputBufferSize)-1); + if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW\n"); } NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*kSamplesPerRun, Mix, kSamplesPerRun); diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index e2d50ff8d0..a19495b1ee 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -569,7 +569,7 @@ void AudioCallback(void* data, Uint8* stream, int len) int num_in = SPU::ReadOutput(buf_in, 710); int num_out = 1024; - +printf("took %d/%d samples\n", num_in, 710); int margin = 6; if (num_in < 710-margin) { @@ -962,7 +962,7 @@ int EmuThreadFunc(void* burp) // framerate limiter based off SDL2_gfx float framerate = (1000.0f * nlines) / (60.0f * 263.0f); - fpslimitcount++; + /*fpslimitcount++; u32 curtick = SDL_GetTicks(); u32 delay = curtick - lasttick; lasttick = curtick; @@ -978,6 +978,24 @@ int EmuThreadFunc(void* burp) { fpslimitcount = 0; starttick = curtick; + }*/ + + fpslimitcount++; + if (fpslimitcount >= 3) + { + u32 curtick = SDL_GetTicks(); + u32 delay = curtick - lasttick; + + bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward); + + u32 wantedtick = lasttick + (u32)((float)fpslimitcount * framerate); + if (curtick < wantedtick && limitfps) + { + SDL_Delay(wantedtick - curtick); + } + + lasttick = SDL_GetTicks(); + fpslimitcount = 0; } nframes++; From 22f3cae0677d07033289689d536f4f515ea3274d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 13 Jul 2019 02:54:14 +0200 Subject: [PATCH 04/32] fix potential out-of-bounds write --- src/GPU.cpp | 1 + src/GPU2D.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/GPU.cpp b/src/GPU.cpp index dcd79b4886..071d5f656a 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -284,6 +284,7 @@ void SetDisplaySettings(bool accel) if (Framebuffer[1][0]) delete[] Framebuffer[1][0]; if (Framebuffer[0][1]) delete[] Framebuffer[0][1]; if (Framebuffer[1][1]) delete[] Framebuffer[1][1]; + Framebuffer[0][0] = new u32[fbsize]; Framebuffer[1][0] = new u32[fbsize]; Framebuffer[0][1] = new u32[fbsize]; diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 3375d45214..8998453f35 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -753,8 +753,10 @@ void GPU2D::DrawScanline(u32 line) case 1: // regular display { - for (int i = 0; i < stride; i+=2) + int i = 0; + for (; i < (stride & ~1); i+=2) *(u64*)&dst[i] = *(u64*)&BGOBJLine[i]; + if (stride & 1) dst[i] = BGOBJLine[i]; } break; From c1fa5d8283cde76110690d15b2d127ead65d2265 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 24 Jul 2019 00:27:08 +0200 Subject: [PATCH 05/32] GPU2D: forced-blank only disables BG/OBJ compositing (VRAM/FIFO display, capture, master brightness still run) fixes #491 --- src/GPU2D.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 8998453f35..9d7ab8f3ee 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -709,10 +709,6 @@ void GPU2D::DrawScanline(u32 line) // oddly that's not the case for GPU A if (Num && !Enabled) forceblank = true; - // forced blank - // (checkme: are there still things that can run under this mode? likely not) - if (DispCnt & (1<<7)) forceblank = true; - if (forceblank) { for (int i = 0; i < 256; i++) @@ -1350,6 +1346,15 @@ void GPU2D::DrawScanlineBGMode6(u32 line) void GPU2D::DrawScanline_BGOBJ(u32 line) { + // forced blank disables BG/OBJ compositing + if (DispCnt & (1<<7)) + { + for (int i = 0; i < 256; i++) + BGOBJLine[i] = 0xFF3F3F3F; + + return; + } + u64 backdrop; if (Num) backdrop = *(u16*)&GPU::Palette[0x400]; else backdrop = *(u16*)&GPU::Palette[0]; From 3c006fd36154e48325c3cf862ed3287b265924c1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 24 Jul 2019 02:46:30 +0200 Subject: [PATCH 06/32] GPU2D: fill gaps in BG modes * mode6 actually works on the sub GPU, albeit limited to 1/4 the full bitmap size due to having only 128K of VRAM * mode7 draws BG0, BG1 and sprites. no BG2/BG3. --- src/GPU2D.cpp | 38 ++++++++++++++++++++++++++++++-------- src/GPU2D.h | 1 + 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 9d7ab8f3ee..4bba23546b 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -1316,12 +1316,6 @@ void GPU2D::DrawScanlineBGMode(u32 line) void GPU2D::DrawScanlineBGMode6(u32 line) { - if (Num) - { - printf("GPU2D: MODE6 ON SUB GPU???\n"); - return; - } - for (int i = 3; i >= 0; i--) { if ((BGCnt[2] & 0x3) == i) @@ -1335,8 +1329,36 @@ void GPU2D::DrawScanlineBGMode6(u32 line) { if (DispCnt & 0x0100) { - if (DispCnt & 0x8) + if ((!Num) && (DispCnt & 0x8)) + DrawBG_3D(); + } + } + if ((DispCnt & 0x1000) && NumSprites) + InterleaveSprites(0x8000 | (i<<16)); + } +} + +void GPU2D::DrawScanlineBGMode7(u32 line) +{ + // mode 7 only has text-mode BG0 and BG1 + + for (int i = 3; i >= 0; i--) + { + if ((BGCnt[1] & 0x3) == i) + { + if (DispCnt & 0x0200) + { + DrawBG_Text(line, 1); + } + } + if ((BGCnt[0] & 0x3) == i) + { + if (DispCnt & 0x0100) + { + if ((!Num) && (DispCnt & 0x8)) DrawBG_3D(); + else + DrawBG_Text(line, 0); } } if ((DispCnt & 0x1000) && NumSprites) @@ -1376,7 +1398,6 @@ void GPU2D::DrawScanline_BGOBJ(u32 line) else memset(WindowMask, 0xFF, 256); - // TODO: what happens in mode 7? mode 6 on the sub engine? switch (DispCnt & 0x7) { case 0: DrawScanlineBGMode<0>(line); break; @@ -1386,6 +1407,7 @@ void GPU2D::DrawScanline_BGOBJ(u32 line) case 4: DrawScanlineBGMode<4>(line); break; case 5: DrawScanlineBGMode<5>(line); break; case 6: DrawScanlineBGMode6(line); break; + case 7: DrawScanlineBGMode7(line); break; } // color special effects diff --git a/src/GPU2D.h b/src/GPU2D.h index b9a2422492..6ad97830d7 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -135,6 +135,7 @@ class GPU2D template void DrawScanlineBGMode(u32 line); void DrawScanlineBGMode6(u32 line); + void DrawScanlineBGMode7(u32 line); void DrawScanline_BGOBJ(u32 line); static void DrawPixel_Normal(u32* dst, u16 color, u32 flag); From a8886d5949780221386ed623d12039bdc8e78e36 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 24 Jul 2019 03:30:09 +0200 Subject: [PATCH 07/32] GPU2D: add 'prohibited' large BG sizes --- src/GPU2D.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 4bba23546b..fbb7fea8dd 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -2069,14 +2069,19 @@ void GPU2D::DrawBG_Large(u32 line) // BG is always BG2 u32 tilesetaddr, tilemapaddr; u16* pal; + // large BG sizes: + // 0: 512x1024 + // 1: 1024x512 + // 2: 512x256 + // 3: 512x512 u32 xmask, ymask; u32 yshift; switch (bgcnt & 0xC000) { case 0x0000: xmask = 0x1FFFF; ymask = 0x3FFFF; yshift = 9; break; case 0x4000: xmask = 0x3FFFF; ymask = 0x1FFFF; yshift = 10; break; - case 0x8000: // TODO (most likely the second size bit is just ignored) - case 0xC000: printf("bad BG size for large BG: %04X\n", bgcnt); return; + case 0x8000: xmask = 0x1FFFF; ymask = 0x0FFFF; yshift = 9; break; + case 0xC000: xmask = 0x1FFFF; ymask = 0x1FFFF; yshift = 9; break; } u32 ofxmask, ofymask; From 78ff4165edaccf995b646b095abbc63b441b7d23 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 24 Jul 2019 04:29:19 +0200 Subject: [PATCH 08/32] GPU2D: * implement reserved mode for bitmap sprites (not too interesting) * mask out DISPCNT bits that don't apply to the sub GPU --- src/GPU2D.cpp | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index fbb7fea8dd..1ce62c68f7 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -304,10 +304,22 @@ void GPU2D::Write8(u32 addr, u8 val) switch (addr & 0x00000FFF) { - case 0x000: DispCnt = (DispCnt & 0xFFFFFF00) | val; return; - case 0x001: DispCnt = (DispCnt & 0xFFFF00FF) | (val << 8); return; - case 0x002: DispCnt = (DispCnt & 0xFF00FFFF) | (val << 16); return; - case 0x003: DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24); return; + case 0x000: + DispCnt = (DispCnt & 0xFFFFFF00) | val; + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x001: + DispCnt = (DispCnt & 0xFFFF00FF) | (val << 8); + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x002: + DispCnt = (DispCnt & 0xFF00FFFF) | (val << 16); + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x003: + DispCnt = (DispCnt & 0x00FFFFFF) | (val << 24); + if (Num) DispCnt &= 0xC0B1FFF7; + return; case 0x008: BGCnt[0] = (BGCnt[0] & 0xFF00) | val; return; case 0x009: BGCnt[0] = (BGCnt[0] & 0x00FF) | (val << 8); return; @@ -386,8 +398,14 @@ 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 0x000: + DispCnt = (DispCnt & 0xFFFF0000) | val; + if (Num) DispCnt &= 0xC0B1FFF7; + return; + case 0x002: + DispCnt = (DispCnt & 0x0000FFFF) | (val << 16); + if (Num) DispCnt &= 0xC0B1FFF7; + return; case 0x008: BGCnt[0] = val; return; case 0x00A: BGCnt[1] = val; return; @@ -519,6 +537,7 @@ void GPU2D::Write32(u32 addr, u32 val) { case 0x000: DispCnt = val; + if (Num) DispCnt &= 0xC0B1FFF7; return; case 0x028: @@ -2326,8 +2345,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 { if (DispCnt & 0x20) { - // TODO ("reserved") - printf("bad reserved mode\n"); + // 'reserved' + // draws nothing + + return; } else { @@ -2559,8 +2580,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) { if (DispCnt & 0x20) { - // TODO ("reserved") - printf("bad reserved mode\n"); + // 'reserved' + // draws nothing + + return; } else { From d838c6ab4ea8a38477b50b7a5018aba5d3f927fc Mon Sep 17 00:00:00 2001 From: Roger Date: Tue, 13 Aug 2019 12:41:16 -0400 Subject: [PATCH 09/32] Use the new GitHub sponsors feature to a link to the patreon --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..bb8335987a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: staplebutter From 5998f7be5f65c259c590bc34b708eac0ea1f8b78 Mon Sep 17 00:00:00 2001 From: Lukas Wienke Date: Thu, 15 Aug 2019 23:54:20 +0200 Subject: [PATCH 10/32] add clion standatd dirs to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f63e23945a..bd1d4857d6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ obj melon_grc.c melon_grc.h cmake-build +cmake-build-debug +.idea From 6a50bcfaf70a08295db62d2a706db158853f179b Mon Sep 17 00:00:00 2001 From: Lukas Wienke Date: Thu, 15 Aug 2019 23:55:00 +0200 Subject: [PATCH 11/32] add warning message if romlist.bin is not found --- src/libui_sdl/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index a19495b1ee..38b734b8c8 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -2573,7 +2573,6 @@ int main(int argc, char** argv) SDL_Quit(); return 0; } - { FILE* f = Platform::OpenLocalFile("romlist.bin", "rb"); if (f) @@ -2590,6 +2589,13 @@ int main(int argc, char** argv) "You should use the latest version of romlist.bin (provided in melonDS release packages)."); } } + else + { + uiMsgBoxError(NULL, + "romlist.bin not found.", + "Save memory type detection will not work correctly.\n\n" + "You should use the latest version of romlist.bin (provided in melonDS release packages)."); + } } CreateMainWindowMenu(); From 626a9c13859b556a19abbf2212233a834e11f022 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 18 Aug 2019 11:31:03 +0200 Subject: [PATCH 12/32] my bad. --- src/SPU.cpp | 22 +++++++++++++++------- src/SPU.h | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index 2dfdf441f5..b25b8d0d3b 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -26,7 +26,7 @@ // * capture addition modes, overflow bugs // * channel hold // * 'length less than 4' glitch - +int brap = 0; namespace SPU { @@ -63,7 +63,7 @@ const s16 PSGTable[8][8] = const u32 kSamplesPerRun = 1; -const u32 OutputBufferSize = 2*1024; +const u32 OutputBufferSize = 2*2*1024; s16 OutputBuffer[2 * OutputBufferSize]; u32 OutputReadOffset; u32 OutputWriteOffset; @@ -101,7 +101,7 @@ void Reset() { memset(OutputBuffer, 0, 2*OutputBufferSize*2); OutputReadOffset = 0; - OutputWriteOffset = OutputBufferSize; + OutputWriteOffset = 0;//OutputBufferSize; Cnt = 0; MasterVolume = 0; @@ -579,7 +579,7 @@ void CaptureUnit::Run(s32 sample) } } - +int zog = 0, zig = 0; void Mix(u32 samples) { s32 channelbuf[32]; @@ -734,15 +734,23 @@ void Mix(u32 samples) OutputBuffer[OutputWriteOffset + 1] = r >> 1; OutputWriteOffset += 2; OutputWriteOffset &= ((2*OutputBufferSize)-1); - if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW\n"); + if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW %d\n", OutputWriteOffset>>1); + zog++; zig++; brap++; } NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*kSamplesPerRun, Mix, kSamplesPerRun); } +int GetOutputSize() +{ + return zog; // derp +} + int ReadOutput(s16* data, int samples) { + printf("ReadOutput(%d): wrote=%d level=%d ReadOffset=%d WriteOffset=%d\n", samples, zog, zig, OutputReadOffset>>1, OutputWriteOffset>>1); + zog = 0; zig -= (zigSetLoopPos(val); return; - case 0xC: chan->SetLength((chan->Length & 0xFFFF0000) | val); return; - case 0xE: chan->SetLength((chan->Length & 0x0000FFFF) | (val << 16)); return; + case 0xC: chan->SetLength(((chan->Length >> 2) & 0xFFFF0000) | val); return; + case 0xE: chan->SetLength(((chan->Length >> 2) & 0x0000FFFF) | (val << 16)); return; } } else diff --git a/src/SPU.h b/src/SPU.h index 3cd5df3499..ddd235a3a5 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -35,6 +35,7 @@ void SetBias(u16 bias); void Mix(u32 samples); +int GetOutputSize(); int ReadOutput(s16* data, int samples); u8 Read8(u32 addr); From 6c7c037b202ca0e145a47a9d8dfbf34bc8cdda7d Mon Sep 17 00:00:00 2001 From: xperia64 Date: Sat, 24 Aug 2019 11:52:24 -0400 Subject: [PATCH 13/32] Fix division edge case --- src/NDS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index 991995d229..ceeeb793d6 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1416,7 +1416,7 @@ void DivDone(u32 param) if (den == 0) { DivQuotient[0] = (num<0) ? 1:-1; - DivQuotient[1] = (num<0) ? -1:1; + DivQuotient[1] = (num<0) ? -1:0; *(s64*)&DivRemainder[0] = num; } else if (num == -0x80000000 && den == -1) From 7cb8112984172d1886d6bd7b12f0afffd1fa7229 Mon Sep 17 00:00:00 2001 From: Zapeth Date: Sun, 25 Aug 2019 18:28:54 +0200 Subject: [PATCH 14/32] Fix MinGW resource file compilation issues --- src/libui_sdl/CMakeLists.txt | 4 ++++ src/libui_sdl/libui/windows/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 63e9f484e1..b5d29d8d68 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -14,6 +14,10 @@ SET(SOURCES_LIBUI OSD.cpp ) +if (WIN32) + set(CMAKE_RC_COMPILE_OBJECT " -i -o ") +endif() + option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON) set(BUILD_SHARED_LIBS OFF) add_subdirectory(libui) diff --git a/src/libui_sdl/libui/windows/CMakeLists.txt b/src/libui_sdl/libui/windows/CMakeLists.txt index 9d5313aea6..24d4ad9663 100644 --- a/src/libui_sdl/libui/windows/CMakeLists.txt +++ b/src/libui_sdl/libui/windows/CMakeLists.txt @@ -73,7 +73,7 @@ macro(_handle_static) add_custom_command( TARGET libui POST_BUILD COMMAND - ${CMAKE_COMMAND} -E copy $/CMakeFiles/libui.dir/windows/resources.rc.* ${_LIBUI_STATIC_RES} + ${CMAKE_COMMAND} -E copy $/CMakeFiles/libui.dir/windows/resources.rc.obj ${_LIBUI_STATIC_RES} COMMENT "Copying libui.res") endmacro() From 6635ded6ec16873e7bc8f4bd7c68d97ce91fd6f2 Mon Sep 17 00:00:00 2001 From: tokumeiwokiboushimasu Date: Wed, 28 Aug 2019 22:23:26 +0900 Subject: [PATCH 15/32] Fix build error on Fedora --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ebb69fe2a..048dd44ad0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,11 @@ endif() if(ENABLE_LTO) add_compile_options(-O3 -flto) + set(CMAKE_AR "gcc-ar") + set(CMAKE_C_ARCHIVE_CREATE " qcs ") + set(CMAKE_C_ARCHIVE_FINISH true) + set(CMAKE_CXX_ARCHIVE_CREATE " qcs ") + set(CMAKE_CXX_ARCHIVE_FINISH true) endif() add_compile_options(-fno-pic) From 96d5d3f4c8ebdb887da49998522e37c329f1115f Mon Sep 17 00:00:00 2001 From: Zapeth Date: Wed, 28 Aug 2019 22:24:54 +0200 Subject: [PATCH 16/32] Fix glib-compile-resources path issues Apparently double quotes are not stripped away for assigned arguments when parsing, which causes isses for paths that include spaces. --- src/libui_sdl/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index b5d29d8d68..64206bf219 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -43,11 +43,11 @@ if (UNIX) ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) add_custom_command(OUTPUT melon_grc.c - COMMAND glib-compile-resources --sourcedir="${CMAKE_SOURCE_DIR}" - --target="${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c" + COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} + --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c --generate-source "${CMAKE_SOURCE_DIR}/melon_grc.xml" - COMMAND glib-compile-resources --sourcedir="${CMAKE_SOURCE_DIR}" - --target="${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h" + COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} + --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") if (CMAKE_SYSTEM_NAME STREQUAL "Linux") From fbad8b0f4393a41892c5da59d1ef62d0314a029b Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 29 Aug 2019 15:55:18 +0200 Subject: [PATCH 17/32] * new FPS limiter * new audio output/sync method about fucking time --- src/SPU.cpp | 47 ++++++++++++++++------ src/SPU.h | 1 + src/libui_sdl/main.cpp | 90 +++++++++++++++++++++++------------------- 3 files changed, 86 insertions(+), 52 deletions(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index b25b8d0d3b..6b594b06f5 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -26,7 +26,6 @@ // * capture addition modes, overflow bugs // * channel hold // * 'length less than 4' glitch -int brap = 0; namespace SPU { @@ -63,10 +62,10 @@ const s16 PSGTable[8][8] = const u32 kSamplesPerRun = 1; -const u32 OutputBufferSize = 2*2*1024; +const u32 OutputBufferSize = 2*1024; s16 OutputBuffer[2 * OutputBufferSize]; -u32 OutputReadOffset; -u32 OutputWriteOffset; +volatile u32 OutputReadOffset; +volatile u32 OutputWriteOffset; u16 Cnt; @@ -579,7 +578,7 @@ void CaptureUnit::Run(s32 sample) } } -int zog = 0, zig = 0; + void Mix(u32 samples) { s32 channelbuf[32]; @@ -629,7 +628,7 @@ void Mix(u32 samples) else if (val > 0x7FFF) val = 0x7FFF; Capture[0]->Run(val); - if (!((Capture[0]->Cnt & (1<<7)))) break; + if (!(Capture[0]->Cnt & (1<<7))) break; } } @@ -644,7 +643,7 @@ void Mix(u32 samples) else if (val > 0x7FFF) val = 0x7FFF; Capture[1]->Run(val); - if (!((Capture[1]->Cnt & (1<<7)))) break; + if (!(Capture[1]->Cnt & (1<<7))) break; } } @@ -735,7 +734,6 @@ void Mix(u32 samples) OutputWriteOffset += 2; OutputWriteOffset &= ((2*OutputBufferSize)-1); if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW %d\n", OutputWriteOffset>>1); - zog++; zig++; brap++; } NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*kSamplesPerRun, Mix, kSamplesPerRun); @@ -744,13 +742,40 @@ void Mix(u32 samples) int GetOutputSize() { - return zog; // derp + int ret; + if (OutputWriteOffset >= OutputReadOffset) + ret = OutputWriteOffset - OutputReadOffset; + else + ret = (OutputBufferSize*2) - OutputReadOffset + OutputWriteOffset; + + ret >>= 1; + return ret; +} + +void Sync(bool wait) +{ + // sync to audio output in case the core is running too fast + // * wait=true: wait until enough audio data has been played + // * wait=false: merely skip some audio data to avoid a FIFO overflow + + const int halflimit = (OutputBufferSize / 2); + + if (wait) + { + // TODO: less CPU-intensive wait? + while (GetOutputSize() > halflimit); + } + else if (GetOutputSize() > halflimit) + { + int readpos = OutputWriteOffset - (halflimit*2); + if (readpos < 0) readpos += (OutputBufferSize*2); + + OutputReadOffset = readpos; + } } int ReadOutput(s16* data, int samples) { - printf("ReadOutput(%d): wrote=%d level=%d ReadOffset=%d WriteOffset=%d\n", samples, zog, zig, OutputReadOffset>>1, OutputWriteOffset>>1); - zog = 0; zig -= (zig> 8; buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8; + /*s16 s_l = buf_in[res_pos*2 ]; + s16 s_r = buf_in[res_pos*2+1]; + + float a = res_timer; + float b = 1.0 - a; + s_l = (s_l * a) + (buf_in[(res_pos-1)*2 ] * b); + s_r = (s_r * a) + (buf_in[(res_pos-1)*2+1] * b); + + buf_out[i*2 ] = (s_l * volume) >> 8; + buf_out[i*2+1] = (s_r * volume) >> 8;*/ + res_timer += res_incr; while (res_timer >= 1.0) { @@ -838,6 +851,7 @@ bool JoyButtonHeld(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat) void UpdateWindowTitle(void* data) { + if (EmuStatus == 0) return; uiWindowSetTitle(MainWindow, (const char*)data); } @@ -880,6 +894,10 @@ int EmuThreadFunc(void* burp) u32 lasttick = starttick; u32 lastmeasuretick = lasttick; u32 fpslimitcount = 0; + u64 perfcount = SDL_GetPerformanceCounter(); + u64 perffreq = SDL_GetPerformanceFrequency(); + float samplesleft = 0; + u32 nsamples = 0; char melontitle[100]; while (EmuRunning != 0) @@ -959,43 +977,30 @@ int EmuThreadFunc(void* burp) } uiAreaQueueRedrawAll(MainDrawArea); - // framerate limiter based off SDL2_gfx - float framerate = (1000.0f * nlines) / (60.0f * 263.0f); - - /*fpslimitcount++; - u32 curtick = SDL_GetTicks(); - u32 delay = curtick - lasttick; - lasttick = curtick; - bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward); + SPU::Sync(limitfps); - u32 wantedtick = starttick + (u32)((float)fpslimitcount * framerate); - if (curtick < wantedtick && limitfps) - { - SDL_Delay(wantedtick - curtick); - } - else - { - fpslimitcount = 0; - starttick = curtick; - }*/ + float framerate = (1000.0f * nlines) / (60.0f * 263.0f); - fpslimitcount++; - if (fpslimitcount >= 3) { u32 curtick = SDL_GetTicks(); u32 delay = curtick - lasttick; - bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward); - - u32 wantedtick = lasttick + (u32)((float)fpslimitcount * framerate); - if (curtick < wantedtick && limitfps) + if (limitfps) { - SDL_Delay(wantedtick - curtick); + float wantedtickF = starttick + (framerate * (fpslimitcount+1)); + u32 wantedtick = (u32)ceil(wantedtickF); + if (curtick < wantedtick) SDL_Delay(wantedtick - curtick); + + lasttick = SDL_GetTicks(); + fpslimitcount++; + if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60)) + { + fpslimitcount = 0; + nsamples = 0; + starttick = lasttick; + } } - - lasttick = SDL_GetTicks(); - fpslimitcount = 0; } nframes++; @@ -2649,20 +2654,23 @@ int main(int argc, char** argv) uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); + AudioFreq = 48000; // TODO: make configurable? SDL_AudioSpec whatIwant, whatIget; memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); - whatIwant.freq = 47340; + whatIwant.freq = AudioFreq; whatIwant.format = AUDIO_S16LSB; whatIwant.channels = 2; whatIwant.samples = 1024; whatIwant.callback = AudioCallback; - AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0); + AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); if (!AudioDevice) { printf("Audio init failed: %s\n", SDL_GetError()); } else { + AudioFreq = whatIget.freq; + printf("Audio output frequency: %d Hz\n", AudioFreq); SDL_PauseAudioDevice(AudioDevice, 1); } From 455b0e568987b66e757f98869450decb94e02d28 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 1 Sep 2019 15:41:46 +0200 Subject: [PATCH 18/32] more fixes to audio output maybe by 2034 we'll finally get that shit going --- src/SPU.cpp | 17 ++++++++++++++--- src/SPU.h | 2 ++ src/libui_sdl/main.cpp | 20 ++++++++++++++++++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index 6b594b06f5..b36becf8cb 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -98,9 +98,7 @@ void DeInit() void Reset() { - memset(OutputBuffer, 0, 2*OutputBufferSize*2); - OutputReadOffset = 0; - OutputWriteOffset = 0;//OutputBufferSize; + InitOutput(); Cnt = 0; MasterVolume = 0; @@ -740,6 +738,19 @@ void Mix(u32 samples) } +void DrainOutput() +{ + OutputReadOffset = 0; + OutputWriteOffset = 0; +} + +void InitOutput() +{ + memset(OutputBuffer, 0, 2*OutputBufferSize*2); + OutputReadOffset = 0; + OutputWriteOffset = OutputBufferSize; +} + int GetOutputSize() { int ret; diff --git a/src/SPU.h b/src/SPU.h index 839b1b0b7e..7c99887b31 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -35,6 +35,8 @@ void SetBias(u16 bias); void Mix(u32 samples); +void DrainOutput(); +void InitOutput(); int GetOutputSize(); void Sync(bool wait); int ReadOutput(s16* data, int samples); diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 7d7bce0fc5..1b4a9c646e 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -159,6 +159,7 @@ int JoystickID; SDL_Joystick* Joystick; int AudioFreq; +float AudioSampleFrac; SDL_AudioDeviceID AudioDevice, MicDevice; u32 MicBufferLength = 2048; @@ -565,7 +566,10 @@ void AudioCallback(void* data, Uint8* stream, int len) // resample incoming audio to match the output sample rate - int len_in = (int)ceil((len * 32823.6328125) / (float)AudioFreq); + float f_len_in = (len * 32823.6328125) / (float)AudioFreq; + f_len_in += AudioSampleFrac; + int len_in = (int)floor(f_len_in); + AudioSampleFrac = f_len_in - len_in; s16 buf_in[1024*2]; s16* buf_out = (s16*)stream; @@ -573,6 +577,12 @@ void AudioCallback(void* data, Uint8* stream, int len) int num_in = SPU::ReadOutput(buf_in, len_in); int num_out = len; + if (num_in < 1) + { + memset(stream, 0, len*sizeof(s16)*2); + return; + } + int margin = 6; if (num_in < len_in-margin) { @@ -591,7 +601,7 @@ void AudioCallback(void* data, Uint8* stream, int len) int volume = Config::AudioVolume; - for (int i = 0; i < 1024; i++) + for (int i = 0; i < len; i++) { buf_out[i*2 ] = (buf_in[res_pos*2 ] * volume) >> 8; buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8; @@ -1522,6 +1532,8 @@ void Run() EmuRunning = 1; RunningSomething = true; + SPU::InitOutput(); + AudioSampleFrac = 0; SDL_PauseAudioDevice(AudioDevice, 0); SDL_PauseAudioDevice(MicDevice, 0); @@ -1560,6 +1572,7 @@ void TogglePause(void* blarg) EmuRunning = 2; uiMenuItemSetChecked(MenuItem_Pause, 1); + SPU::DrainOutput(); SDL_PauseAudioDevice(AudioDevice, 1); SDL_PauseAudioDevice(MicDevice, 1); @@ -1571,6 +1584,8 @@ void TogglePause(void* blarg) EmuRunning = 1; uiMenuItemSetChecked(MenuItem_Pause, 0); + SPU::InitOutput(); + AudioSampleFrac = 0; SDL_PauseAudioDevice(AudioDevice, 0); SDL_PauseAudioDevice(MicDevice, 0); @@ -1621,6 +1636,7 @@ void Stop(bool internal) uiAreaQueueRedrawAll(MainDrawArea); + SPU::DrainOutput(); SDL_PauseAudioDevice(AudioDevice, 1); SDL_PauseAudioDevice(MicDevice, 1); From f01016a30b2e8482d06798895ebc674370e81816 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 1 Sep 2019 18:35:33 +0200 Subject: [PATCH 19/32] GPU2D: shape3 sprites are always 8x8 --- src/GPU2D.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 1ce62c68f7..432eaaffec 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -2192,17 +2192,17 @@ void GPU2D::DrawSprites(u32 line) const s32 spritewidth[16] = { - 8, 16, 8, 0, - 16, 32, 8, 0, - 32, 32, 16, 0, - 64, 64, 32, 0 + 8, 16, 8, 8, + 16, 32, 8, 8, + 32, 32, 16, 8, + 64, 64, 32, 8 }; const s32 spriteheight[16] = { - 8, 8, 16, 0, - 16, 8, 32, 0, - 32, 16, 32, 0, - 64, 32, 64, 0 + 8, 8, 16, 8, + 16, 8, 32, 8, + 32, 16, 32, 8, + 64, 32, 64, 8 }; u32 nsprites = 0; From 5b5103443608d6f7e88229b1fbf8fb276b4f5f27 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 1 Sep 2019 18:38:01 +0200 Subject: [PATCH 20/32] zerp --- src/GPU2D.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 432eaaffec..288ee58131 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -2205,8 +2205,6 @@ void GPU2D::DrawSprites(u32 line) 64, 32, 64, 8 }; - u32 nsprites = 0; - for (int bgnum = 0x0C00; bgnum >= 0x0000; bgnum -= 0x0400) { for (int sprnum = 127; sprnum >= 0; sprnum--) From abb06269a1ade49f71c02d1fc2b63128f872d294 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 1 Sep 2019 20:20:22 +0200 Subject: [PATCH 21/32] add VSync toggle --- src/libui_sdl/DlgVideoSettings.cpp | 26 +++++++++++++++++++++++++- src/libui_sdl/PlatformConfig.cpp | 2 ++ src/libui_sdl/PlatformConfig.h | 1 + src/libui_sdl/main.cpp | 18 ++++++++++++++++-- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/libui_sdl/DlgVideoSettings.cpp b/src/libui_sdl/DlgVideoSettings.cpp index 7d876e242a..155fe8b8be 100644 --- a/src/libui_sdl/DlgVideoSettings.cpp +++ b/src/libui_sdl/DlgVideoSettings.cpp @@ -39,12 +39,14 @@ uiWindow* win; uiRadioButtons* rbRenderer; uiCheckbox* cbGLDisplay; +uiCheckbox* cbVSync; uiCheckbox* cbThreaded3D; uiCombobox* cbResolution; uiCheckbox* cbAntialias; int old_renderer; int old_gldisplay; +int old_vsync; int old_threaded3D; int old_resolution; int old_antialias; @@ -89,6 +91,11 @@ void RevertSettings() { Config::ScreenUseGL = old_gldisplay; } + if (old_vsync != Config::ScreenVSync) + { + Config::ScreenVSync = old_vsync; + ApplyNewSettings(4); + } if (old_usegl != new_usegl) { apply2 = true; @@ -134,17 +141,25 @@ void OnRendererChanged(uiRadioButtons* rb, void* blarg) ApplyNewSettings(2); else ApplyNewSettings(3); - + uiControlSetFocus(uiControl(win)); } void OnGLDisplayChanged(uiCheckbox* cb, void* blarg) { Config::ScreenUseGL = uiCheckboxChecked(cb); + if (Config::ScreenUseGL) uiControlEnable(uiControl(cbVSync)); + else uiControlDisable(uiControl(cbVSync)); ApplyNewSettings(2); uiControlSetFocus(uiControl(win)); } +void OnVSyncChanged(uiCheckbox* cb, void* blarg) +{ + Config::ScreenVSync = uiCheckboxChecked(cb); + ApplyNewSettings(4); +} + void OnThreaded3DChanged(uiCheckbox* cb, void* blarg) { Config::Threaded3D = uiCheckboxChecked(cb); @@ -232,6 +247,10 @@ void Open() cbGLDisplay = uiNewCheckbox("OpenGL display"); uiCheckboxOnToggled(cbGLDisplay, OnGLDisplayChanged, NULL); uiBoxAppend(in_ctrl, uiControl(cbGLDisplay), 0); + + cbVSync = uiNewCheckbox("VSync"); + uiCheckboxOnToggled(cbVSync, OnVSyncChanged, NULL); + uiBoxAppend(in_ctrl, uiControl(cbVSync), 0); } { @@ -300,17 +319,22 @@ void Open() old_renderer = Config::_3DRenderer; old_gldisplay = Config::ScreenUseGL; + old_vsync = Config::ScreenVSync; old_threaded3D = Config::Threaded3D; old_resolution = Config::GL_ScaleFactor; old_antialias = Config::GL_Antialias; uiCheckboxSetChecked(cbGLDisplay, Config::ScreenUseGL); + uiCheckboxSetChecked(cbVSync, Config::ScreenVSync); uiCheckboxSetChecked(cbThreaded3D, Config::Threaded3D); uiComboboxSetSelected(cbResolution, Config::GL_ScaleFactor-1); //uiCheckboxSetChecked(cbAntialias, Config::GL_Antialias); uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer); UpdateControls(); + if (Config::ScreenUseGL) uiControlEnable(uiControl(cbVSync)); + else uiControlDisable(uiControl(cbVSync)); + uiControlShow(uiControl(win)); } diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp index 7f45b59121..fb31ccdc57 100644 --- a/src/libui_sdl/PlatformConfig.cpp +++ b/src/libui_sdl/PlatformConfig.cpp @@ -43,6 +43,7 @@ int ScreenSizing; int ScreenFilter; int ScreenUseGL; +int ScreenVSync; int ScreenRatio; int LimitFPS; @@ -118,6 +119,7 @@ ConfigEntry PlatformConfigFile[] = {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0}, {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, + {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, {"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0}, {"LimitFPS", 0, &LimitFPS, 1, NULL, 0}, diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h index 2c59e5d9c8..2aede24ac7 100644 --- a/src/libui_sdl/PlatformConfig.h +++ b/src/libui_sdl/PlatformConfig.h @@ -54,6 +54,7 @@ extern int ScreenSizing; extern int ScreenFilter; extern int ScreenUseGL; +extern int ScreenVSync; extern int ScreenRatio; extern int LimitFPS; diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 1b4a9c646e..24febf6103 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -988,7 +988,8 @@ int EmuThreadFunc(void* burp) uiAreaQueueRedrawAll(MainDrawArea); bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward); - SPU::Sync(limitfps); + bool vsync = Config::ScreenVSync && Screen_UseGL; + SPU::Sync(limitfps || vsync); float framerate = (1000.0f * nlines) / (60.0f * 263.0f); @@ -2260,6 +2261,19 @@ void ApplyNewSettings(int type) GPU3D::InitRenderer(Screen_UseGL); if (Screen_UseGL) uiGLMakeContextCurrent(NULL); } + else if (type == 4) // vsync + { + if (Screen_UseGL) + { + uiGLMakeContextCurrent(GLContext); + uiGLSetVSync(Config::ScreenVSync); + uiGLMakeContextCurrent(NULL); + } + else + { + // TODO eventually: VSync for non-GL screen? + } + } EmuRunning = prevstatus; } @@ -2469,7 +2483,7 @@ void CreateMainWindow(bool opengl) if (opengl_good) { uiGLMakeContextCurrent(GLContext); - uiGLSetVSync(0); // TODO: make configurable? + uiGLSetVSync(Config::ScreenVSync); if (!GLScreen_Init()) opengl_good = false; if (opengl_good) { From f70ee39543e7c57ebca8c02f025798d347e3aef2 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 1 Sep 2019 20:40:55 +0200 Subject: [PATCH 22/32] =?UTF-8?q?BAHAHAHAHHHAHARKKZKFKKSLFS-*~+=C2=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- melon.rc | 8 ++++---- src/version.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/melon.rc b/melon.rc index 15535c365f..e2d8dc289e 100644 --- a/melon.rc +++ b/melon.rc @@ -6,8 +6,8 @@ //include version information in .exe, modify these values to match your needs 1 VERSIONINFO -FILEVERSION 0,8,2,0 -PRODUCTVERSION 0,8,2,0 +FILEVERSION 0,8,3,0 +PRODUCTVERSION 0,8,3,0 FILETYPE VFT_APP { BLOCK "StringFileInfo" @@ -15,14 +15,14 @@ FILETYPE VFT_APP BLOCK "040904E4" { VALUE "CompanyName", "Melon Factory of Kuribo64" - VALUE "FileVersion", "0.8.2" + VALUE "FileVersion", "0.8.3" VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon." VALUE "InternalName", "SDnolem" VALUE "LegalCopyright", "2016-2019 Arisotura & co." VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "zafkflzdasd.exe" VALUE "ProductName", "melonDS" - VALUE "ProductVersion", "0.8.2" + VALUE "ProductVersion", "0.8.3" } } BLOCK "VarFileInfo" diff --git a/src/version.h b/src/version.h index 0d71ed86fc..2e18ba91ed 100644 --- a/src/version.h +++ b/src/version.h @@ -19,7 +19,7 @@ #ifndef VERSION_H #define VERSION_H -#define MELONDS_VERSION "0.8.2" +#define MELONDS_VERSION "0.8.3" #define MELONDS_URL "http://melonds.kuribo64.net/" From a4f9187b9b06ef3babb7659bf563b809a328e6e5 Mon Sep 17 00:00:00 2001 From: StapleButter Date: Sun, 1 Sep 2019 23:04:06 +0200 Subject: [PATCH 23/32] fix bug with vsync checkbox --- src/libui_sdl/DlgVideoSettings.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libui_sdl/DlgVideoSettings.cpp b/src/libui_sdl/DlgVideoSettings.cpp index 155fe8b8be..afa735779f 100644 --- a/src/libui_sdl/DlgVideoSettings.cpp +++ b/src/libui_sdl/DlgVideoSettings.cpp @@ -137,6 +137,10 @@ void OnRendererChanged(uiRadioButtons* rb, void* blarg) UpdateControls(); bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + + if (new_usegl) uiControlEnable(uiControl(cbVSync)); + else uiControlDisable(uiControl(cbVSync)); + if (new_usegl != old_usegl) ApplyNewSettings(2); else @@ -332,8 +336,10 @@ void Open() uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer); UpdateControls(); - if (Config::ScreenUseGL) uiControlEnable(uiControl(cbVSync)); - else uiControlDisable(uiControl(cbVSync)); + if (Config::ScreenUseGL || Config::_3DRenderer != 0) + uiControlEnable(uiControl(cbVSync)); + else + uiControlDisable(uiControl(cbVSync)); uiControlShow(uiControl(win)); } From 1b40149b0a39d55ed64831050766f0b35a6f2e24 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 4 Sep 2019 15:41:42 +0200 Subject: [PATCH 24/32] blarg here, have code --- src/libui_sdl/PlatformConfig.cpp | 4 +++- src/libui_sdl/PlatformConfig.h | 1 + src/libui_sdl/main.cpp | 18 ++++++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp index fb31ccdc57..c8ec19fb6f 100644 --- a/src/libui_sdl/PlatformConfig.cpp +++ b/src/libui_sdl/PlatformConfig.cpp @@ -47,6 +47,7 @@ int ScreenVSync; int ScreenRatio; int LimitFPS; +int AudioSync; int ShowOSD; int DirectBoot; @@ -122,7 +123,8 @@ ConfigEntry PlatformConfigFile[] = {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, {"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0}, - {"LimitFPS", 0, &LimitFPS, 1, NULL, 0}, + {"LimitFPS", 0, &LimitFPS, 0, NULL, 0}, + {"AudioSync", 0, &AudioSync, 1, NULL, 0}, {"ShowOSD", 0, &ShowOSD, 1, NULL, 0}, {"DirectBoot", 0, &DirectBoot, 1, NULL, 0}, diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h index 2aede24ac7..842e72ae2f 100644 --- a/src/libui_sdl/PlatformConfig.h +++ b/src/libui_sdl/PlatformConfig.h @@ -58,6 +58,7 @@ extern int ScreenVSync; extern int ScreenRatio; extern int LimitFPS; +extern int AudioSync; extern int ShowOSD; extern int DirectBoot; diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 7fd02bb745..c4cc542961 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -93,6 +93,7 @@ uiMenuItem* MenuItem_ScreenSizing[4]; uiMenuItem* MenuItem_ScreenFilter; uiMenuItem* MenuItem_LimitFPS; +uiMenuItem* MenuItem_AudioSync; uiMenuItem* MenuItem_ShowOSD; SDL_Thread* EmuThread; @@ -2198,6 +2199,13 @@ void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg) else Config::LimitFPS = false; } +void OnSetAudioSync(uiMenuItem* item, uiWindow* window, void* blarg) +{ + int chk = uiMenuItemChecked(item); + if (chk != 0) Config::AudioSync = true; + else Config::AudioSync = false; +} + void OnSetShowOSD(uiMenuItem* item, uiWindow* window, void* blarg) { int chk = uiMenuItemChecked(item); @@ -2442,11 +2450,16 @@ void CreateMainWindowMenu() MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering"); uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL); + MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD"); + uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL); + + uiMenuAppendSeparator(menu); + MenuItem_LimitFPS = uiMenuAppendCheckItem(menu, "Limit framerate"); uiMenuItemOnClicked(MenuItem_LimitFPS, OnSetLimitFPS, NULL); - MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD"); - uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL); + MenuItem_AudioSync = uiMenuAppendCheckItem(menu, "Audio sync"); + uiMenuItemOnClicked(MenuItem_AudioSync, OnSetAudioSync, NULL); } void CreateMainWindow(bool opengl) @@ -2688,6 +2701,7 @@ int main(int argc, char** argv) uiMenuItemSetChecked(MenuItem_ScreenFilter, Config::ScreenFilter==1); uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); + uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1); uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); AudioFreq = 48000; // TODO: make configurable? From 02a6fe182c21afe68f39067318f95eacaa051484 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 4 Sep 2019 16:29:40 +0200 Subject: [PATCH 25/32] see, Arisotura, was it that hard? --- src/SPU.cpp | 10 ++++++ src/SPU.h | 1 + src/libui_sdl/DlgVideoSettings.cpp | 10 +++--- src/libui_sdl/main.cpp | 53 ++++++++++++++++++++++++++---- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index b36becf8cb..9249416336 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -738,6 +738,16 @@ void Mix(u32 samples) } +void TrimOutput() +{ + const int halflimit = (OutputBufferSize / 2); + + int readpos = OutputWriteOffset - (halflimit*2); + if (readpos < 0) readpos += (OutputBufferSize*2); + + OutputReadOffset = readpos; +} + void DrainOutput() { OutputReadOffset = 0; diff --git a/src/SPU.h b/src/SPU.h index 7c99887b31..53a8e0a317 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -35,6 +35,7 @@ void SetBias(u16 bias); void Mix(u32 samples); +void TrimOutput(); void DrainOutput(); void InitOutput(); int GetOutputSize(); diff --git a/src/libui_sdl/DlgVideoSettings.cpp b/src/libui_sdl/DlgVideoSettings.cpp index afa735779f..ff88ba8e27 100644 --- a/src/libui_sdl/DlgVideoSettings.cpp +++ b/src/libui_sdl/DlgVideoSettings.cpp @@ -94,7 +94,7 @@ void RevertSettings() if (old_vsync != Config::ScreenVSync) { Config::ScreenVSync = old_vsync; - ApplyNewSettings(4); + //ApplyNewSettings(4); } if (old_usegl != new_usegl) { @@ -137,10 +137,10 @@ void OnRendererChanged(uiRadioButtons* rb, void* blarg) UpdateControls(); bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); - + if (new_usegl) uiControlEnable(uiControl(cbVSync)); else uiControlDisable(uiControl(cbVSync)); - + if (new_usegl != old_usegl) ApplyNewSettings(2); else @@ -161,7 +161,7 @@ void OnGLDisplayChanged(uiCheckbox* cb, void* blarg) void OnVSyncChanged(uiCheckbox* cb, void* blarg) { Config::ScreenVSync = uiCheckboxChecked(cb); - ApplyNewSettings(4); + //ApplyNewSettings(4); } void OnThreaded3DChanged(uiCheckbox* cb, void* blarg) @@ -336,7 +336,7 @@ void Open() uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer); UpdateControls(); - if (Config::ScreenUseGL || Config::_3DRenderer != 0) + if (Config::ScreenUseGL || Config::_3DRenderer != 0) uiControlEnable(uiControl(cbVSync)); else uiControlDisable(uiControl(cbVSync)); diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index c4cc542961..d4afa22836 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -130,6 +130,8 @@ bool GL_ScreenSizeDirty; int GL_3DScale; +bool GL_VSyncStatus; + int ScreenGap = 0; int ScreenLayout = 0; int ScreenSizing = 0; @@ -163,6 +165,9 @@ int AudioFreq; float AudioSampleFrac; SDL_AudioDeviceID AudioDevice, MicDevice; +SDL_cond* AudioSync; +SDL_mutex* AudioSyncLock; + u32 MicBufferLength = 2048; s16 MicBuffer[2048]; u32 MicBufferReadPos, MicBufferWritePos; @@ -239,6 +244,8 @@ bool GLScreen_InitOSDShader(GLuint* shader) bool GLScreen_Init() { + GL_VSyncStatus = Config::ScreenVSync; + // TODO: consider using epoxy? if (!OpenGL_Init()) return false; @@ -301,6 +308,13 @@ void GLScreen_DeInit() void GLScreen_DrawScreen() { + bool vsync = Config::ScreenVSync && !HotkeyDown(HK_FastForward); + if (vsync != GL_VSyncStatus) + { + GL_VSyncStatus = vsync; + uiGLSetVSync(vsync); + } + float scale = uiGLGetFramebufferScale(GLContext); glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext)); @@ -575,9 +589,14 @@ void AudioCallback(void* data, Uint8* stream, int len) s16 buf_in[1024*2]; s16* buf_out = (s16*)stream; - int num_in = SPU::ReadOutput(buf_in, len_in); + int num_in; int num_out = len; + SDL_LockMutex(AudioSyncLock); + num_in = SPU::ReadOutput(buf_in, len_in); + SDL_CondSignal(AudioSync); + SDL_UnlockMutex(AudioSyncLock); + if (num_in < 1) { memset(stream, 0, len*sizeof(s16)*2); @@ -920,6 +939,7 @@ int EmuThreadFunc(void* burp) Config::LimitFPS = !Config::LimitFPS; uiQueueMain(UpdateFPSLimit, NULL); } + // TODO: similar hotkeys for video/audio sync? if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); @@ -988,9 +1008,23 @@ int EmuThreadFunc(void* burp) } uiAreaQueueRedrawAll(MainDrawArea); - bool limitfps = Config::LimitFPS && !HotkeyDown(HK_FastForward); - bool vsync = Config::ScreenVSync && Screen_UseGL; - SPU::Sync(limitfps || vsync); + bool fastforward = HotkeyDown(HK_FastForward); + + if (Config::AudioSync && !fastforward) + { + SDL_LockMutex(AudioSyncLock); + while (SPU::GetOutputSize() > 1024) + { + int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500); + if (ret == SDL_MUTEX_TIMEDOUT) break; + } + SDL_UnlockMutex(AudioSyncLock); + } + else + { + // ensure the audio FIFO doesn't overflow + //SPU::TrimOutput(); + } float framerate = (1000.0f * nlines) / (60.0f * 263.0f); @@ -998,6 +1032,7 @@ int EmuThreadFunc(void* burp) u32 curtick = SDL_GetTicks(); u32 delay = curtick - lasttick; + bool limitfps = Config::LimitFPS && !fastforward; if (limitfps) { float wantedtickF = starttick + (framerate * (fpslimitcount+1)); @@ -2269,7 +2304,7 @@ void ApplyNewSettings(int type) GPU3D::InitRenderer(Screen_UseGL); if (Screen_UseGL) uiGLMakeContextCurrent(NULL); } - else if (type == 4) // vsync + /*else if (type == 4) // vsync { if (Screen_UseGL) { @@ -2281,7 +2316,7 @@ void ApplyNewSettings(int type) { // TODO eventually: VSync for non-GL screen? } - } + }*/ EmuRunning = prevstatus; } @@ -2704,6 +2739,9 @@ int main(int argc, char** argv) uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1); uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); + AudioSync = SDL_CreateCond(); + AudioSyncLock = SDL_CreateMutex(); + AudioFreq = 48000; // TODO: make configurable? SDL_AudioSpec whatIwant, whatIget; memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); @@ -2779,6 +2817,9 @@ int main(int argc, char** argv) if (AudioDevice) SDL_CloseAudioDevice(AudioDevice); if (MicDevice) SDL_CloseAudioDevice(MicDevice); + SDL_DestroyCond(AudioSync); + SDL_DestroyMutex(AudioSyncLock); + if (MicWavBuffer) delete[] MicWavBuffer; if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); From 3efe90f78a3536bfe86931cbcf24cb88545ccc17 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 4 Sep 2019 16:40:29 +0200 Subject: [PATCH 26/32] deal with SPU FIFO overflow in a more pleasant manner --- src/SPU.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index 9249416336..9d5f04f002 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -731,7 +731,13 @@ void Mix(u32 samples) OutputBuffer[OutputWriteOffset + 1] = r >> 1; OutputWriteOffset += 2; OutputWriteOffset &= ((2*OutputBufferSize)-1); - if (OutputWriteOffset == OutputReadOffset) printf("!! SOUND FIFO OVERFLOW %d\n", OutputWriteOffset>>1); + if (OutputWriteOffset == OutputReadOffset) + { + //printf("!! SOUND FIFO OVERFLOW %d\n", OutputWriteOffset>>1); + // advance the read position too, to avoid losing the entire FIFO + OutputReadOffset += 2; + OutputReadOffset &= ((2*OutputBufferSize)-1); + } } NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*kSamplesPerRun, Mix, kSamplesPerRun); From e8f4735c7fb4d9fc142a4571e99672ca750be66b Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 4 Sep 2019 17:03:51 +0200 Subject: [PATCH 27/32] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fabcafb81..cf0afed207 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

melonDS

- +

From 0010e296bd6d5e12c93791c7481bc04430a58ab5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 5 Sep 2019 11:42:08 +0200 Subject: [PATCH 28/32] GPU2D: delay palette lookup for sprites --- src/GPU2D.cpp | 129 +++++++++++++++++++++++++++++++------------------- src/GPU2D.h | 2 +- 2 files changed, 80 insertions(+), 51 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 288ee58131..ef9be41c0b 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -1193,33 +1193,33 @@ u16* GPU2D::GetBGExtPal(u32 slot, u32 pal) return dst; } -u16* GPU2D::GetOBJExtPal(u32 pal) +u16* GPU2D::GetOBJExtPal() { - u16* dst = &OBJExtPalCache[pal << 8]; + u16* dst = OBJExtPalCache; - if (!(OBJExtPalStatus & (1< void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos) { - u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000; + u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0x40000; u32 tilenum = attrib[2] & 0x03FF; u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3); u32 xmos = 0, xmossize = 0; @@ -2337,7 +2374,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (!alpha) return; alpha++; - prio |= (0xC0000000 | (alpha << 24)); + pixelattr |= (0xC0000000 | (alpha << 24)); if (DispCnt & 0x40) { @@ -2387,7 +2424,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | prio; + else OBJLine[xpos] = color | pixelattr; } } else @@ -2414,8 +2451,8 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 ytilefactor = 0x20; } - if (spritemode == 1) prio |= 0x80000000; - else prio |= 0x10000000; + if (spritemode == 1) pixelattr |= 0x80000000; + else pixelattr |= 0x10000000; if (attrib[0] & 0x2000) { @@ -2424,13 +2461,9 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 ytilefactor <<= 5; u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; - u32 extpal = (DispCnt & 0x80000000); - - u16* pal; if (!window) { - if (extpal) pal = GetOBJExtPal(attrib[2] >> 12); - else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; } if (xmos && !(attrib[0]&0x0200)) @@ -2451,7 +2484,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } } else @@ -2473,11 +2506,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 ytilefactor <<= 5; u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; - u16* pal; if (!window) { - pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; - pal += (attrib[2] & 0xF000) >> 8; + pixelattr |= 0x1000; + pixelattr |= ((attrib[2] & 0xF000) >> 8); } if (xmos && !(attrib[0]&0x0200)) @@ -2509,7 +2541,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } } else @@ -2530,7 +2562,7 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 template void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) { - u32 prio = ((attrib[2] & 0x0C00) << 6) | 0x8000; + u32 pixelattr = ((attrib[2] & 0x0C00) << 6) | 0x40000; u32 tilenum = attrib[2] & 0x03FF; u32 spritemode = window ? 0 : ((attrib[0] >> 10) & 0x3); u32 xmos = 0, xmossize = 0; @@ -2572,7 +2604,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (!alpha) return; alpha++; - prio |= (0xC0000000 | (alpha << 24)); + pixelattr |= (0xC0000000 | (alpha << 24)); if (DispCnt & 0x40) { @@ -2625,7 +2657,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2652,7 +2684,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color & 0x8000) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = color | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2672,8 +2704,8 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) tilenum += ((ypos >> 3) * 0x20); } - if (spritemode == 1) prio |= 0x80000000; - else prio |= 0x10000000; + if (spritemode == 1) pixelattr |= 0x80000000; + else pixelattr |= 0x10000000; if (attrib[0] & 0x2000) { @@ -2682,13 +2714,9 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; pixelsaddr += ((ypos & 0x7) << 3); - u32 extpal = (DispCnt & 0x80000000); - - u16* pal; if (!window) { - if (extpal) pal = GetOBJExtPal(attrib[2] >> 12); - else pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; + if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; } if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works @@ -2712,7 +2740,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2741,7 +2769,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2757,13 +2785,14 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) u32 pixelsaddr = (Num ? 0x06600000 : 0x06400000) + tilenum; pixelsaddr += ((ypos & 0x7) << 2); - u16* pal; if (!window) { - pal = (u16*)&GPU::Palette[Num ? 0x600 : 0x200]; - pal += (attrib[2] & 0xF000) >> 8; + pixelattr |= 0x1000; + pixelattr |= ((attrib[2] & 0xF000) >> 8); } + // TODO: optimize VRAM access!! + if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works { pixelsaddr += (((width-1 - xoff) & wmask) << 2); @@ -2790,7 +2819,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; @@ -2824,7 +2853,7 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (color) { if (window) OBJWindow[xpos] = 1; - else OBJLine[xpos] = pal[color] | prio; + else OBJLine[xpos] = color | pixelattr; } xoff++; diff --git a/src/GPU2D.h b/src/GPU2D.h index 6ad97830d7..9184215fa3 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -63,7 +63,7 @@ class GPU2D void OBJExtPalDirty(); u16* GetBGExtPal(u32 slot, u32 pal); - u16* GetOBJExtPal(u32 pal); + u16* GetOBJExtPal(); private: u32 Num; From 1aaf0c33cef521b86b72110e82ba6ef7ac0581dd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 5 Sep 2019 11:49:22 +0200 Subject: [PATCH 29/32] guess who the idiot is who broke sprite extpal --- src/GPU2D.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index ef9be41c0b..9297643da1 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -2463,7 +2463,10 @@ void GPU2D::DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 if (!window) { - if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; + if (!(DispCnt & 0x80000000)) + pixelattr |= 0x1000; + else + pixelattr |= ((attrib[2] & 0xF000) >> 4); } if (xmos && !(attrib[0]&0x0200)) @@ -2716,7 +2719,10 @@ void GPU2D::DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos) if (!window) { - if (!(DispCnt & 0x80000000)) pixelattr |= 0x1000; + if (!(DispCnt & 0x80000000)) + pixelattr |= 0x1000; + else + pixelattr |= ((attrib[2] & 0xF000) >> 4); } if (attrib[1] & 0x1000) // xflip. TODO: do better? oh well for now this works From 9d376335b722c627b00061d89143c5a70ddeeb99 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 13 Sep 2019 22:43:02 +0200 Subject: [PATCH 30/32] HARK HARK HARK HARK --- melonDS.cbp | 22 +++++++++++++++++++ src/libui_sdl/MelonCap.cpp | 43 ++++++++++++++++++++++++++++++++++++++ src/libui_sdl/MelonCap.h | 34 ++++++++++++++++++++++++++++++ src/libui_sdl/main.cpp | 16 ++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 src/libui_sdl/MelonCap.cpp create mode 100644 src/libui_sdl/MelonCap.h diff --git a/melonDS.cbp b/melonDS.cbp index 0af2f4ab2a..a9a7b722bd 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -53,6 +53,22 @@
+ + @@ -143,6 +159,12 @@ + + + + diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp new file mode 100644 index 0000000000..aea187fed9 --- /dev/null +++ b/src/libui_sdl/MelonCap.cpp @@ -0,0 +1,43 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "MelonCap.h" + + +namespace MelonCap +{ + +void Init() +{ + printf("MelonCap init\n"); +} + +void DeInit() +{ + // +} + + +void Update() +{ + // +} + +} diff --git a/src/libui_sdl/MelonCap.h b/src/libui_sdl/MelonCap.h new file mode 100644 index 0000000000..1185dea0a4 --- /dev/null +++ b/src/libui_sdl/MelonCap.h @@ -0,0 +1,34 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MELONCAP_H +#define MELONCAP_H + +#include "types.h" + +namespace MelonCap +{ + +void Init(); +void DeInit(); + +void Update(); + +} + +#endif // MELONCAP_H diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index d4afa22836..13778ec9a9 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -48,6 +48,10 @@ #include "OSD.h" +#ifdef MELONCAP +#include "MelonCap.h" +#endif // MELONCAP + // savestate slot mapping // 1-8: regular slots (quick access) @@ -999,6 +1003,10 @@ int EmuThreadFunc(void* burp) // emulate u32 nlines = NDS::RunFrame(); +#ifdef MELONCAP + MelonCap::Update(); +#endif // MELONCAP + if (EmuRunning == 0) break; if (Screen_UseGL) @@ -2739,6 +2747,10 @@ int main(int argc, char** argv) uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1); uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); +#ifdef MELONCAP + MelonCap::Init(); +#endif // MELONCAP + AudioSync = SDL_CreateCond(); AudioSyncLock = SDL_CreateMutex(); @@ -2822,6 +2834,10 @@ int main(int argc, char** argv) if (MicWavBuffer) delete[] MicWavBuffer; +#ifdef MELONCAP + MelonCap::DeInit(); +#endif // MELONCAP + if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); From 1c3661f33d9ee2a0985fe0a7782c81f3ed21821d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 14 Sep 2019 01:16:38 +0200 Subject: [PATCH 31/32] BLAHAHAHAHHHH --- melonDS.cbp | 2 + src/libui_sdl/MelonCap.cpp | 299 ++++++++++++++++++++++++++++++++++++- 2 files changed, 299 insertions(+), 2 deletions(-) diff --git a/melonDS.cbp b/melonDS.cbp index a9a7b722bd..a1fd6d5d57 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -67,6 +67,8 @@ + +
diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp index aea187fed9..0383ec14ee 100644 --- a/src/libui_sdl/MelonCap.cpp +++ b/src/libui_sdl/MelonCap.cpp @@ -19,25 +19,320 @@ #include #include #include "MelonCap.h" +#include "libui/ui.h" +#include "../NDS.h" +#include "../GPU.h" + +#include +#include +#include +#include namespace MelonCap { +uiWindow* Window; +uiArea* Area; +uiAreaHandler AreaHandler; +uiDrawBitmap* WinBitmap; +bool WinBitmapInited; + +u32* WinBitmapData; + +// this crap was built from the reverse-engineering of ds_capture.exe + +GUID InterfaceClass = {0xA0B880F6, 0xD6A5, 0x4700, {0xA8, 0xEA, 0x22, 0x28, 0x2A, 0xCA, 0x55, 0x87}}; +HANDLE CapHandle; +WINUSB_INTERFACE_HANDLE CapUSBHandle; + + +void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) +{ + if (!WinBitmapInited) + { + if (WinBitmap) uiDrawFreeBitmap(WinBitmap); + + WinBitmapInited = true; + WinBitmap = uiDrawNewBitmap(params->Context, 768, 384, 0); + } + + if (!WinBitmap) return; + if (!WinBitmapData) return; + + uiRect rc = {0, 0, 768, 384}; + + uiDrawBitmapUpdate(WinBitmap, WinBitmapData); + uiDrawBitmapDraw(params->Context, WinBitmap, &rc, &rc, 0); +} + +void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt) +{ +} + +void OnAreaMouseCrossed(uiAreaHandler* handler, uiArea* area, int left) +{ +} + +void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) +{ +} + +int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) +{ + return 1; +} + +void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height) +{ +} + + void Init() { printf("MelonCap init\n"); + + // TODO: flags value!!!!! + HDEVINFO devinfo = SetupDiGetClassDevsW(&InterfaceClass, NULL, NULL, 0x12); + if (devinfo == INVALID_HANDLE_VALUE) return; + + int member = 0; + bool good = false; + for (;;) + { + SP_DEVICE_INTERFACE_DATA interfacedata; + memset(&interfacedata, 0, sizeof(interfacedata)); + interfacedata.cbSize = sizeof(interfacedata); + + BOOL ret = SetupDiEnumDeviceInterfaces(devinfo, NULL, &InterfaceClass, member, &interfacedata); + if (!ret) + { + printf("found %d interfaces\n", member); + break; + } + + DWORD requiredsize = 0; + SetupDiGetDeviceInterfaceDetailW(devinfo, &interfacedata, NULL, NULL, &requiredsize, NULL); + printf("%d: required size %d\n", member, requiredsize); + + PSP_DEVICE_INTERFACE_DETAIL_DATA_W interfacedetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new u8[requiredsize]; + interfacedetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_W); + ret = SetupDiGetDeviceInterfaceDetailW(devinfo, &interfacedata, interfacedetail, requiredsize, NULL, NULL); + if (ret) + { + printf("got interface detail: path=%S\n", interfacedetail->DevicePath); + HANDLE file = CreateFileW(interfacedetail->DevicePath, 0xC0000000, 3, NULL, 3, 0x40000080, NULL); + if (file != INVALID_HANDLE_VALUE) + { + WINUSB_INTERFACE_HANDLE usbhandle; + ret = WinUsb_Initialize(file, &usbhandle); + if (ret) + { + int val; + val = 0x1E; + WinUsb_SetPipePolicy(usbhandle, 0x00, 3, 4, &val); + val = 0x32; + WinUsb_SetPipePolicy(usbhandle, 0x82, 3, 4, &val); + val = 0x01; + WinUsb_SetPipePolicy(usbhandle, 0x82, 7, 1, &val); + + printf("looking good\n"); + good = true; + + CapHandle = file; + CapUSBHandle = usbhandle; + } + else + CloseHandle(file); + } + } + + delete[] (u8*)interfacedetail; + + if (good) break; + + member++; + } + + SetupDiDestroyDeviceInfoList(devinfo); + + + AreaHandler.Draw = OnAreaDraw; + AreaHandler.MouseEvent = OnAreaMouseEvent; + AreaHandler.MouseCrossed = OnAreaMouseCrossed; + AreaHandler.DragBroken = OnAreaDragBroken; + AreaHandler.KeyEvent = OnAreaKeyEvent; + AreaHandler.Resize = OnAreaResize; + + WinBitmapInited = false; + WinBitmapData = new u32[768*384]; + + Window = uiNewWindow("melonDS - topnotch pixel checker", 768, 384, 0, 0, 0); + Area = uiNewArea(&AreaHandler); + uiWindowSetChild(Window, uiControl(Area)); + + uiControlShow(uiControl(Window)); } void DeInit() { - // + uiControlDestroy(uiControl(Window)); + uiDrawFreeBitmap(WinBitmap); + WinBitmapInited = false; + delete[] WinBitmapData; + + WinUsb_Free(CapUSBHandle); + CloseHandle(CapHandle); } +u32 VendorIn(u8 req, u16 len, u8* buf) +{ + WINUSB_SETUP_PACKET pkt; + pkt.RequestType = 0xC0; // device to host + pkt.Request = req; + pkt.Value = 0; // ????? + pkt.Index = 0; + pkt.Length = len; + + ULONG ret = 0; + BOOL res = WinUsb_ControlTransfer(CapUSBHandle, pkt, buf, len, &ret, NULL); + if (!res) return -1; + return ret; +} + +u32 VendorOut(u8 req, u16 val, u16 len, u8* buf) +{ + WINUSB_SETUP_PACKET pkt; + pkt.RequestType = 0x40; // device to host + pkt.Request = req; + pkt.Value = val; + pkt.Index = 0; + pkt.Length = len; + + ULONG ret = 0; + BOOL res = WinUsb_ControlTransfer(CapUSBHandle, pkt, buf, len, &ret, NULL); + if (!res) return -1; + return ret; +} + +u32 BulkIn(u8* buf, u32 len) +{ + ULONG ret = 0; + BOOL res = WinUsb_ReadPipe(CapUSBHandle, 0x82, buf, len, &ret, NULL); + if (!res) return -1; + return ret; +} + + +u32 ConvertColor(u16 col) +{ + u32 b = col & 0x001F; + u32 g = (col & 0x07E0) >> 5; + u32 r = (col & 0xF800) >> 11; + + u32 ret = 0xFF000000; + ret |= ((r << 3) | (r >> 2)) << 16; + ret |= ((g << 2) | (g >> 4)) << 8; + ret |= (b << 3) | (b >> 2); + return ret; +} + +void CaptureFrame() +{ + u32 ret; + u8 derp; + u32 framelen = 256*384*2; + u16 frame[framelen/2]; + u32 framepos = 0; + u8 frameinfo[64]; + + ret = VendorOut(0x30, 0, 0, &derp); + if (ret < 0) return; + + while (framepos < framelen) + { + ret = BulkIn((u8*)&frame[framepos/2], framelen-framepos); + if (ret < 0) break; + if (ret > 0) framepos += ret; + } + + ret = VendorIn(0x30, 64, frameinfo); + if (ret < 0) return; + if ((frameinfo[0] & 0x03) != 0x03) return; + if (!frameinfo[52]) return; + + u16* in = &frame[0]; + u32* out = &WinBitmapData[256]; + + for (int y = 0; y < 384; y++) + { + u32* out = &WinBitmapData[((y/2)*768) + ((y&1)*128) + 256]; + + if (!(frameinfo[y>>3] & (1<<(y&7)))) + { + continue; + } + + for (int x = 0; x < 256/2; x++) + { + out[0] = ConvertColor(in[1]); + out[768*192] = ConvertColor(in[0]); + out++; + in += 2; + } + } +} + void Update() { - // + // melonDS output + + int frontbuf = GPU::FrontBuffer; + + u32* topbuf = GPU::Framebuffer[frontbuf][0]; + if (topbuf) + { + for (int y = 0; y < 192; y++) + { + memcpy(&WinBitmapData[y*768], &topbuf[y*256], 256*4); + } + } + + u32* botbuf = GPU::Framebuffer[frontbuf][1]; + if (botbuf) + { + for (int y = 0; y < 192; y++) + { + memcpy(&WinBitmapData[(y+192)*768], &botbuf[y*256], 256*4); + } + } + + // DS capture + + CaptureFrame(); + + // compare + + for (int y = 0; y < 384; y++) + { + for (int x = 0; x < 256; x++) + { + u32 colA = WinBitmapData[(y*768) + x + 0]; + u32 colB = WinBitmapData[(y*768) + x + 256]; + + // best we get from the capture card is RGB565 + // so we'll ignore the lower bits + const u32 mask = 0x00F8FCF8; + colA &= mask; + colB &= mask; + + if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF00FF00; + else WinBitmapData[(y*768) + x + 512] = 0xFFFF0000; + } + } + + uiAreaQueueRedrawAll(Area); } } From 20a97b79d4c37ba40ee39ae0d3ab142184c234c4 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 14 Sep 2019 01:38:46 +0200 Subject: [PATCH 32/32] make it a bit less braindead --- melonDS.cbp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/melonDS.cbp b/melonDS.cbp index a1fd6d5d57..fb42cb47bf 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -55,8 +55,8 @@