diff --git a/README.md b/README.md index 8df34df2..09216f4c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

melonDS

- +

diff --git a/melon.rc b/melon.rc index dae2772c..23e3df70 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,9,0,0 -PRODUCTVERSION 0,9,0,0 +FILEVERSION 0,9,1,0 +PRODUCTVERSION 0,9,1,0 FILETYPE VFT_APP { BLOCK "StringFileInfo" @@ -15,14 +15,14 @@ FILETYPE VFT_APP BLOCK "040904E4" { VALUE "CompanyName", "Melon Factory of Kuribo64" - VALUE "FileVersion", "0.9" + VALUE "FileVersion", "0.9.1" VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon." VALUE "InternalName", "SDnolem" VALUE "LegalCopyright", "2016-2020 Arisotura & co." VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "zafkflzdasd.exe" VALUE "ProductName", "melonDS" - VALUE "ProductVersion", "0.9" + VALUE "ProductVersion", "0.9.1" } } BLOCK "VarFileInfo" diff --git a/src/ARCodeFile.h b/src/ARCodeFile.h index 374c56e5..56dfff7c 100644 --- a/src/ARCodeFile.h +++ b/src/ARCodeFile.h @@ -23,23 +23,21 @@ #include "types.h" -typedef struct +struct ARCode { char Name[128]; bool Enabled; u32 CodeLen; u32 Code[2*64]; - -} ARCode; +}; typedef std::list ARCodeList; -typedef struct +struct ARCodeCat { char Name[128]; ARCodeList Codes; - -} ARCodeCat; +}; typedef std::list ARCodeCatList; diff --git a/src/ARMJIT_A64/ARMJIT_Linkage.S b/src/ARMJIT_A64/ARMJIT_Linkage.S index 78863155..58b53999 100644 --- a/src/ARMJIT_A64/ARMJIT_Linkage.S +++ b/src/ARMJIT_A64/ARMJIT_Linkage.S @@ -8,8 +8,13 @@ .p2align 4,,15 +#ifdef __APPLE__ +.global _ARM_Dispatch +_ARM_Dispatch: +#else .global ARM_Dispatch ARM_Dispatch: +#endif stp x19, x20, [sp, #-96]! stp x21, x22, [sp, #16] stp x23, x24, [sp, #32] @@ -25,8 +30,13 @@ ARM_Dispatch: .p2align 4,,15 +#ifdef __APPLE__ +.global _ARM_Ret +_ARM_Ret: +#else .global ARM_Ret ARM_Ret: +#endif str RCycles, [RCPU, ARM_Cycles_offset] str RCPSR, [RCPU, ARM_CPSR_offset] @@ -65,4 +75,4 @@ ARM_RestoreContext: ldp x17, x18, [sp, #248] mov sp, x17 - br x18 \ No newline at end of file + br x18 diff --git a/src/Config.h b/src/Config.h index 9fd7488b..9671f16d 100644 --- a/src/Config.h +++ b/src/Config.h @@ -26,7 +26,7 @@ namespace Config { -typedef struct +struct ConfigEntry { char Name[32]; int Type; @@ -34,8 +34,7 @@ typedef struct int DefaultInt; const char* DefaultStr; int StrLength; // should be set to actual array length minus one - -} ConfigEntry; +}; FILE* GetConfigFile(const char* fileName, const char* permissions); bool HasConfigFile(const char* fileName); diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 8f5c3f3f..9153e907 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -38,8 +38,8 @@ bool OutputFlush; u32 InputDMASize, OutputDMASize; u32 AESMode; -FIFO* InputFIFO; -FIFO* OutputFIFO; +FIFO InputFIFO; +FIFO OutputFIFO; u8 IV[16]; @@ -91,9 +91,6 @@ void ROL16(u8* val, u32 n) bool Init() { - InputFIFO = new FIFO(16); - OutputFIFO = new FIFO(16); - const u8 zero[16] = {0}; AES_init_ctx_iv(&Ctx, zero, zero); @@ -102,8 +99,6 @@ bool Init() void DeInit() { - delete InputFIFO; - delete OutputFIFO; } void Reset() @@ -119,8 +114,8 @@ void Reset() OutputDMASize = 0; AESMode = 0; - InputFIFO->Clear(); - OutputFIFO->Clear(); + InputFIFO.Clear(); + OutputFIFO.Clear(); memset(IV, 0, sizeof(IV)); @@ -164,10 +159,10 @@ void ProcessBlock_CCM_Decrypt() u8 data[16]; u8 data_rev[16]; - *(u32*)&data[0] = InputFIFO->Read(); - *(u32*)&data[4] = InputFIFO->Read(); - *(u32*)&data[8] = InputFIFO->Read(); - *(u32*)&data[12] = InputFIFO->Read(); + *(u32*)&data[0] = InputFIFO.Read(); + *(u32*)&data[4] = InputFIFO.Read(); + *(u32*)&data[8] = InputFIFO.Read(); + *(u32*)&data[12] = InputFIFO.Read(); //printf("AES-CCM: "); _printhex2(data, 16); @@ -181,10 +176,10 @@ void ProcessBlock_CCM_Decrypt() //printf(" -> "); _printhex2(data, 16); - OutputFIFO->Write(*(u32*)&data[0]); - OutputFIFO->Write(*(u32*)&data[4]); - OutputFIFO->Write(*(u32*)&data[8]); - OutputFIFO->Write(*(u32*)&data[12]); + OutputFIFO.Write(*(u32*)&data[0]); + OutputFIFO.Write(*(u32*)&data[4]); + OutputFIFO.Write(*(u32*)&data[8]); + OutputFIFO.Write(*(u32*)&data[12]); } void ProcessBlock_CCM_Encrypt() @@ -192,10 +187,10 @@ void ProcessBlock_CCM_Encrypt() u8 data[16]; u8 data_rev[16]; - *(u32*)&data[0] = InputFIFO->Read(); - *(u32*)&data[4] = InputFIFO->Read(); - *(u32*)&data[8] = InputFIFO->Read(); - *(u32*)&data[12] = InputFIFO->Read(); + *(u32*)&data[0] = InputFIFO.Read(); + *(u32*)&data[4] = InputFIFO.Read(); + *(u32*)&data[8] = InputFIFO.Read(); + *(u32*)&data[12] = InputFIFO.Read(); //printf("AES-CCM: "); _printhex2(data, 16); @@ -209,10 +204,10 @@ void ProcessBlock_CCM_Encrypt() //printf(" -> "); _printhex2(data, 16); - OutputFIFO->Write(*(u32*)&data[0]); - OutputFIFO->Write(*(u32*)&data[4]); - OutputFIFO->Write(*(u32*)&data[8]); - OutputFIFO->Write(*(u32*)&data[12]); + OutputFIFO.Write(*(u32*)&data[0]); + OutputFIFO.Write(*(u32*)&data[4]); + OutputFIFO.Write(*(u32*)&data[8]); + OutputFIFO.Write(*(u32*)&data[12]); } void ProcessBlock_CTR() @@ -220,10 +215,10 @@ void ProcessBlock_CTR() u8 data[16]; u8 data_rev[16]; - *(u32*)&data[0] = InputFIFO->Read(); - *(u32*)&data[4] = InputFIFO->Read(); - *(u32*)&data[8] = InputFIFO->Read(); - *(u32*)&data[12] = InputFIFO->Read(); + *(u32*)&data[0] = InputFIFO.Read(); + *(u32*)&data[4] = InputFIFO.Read(); + *(u32*)&data[8] = InputFIFO.Read(); + *(u32*)&data[12] = InputFIFO.Read(); //printf("AES-CTR: "); _printhex2(data, 16); @@ -233,10 +228,10 @@ void ProcessBlock_CTR() //printf(" -> "); _printhex(data, 16); - OutputFIFO->Write(*(u32*)&data[0]); - OutputFIFO->Write(*(u32*)&data[4]); - OutputFIFO->Write(*(u32*)&data[8]); - OutputFIFO->Write(*(u32*)&data[12]); + OutputFIFO.Write(*(u32*)&data[0]); + OutputFIFO.Write(*(u32*)&data[4]); + OutputFIFO.Write(*(u32*)&data[8]); + OutputFIFO.Write(*(u32*)&data[12]); } @@ -244,8 +239,8 @@ u32 ReadCnt() { u32 ret = Cnt; - ret |= InputFIFO->Level(); - ret |= (OutputFIFO->Level() << 5); + ret |= InputFIFO.Level(); + ret |= (OutputFIFO.Level() << 5); return ret; } @@ -341,9 +336,9 @@ void WriteBlkCnt(u32 val) u32 ReadOutputFIFO() { - if (OutputFIFO->IsEmpty()) printf("!!! AES OUTPUT FIFO EMPTY\n"); + if (OutputFIFO.IsEmpty()) printf("!!! AES OUTPUT FIFO EMPTY\n"); - u32 ret = OutputFIFO->Read(); + u32 ret = OutputFIFO.Read(); if (Cnt & (1<<31)) { @@ -352,17 +347,17 @@ u32 ReadOutputFIFO() } else { - if (OutputFIFO->Level() > 0) + if (OutputFIFO.Level() > 0) DSi::CheckNDMAs(1, 0x2B); else DSi::StopNDMAs(1, 0x2B); - if (OutputMACDue && OutputFIFO->Level() <= 12) + if (OutputMACDue && OutputFIFO.Level() <= 12) { - OutputFIFO->Write(*(u32*)&OutputMAC[0]); - OutputFIFO->Write(*(u32*)&OutputMAC[4]); - OutputFIFO->Write(*(u32*)&OutputMAC[8]); - OutputFIFO->Write(*(u32*)&OutputMAC[12]); + OutputFIFO.Write(*(u32*)&OutputMAC[0]); + OutputFIFO.Write(*(u32*)&OutputMAC[4]); + OutputFIFO.Write(*(u32*)&OutputMAC[8]); + OutputFIFO.Write(*(u32*)&OutputMAC[12]); OutputMACDue = false; } } @@ -374,9 +369,9 @@ void WriteInputFIFO(u32 val) { // TODO: add some delay to processing - if (InputFIFO->IsFull()) printf("!!! AES INPUT FIFO FULL\n"); + if (InputFIFO.IsFull()) printf("!!! AES INPUT FIFO FULL\n"); - InputFIFO->Write(val); + InputFIFO.Write(val); if (!(Cnt & (1<<31))) return; @@ -387,7 +382,7 @@ void CheckInputDMA() { if (RemBlocks == 0) return; - if (InputFIFO->Level() <= InputDMASize) + if (InputFIFO.Level() <= InputDMASize) { // trigger input DMA DSi::CheckNDMAs(1, 0x2A); @@ -398,7 +393,7 @@ void CheckInputDMA() void CheckOutputDMA() { - if (OutputFIFO->Level() >= OutputDMASize) + if (OutputFIFO.Level() >= OutputDMASize) { // trigger output DMA DSi::CheckNDMAs(1, 0x2B); @@ -407,7 +402,7 @@ void CheckOutputDMA() void Update() { - while (InputFIFO->Level() >= 4 && OutputFIFO->Level() <= 12 && RemBlocks > 0) + while (InputFIFO.Level() >= 4 && OutputFIFO.Level() <= 12 && RemBlocks > 0) { switch (AESMode) { @@ -463,7 +458,7 @@ void Update() if (Cnt & (1<<30)) NDS::SetIRQ2(NDS::IRQ2_DSi_AES); DSi::StopNDMAs(1, 0x2A); - if (OutputFIFO->Level() > 0) + if (!OutputFIFO.IsEmpty()) DSi::CheckNDMAs(1, 0x2B); else DSi::StopNDMAs(1, 0x2B); diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp index 79cfe3fd..cfb3b8dd 100644 --- a/src/DSi_Camera.cpp +++ b/src/DSi_Camera.cpp @@ -303,7 +303,7 @@ u8 DSi_Camera::Read8(u32 addr) } u16 DSi_Camera::Read16(u32 addr) -{printf("CAM READ %08X %08X\n", addr, NDS::GetPC(0)); +{ switch (addr) { case 0x04004200: return ModuleCnt; @@ -313,15 +313,16 @@ u16 DSi_Camera::Read16(u32 addr) printf("unknown DSi cam read16 %08X\n", addr); return 0; } -u32 dorp = 0; + u32 DSi_Camera::Read32(u32 addr) { switch (addr) { case 0x04004204: { + // TODO return 0xFC00801F; - if (!(Cnt & (1<<15))) return 0; // CHECKME + /*if (!(Cnt & (1<<15))) return 0; // CHECKME u32 ret = *(u32*)&FrameBuffer[TransferPos]; TransferPos += 4; if (TransferPos >= FrameLength) TransferPos = 0; @@ -332,7 +333,7 @@ u32 DSi_Camera::Read32(u32 addr) dorp = 0; Cnt &= ~(1<<4); } - return ret; + return ret;*/ } } @@ -348,7 +349,7 @@ void DSi_Camera::Write8(u32 addr, u8 val) } void DSi_Camera::Write16(u32 addr, u16 val) -{printf("CAM WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(0)); +{ switch (addr) { case 0x04004200: diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 54719cf7..8b659319 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -116,18 +116,20 @@ const u8 CIS1[256] = DSi_NWifi* Ctx = nullptr; -DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) +DSi_NWifi::DSi_NWifi(DSi_SDHost* host) + : DSi_SDDevice(host), + Mailbox + { + // HACK + // the mailboxes are supposed to be 0x80 bytes + // however, as we do things instantly, emulating this is meaningless + // and only adds complication + DynamicFIFO(0x600), DynamicFIFO(0x600), DynamicFIFO(0x600), DynamicFIFO(0x600), + DynamicFIFO(0x600), DynamicFIFO(0x600), DynamicFIFO(0x600), DynamicFIFO(0x600), + // mailbox 8: extra mailbox acting as a bigger RX buffer + DynamicFIFO(0x8000) + } { - // HACK - // the mailboxes are supposed to be 0x80 bytes - // however, as we do things instantly, emulating this is meaningless - // and only adds complication - for (int i = 0; i < 8; i++) - Mailbox[i] = new FIFO(0x600);//0x80); - - // extra mailbox acting as a bigger RX buffer - Mailbox[8] = new FIFO(0x8000); - // this seems to control whether the firmware upload is done EEPROMReady = 0; @@ -136,9 +138,6 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) DSi_NWifi::~DSi_NWifi() { - for (int i = 0; i < 9; i++) - delete Mailbox[i]; - NDS::CancelEvent(NDS::Event_DSi_NWifi); Ctx = nullptr; } @@ -159,7 +158,7 @@ void DSi_NWifi::Reset() WindowWriteAddr = 0; for (int i = 0; i < 9; i++) - Mailbox[i]->Clear(); + Mailbox[i].Clear(); u8* mac = SPI_Firmware::GetWifiMAC(); printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -250,10 +249,10 @@ void DSi_NWifi::UpdateIRQ_F1() { F1_IRQStatus = 0; - if (!Mailbox[4]->IsEmpty()) F1_IRQStatus |= (1<<0); - if (!Mailbox[5]->IsEmpty()) F1_IRQStatus |= (1<<1); - if (!Mailbox[6]->IsEmpty()) F1_IRQStatus |= (1<<2); - if (!Mailbox[7]->IsEmpty()) F1_IRQStatus |= (1<<3); + if (!Mailbox[4].IsEmpty()) F1_IRQStatus |= (1<<0); + if (!Mailbox[5].IsEmpty()) F1_IRQStatus |= (1<<1); + if (!Mailbox[6].IsEmpty()) F1_IRQStatus |= (1<<2); + if (!Mailbox[7].IsEmpty()) F1_IRQStatus |= (1<<3); if (F1_IRQStatus_Counter & F1_IRQEnable_Counter) F1_IRQStatus |= (1<<4); if (F1_IRQStatus_CPU & F1_IRQEnable_CPU) F1_IRQStatus |= (1<<6); if (F1_IRQStatus_Error & F1_IRQEnable_Error) F1_IRQStatus |= (1<<7); @@ -337,26 +336,26 @@ u8 DSi_NWifi::F1_Read(u32 addr) { if (addr < 0x100) { - u8 ret = Mailbox[4]->Read(); + u8 ret = Mailbox[4].Read(); if (addr == 0xFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } else if (addr < 0x200) { - u8 ret = Mailbox[5]->Read(); + u8 ret = Mailbox[5].Read(); UpdateIRQ_F1(); return ret; } else if (addr < 0x300) { - u8 ret = Mailbox[6]->Read(); + u8 ret = Mailbox[6].Read(); UpdateIRQ_F1(); return ret; } else if (addr < 0x400) { - u8 ret = Mailbox[7]->Read(); + u8 ret = Mailbox[7].Read(); UpdateIRQ_F1(); return ret; } @@ -373,18 +372,18 @@ u8 DSi_NWifi::F1_Read(u32 addr) { u8 ret = 0; - if (Mailbox[4]->Level() >= 4) ret |= (1<<0); - if (Mailbox[5]->Level() >= 4) ret |= (1<<1); - if (Mailbox[6]->Level() >= 4) ret |= (1<<2); - if (Mailbox[7]->Level() >= 4) ret |= (1<<3); + if (Mailbox[4].Level() >= 4) ret |= (1<<0); + if (Mailbox[5].Level() >= 4) ret |= (1<<1); + if (Mailbox[6].Level() >= 4) ret |= (1<<2); + if (Mailbox[7].Level() >= 4) ret |= (1<<3); return ret; } - case 0x00408: return Mailbox[4]->Peek(0); - case 0x00409: return Mailbox[4]->Peek(1); - case 0x0040A: return Mailbox[4]->Peek(2); - case 0x0040B: return Mailbox[4]->Peek(3); + case 0x00408: return Mailbox[4].Peek(0); + case 0x00409: return Mailbox[4].Peek(1); + case 0x0040A: return Mailbox[4].Peek(2); + case 0x0040B: return Mailbox[4].Peek(3); case 0x00418: return F1_IRQEnable; case 0x00419: return F1_IRQEnable_CPU; @@ -403,32 +402,32 @@ u8 DSi_NWifi::F1_Read(u32 addr) } else if (addr < 0x1000) { - u8 ret = Mailbox[4]->Read(); + u8 ret = Mailbox[4].Read(); if (addr == 0xFFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } else if (addr < 0x1800) { - u8 ret = Mailbox[5]->Read(); + u8 ret = Mailbox[5].Read(); UpdateIRQ_F1(); return ret; } else if (addr < 0x2000) { - u8 ret = Mailbox[6]->Read(); + u8 ret = Mailbox[6].Read(); UpdateIRQ_F1(); return ret; } else if (addr < 0x2800) { - u8 ret = Mailbox[7]->Read(); + u8 ret = Mailbox[7].Read(); UpdateIRQ_F1(); return ret; } else { - u8 ret = Mailbox[4]->Read(); + u8 ret = Mailbox[4].Read(); if (addr == 0x3FFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; @@ -442,30 +441,30 @@ void DSi_NWifi::F1_Write(u32 addr, u8 val) { if (addr < 0x100) { - if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); - Mailbox[0]->Write(val); + if (Mailbox[0].IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); + Mailbox[0].Write(val); if (addr == 0xFF) HandleCommand(); UpdateIRQ_F1(); return; } else if (addr < 0x200) { - if (Mailbox[1]->IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); - Mailbox[1]->Write(val); + if (Mailbox[1].IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); + Mailbox[1].Write(val); UpdateIRQ_F1(); return; } else if (addr < 0x300) { - if (Mailbox[2]->IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); - Mailbox[2]->Write(val); + if (Mailbox[2].IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); + Mailbox[2].Write(val); UpdateIRQ_F1(); return; } else if (addr < 0x400) { - if (Mailbox[3]->IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); - Mailbox[3]->Write(val); + if (Mailbox[3].IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); + Mailbox[3].Write(val); UpdateIRQ_F1(); return; } @@ -505,37 +504,37 @@ void DSi_NWifi::F1_Write(u32 addr, u8 val) } else if (addr < 0x1000) { - if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); - Mailbox[0]->Write(val); + if (Mailbox[0].IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); + Mailbox[0].Write(val); if (addr == 0xFFF) HandleCommand(); UpdateIRQ_F1(); return; } else if (addr < 0x1800) { - if (Mailbox[1]->IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); - Mailbox[1]->Write(val); + if (Mailbox[1].IsFull()) printf("!!! NWIFI: MBOX1 FULL\n"); + Mailbox[1].Write(val); UpdateIRQ_F1(); return; } else if (addr < 0x2000) { - if (Mailbox[2]->IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); - Mailbox[2]->Write(val); + if (Mailbox[2].IsFull()) printf("!!! NWIFI: MBOX2 FULL\n"); + Mailbox[2].Write(val); UpdateIRQ_F1(); return; } else if (addr < 0x2800) { - if (Mailbox[3]->IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); - Mailbox[3]->Write(val); + if (Mailbox[3].IsFull()) printf("!!! NWIFI: MBOX3 FULL\n"); + Mailbox[3].Write(val); UpdateIRQ_F1(); return; } else { - if (Mailbox[0]->IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); - Mailbox[0]->Write(val); + if (Mailbox[0].IsFull()) printf("!!! NWIFI: MBOX0 FULL\n"); + Mailbox[0].Write(val); if (addr == 0x3FFF) HandleCommand(); // CHECKME UpdateIRQ_F1(); return; @@ -750,7 +749,7 @@ void DSi_NWifi::BMI_Command() for (int i = 0; i < len; i++) { - u8 val = Mailbox[0]->Read(); + u8 val = Mailbox[0].Read(); // TODO: do something with it!! } @@ -804,7 +803,7 @@ void DSi_NWifi::BMI_Command() for (int i = 0; i < len; i++) { - u8 val = Mailbox[0]->Read(); + u8 val = Mailbox[0].Read(); // TODO: do something with it!! //fwrite(&val, 1, 1, f); @@ -873,7 +872,7 @@ void DSi_NWifi::HTC_Command() printf("unknown HTC command %04X\n", cmd); for (int i = 0; i < len; i++) { - printf("%02X ", Mailbox[0]->Read()); + printf("%02X ", Mailbox[0].Read()); if ((i&0xF)==0xF) printf("\n"); } printf("\n"); @@ -926,7 +925,7 @@ void DSi_NWifi::WMI_Command() case 0x0004: // synchronize { - Mailbox[0]->Read(); + Mailbox[0].Read(); // TODO?? } break; @@ -944,8 +943,8 @@ void DSi_NWifi::WMI_Command() u32 legacy = MB_Read32(0); u32 scantime = MB_Read32(0); u32 forceinterval = MB_Read32(0); - u8 scantype = Mailbox[0]->Read(); - u8 nchannels = Mailbox[0]->Read(); + u8 scantype = Mailbox[0].Read(); + u8 nchannels = Mailbox[0].Read(); printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n", forcefg, legacy, scantime, forceinterval, scantype, nchannels); @@ -969,10 +968,10 @@ void DSi_NWifi::WMI_Command() case 0x0009: // set BSS filter { // TODO: do something with the params!! - u8 bssfilter = Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + u8 bssfilter = Mailbox[0].Read(); + Mailbox[0].Read(); + Mailbox[0].Read(); + Mailbox[0].Read(); u32 iemask = MB_Read32(0); printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask); @@ -981,13 +980,13 @@ void DSi_NWifi::WMI_Command() case 0x000A: // set probed BSSID { - u8 id = Mailbox[0]->Read(); - u8 flags = Mailbox[0]->Read(); - u8 len = Mailbox[0]->Read(); + u8 id = Mailbox[0].Read(); + u8 flags = Mailbox[0].Read(); + u8 len = Mailbox[0].Read(); char ssid[33] = {0}; for (int i = 0; i < len && i < 32; i++) - ssid[i] = Mailbox[0]->Read(); + ssid[i] = Mailbox[0].Read(); // TODO: store it somewhere printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); @@ -996,7 +995,7 @@ void DSi_NWifi::WMI_Command() case 0x000D: // set disconnect timeout { - Mailbox[0]->Read(); + Mailbox[0].Read(); // TODO?? } break; @@ -1018,10 +1017,10 @@ void DSi_NWifi::WMI_Command() case 0x0011: // set channel params { - Mailbox[0]->Read(); - u8 scan = Mailbox[0]->Read(); - u8 phymode = Mailbox[0]->Read(); - u8 len = Mailbox[0]->Read(); + Mailbox[0].Read(); + u8 scan = Mailbox[0].Read(); + u8 phymode = Mailbox[0].Read(); + u8 len = Mailbox[0].Read(); u16 channels[32]; for (int i = 0; i < len && i < 32; i++) @@ -1037,13 +1036,13 @@ void DSi_NWifi::WMI_Command() case 0x0012: // set power mode { - Mailbox[0]->Read(); + Mailbox[0].Read(); // TODO?? } break; case 0x0017: // dummy? - Mailbox[0]->Read(); + Mailbox[0].Read(); break; case 0x0022: // set error bitmask @@ -1080,14 +1079,14 @@ void DSi_NWifi::WMI_Command() case 0x003D: // set keepalive interval { - Mailbox[0]->Read(); + Mailbox[0].Read(); // TODO?? } break; case 0x0041: // 'WMI_SET_WSC_STATUS_CMD' { - Mailbox[0]->Read(); + Mailbox[0].Read(); // TODO?? } break; @@ -1102,8 +1101,8 @@ void DSi_NWifi::WMI_Command() { MB_Read32(0); MB_Read32(0); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + Mailbox[0].Read(); + Mailbox[0].Read(); } break; @@ -1116,9 +1115,9 @@ void DSi_NWifi::WMI_Command() case 0xF000: // set bitrate { // TODO! - Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + Mailbox[0].Read(); + Mailbox[0].Read(); + Mailbox[0].Read(); } break; @@ -1126,7 +1125,7 @@ void DSi_NWifi::WMI_Command() printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2); for (int i = 0; i < len-2; i++) { - printf("%02X ", Mailbox[0]->Read()); + printf("%02X ", Mailbox[0].Read()); if ((i&0xF)==0xF) printf("\n"); } printf("\n"); @@ -1142,18 +1141,18 @@ void DSi_NWifi::WMI_Command() void DSi_NWifi::WMI_ConnectToNetwork() { - u8 type = Mailbox[0]->Read(); - u8 auth11 = Mailbox[0]->Read(); - u8 auth = Mailbox[0]->Read(); - u8 pCryptoType = Mailbox[0]->Read(); - u8 pCryptoLen = Mailbox[0]->Read(); - u8 gCryptoType = Mailbox[0]->Read(); - u8 gCryptoLen = Mailbox[0]->Read(); - u8 ssidLen = Mailbox[0]->Read(); + u8 type = Mailbox[0].Read(); + u8 auth11 = Mailbox[0].Read(); + u8 auth = Mailbox[0].Read(); + u8 pCryptoType = Mailbox[0].Read(); + u8 pCryptoLen = Mailbox[0].Read(); + u8 gCryptoType = Mailbox[0].Read(); + u8 gCryptoLen = Mailbox[0].Read(); + u8 ssidLen = Mailbox[0].Read(); char ssid[33] = {0}; for (int i = 0; i < 32; i++) - ssid[i] = Mailbox[0]->Read(); + ssid[i] = Mailbox[0].Read(); if (ssidLen <= 32) ssid[ssidLen] = '\0'; @@ -1219,11 +1218,11 @@ void DSi_NWifi::WMI_SendPacket(u16 len) { printf("WMI: data sync\n"); - /*Mailbox[8]->Write(2); // eid - Mailbox[8]->Write(0x00); // flags + /*Mailbox[8].Write(2); // eid + Mailbox[8].Write(0x00); // flags MB_Write16(8, 2); // data length - Mailbox[8]->Write(0); // - Mailbox[8]->Write(0); // + Mailbox[8].Write(0); // + Mailbox[8].Write(0); // MB_Write16(8, 0x0200); // DrainRXBuffer();*/ @@ -1235,7 +1234,7 @@ void DSi_NWifi::WMI_SendPacket(u16 len) printf("WMI: special frame %04X len=%d\n", hdr, len); for (int i = 0; i < len-2; i++) { - printf("%02X ", Mailbox[0]->Read()); + printf("%02X ", Mailbox[0].Read()); if ((i&0xF)==0xF) printf("\n"); } printf("\n"); @@ -1279,7 +1278,7 @@ void DSi_NWifi::WMI_SendPacket(u16 len) *(u16*)&LANBuffer[12] = ethertype; // type for (int i = 0; i < lan_len-14; i++) { - LANBuffer[14+i] = Mailbox[0]->Read(); + LANBuffer[14+i] = Mailbox[0].Read(); } /*for (int i = 0; i < lan_len; i++) @@ -1294,73 +1293,73 @@ void DSi_NWifi::WMI_SendPacket(u16 len) void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len) { - if (!Mailbox[8]->CanFit(6+len+2+8)) + if (!Mailbox[8].CanFit(6+len+2+8)) { printf("NWifi: !! not enough space in RX buffer for WMI event %04X\n", id); return; } - Mailbox[8]->Write(ep); // eid - Mailbox[8]->Write(0x02); // flags (trailer) + Mailbox[8].Write(ep); // eid + Mailbox[8].Write(0x02); // flags (trailer) MB_Write16(8, len+2+8); // data length (plus event ID and trailer) - Mailbox[8]->Write(8); // trailer length - Mailbox[8]->Write(0); // + Mailbox[8].Write(8); // trailer length + Mailbox[8].Write(0); // MB_Write16(8, id); // event ID for (int i = 0; i < len; i++) { - Mailbox[8]->Write(data[i]); + Mailbox[8].Write(data[i]); } // trailer - Mailbox[8]->Write(0x02); - Mailbox[8]->Write(0x06); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); + Mailbox[8].Write(0x02); + Mailbox[8].Write(0x06); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); DrainRXBuffer(); } void DSi_NWifi::SendWMIAck(u8 ep) { - if (!Mailbox[8]->CanFit(6+12)) + if (!Mailbox[8].CanFit(6+12)) { printf("NWifi: !! not enough space in RX buffer for WMI ack (ep #%d)\n", ep); return; } - Mailbox[8]->Write(0); // eid - Mailbox[8]->Write(0x02); // flags (trailer) + Mailbox[8].Write(0); // eid + Mailbox[8].Write(0x02); // flags (trailer) MB_Write16(8, 0xC); // data length (plus trailer) - Mailbox[8]->Write(0xC); // trailer length - Mailbox[8]->Write(0); // + Mailbox[8].Write(0xC); // trailer length + Mailbox[8].Write(0); // // credit report - Mailbox[8]->Write(0x01); - Mailbox[8]->Write(0x02); - Mailbox[8]->Write(ep); - Mailbox[8]->Write(0x01); + Mailbox[8].Write(0x01); + Mailbox[8].Write(0x02); + Mailbox[8].Write(ep); + Mailbox[8].Write(0x01); // lookahead - Mailbox[8]->Write(0x02); - Mailbox[8]->Write(0x06); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); - Mailbox[8]->Write(0x00); + Mailbox[8].Write(0x02); + Mailbox[8].Write(0x06); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); + Mailbox[8].Write(0x00); DrainRXBuffer(); } void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) { - if (!Mailbox[8]->CanFit(6+len+2+16)) + if (!Mailbox[8].CanFit(6+len+2+16)) { printf("NWifi: !! not enough space in RX buffer for WMI BSSINFO event\n"); return; @@ -1369,16 +1368,16 @@ void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) // TODO: check when version>=2 frame type is used? // I observed the version<2 variant on my DSi - Mailbox[8]->Write(1); // eid - Mailbox[8]->Write(0x00); // flags + Mailbox[8].Write(1); // eid + Mailbox[8].Write(0x00); // flags MB_Write16(8, len+2+16); // data length (plus event ID and trailer) - Mailbox[8]->Write(0xFF); // trailer length - Mailbox[8]->Write(0xFF); // + Mailbox[8].Write(0xFF); // trailer length + Mailbox[8].Write(0xFF); // MB_Write16(8, 0x1004); // event ID MB_Write16(8, 2437); // channel (6) (checkme!) - Mailbox[8]->Write(type); - Mailbox[8]->Write(0x1B); // 'snr' + Mailbox[8].Write(type); + Mailbox[8].Write(0x1B); // 'snr' MB_Write16(8, 0xFFBC); // RSSI MB_Write32(8, *(u32*)&WifiAP::APMac[0]); MB_Write16(8, *(u16*)&WifiAP::APMac[4]); @@ -1386,7 +1385,7 @@ void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) for (int i = 0; i < len; i++) { - Mailbox[8]->Write(data[i]); + Mailbox[8].Write(data[i]); } DrainRXBuffer(); @@ -1394,7 +1393,7 @@ void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) void DSi_NWifi::CheckRX() { - if (!Mailbox[8]->CanFit(2048)) + if (!Mailbox[8].CanFit(2048)) return; int rxlen = Platform::LAN_RecvPacket(LANBuffer); @@ -1433,11 +1432,11 @@ void DSi_NWifi::CheckRX() // TODO: not hardcode the endpoint ID!! u8 ep = 2; - Mailbox[8]->Write(ep); - Mailbox[8]->Write(0x00); + Mailbox[8].Write(ep); + Mailbox[8].Write(0x00); MB_Write16(8, 16 + 8 + datalen); - Mailbox[8]->Write(0); - Mailbox[8]->Write(0); + Mailbox[8].Write(0); + Mailbox[8].Write(0); MB_Write16(8, hdr); MB_Write32(8, *(u32*)&LANBuffer[0]); @@ -1454,7 +1453,7 @@ void DSi_NWifi::CheckRX() MB_Write16(8, *(u16*)&LANBuffer[12]); for (int i = 0; i < datalen; i++) - Mailbox[8]->Write(LANBuffer[14+i]); + Mailbox[8].Write(LANBuffer[14+i]); DrainRXBuffer(); } @@ -1541,25 +1540,25 @@ void DSi_NWifi::_MSTimer() if (ConnectionStatus == 1) { - //if (Mailbox[4]->IsEmpty()) + //if (Mailbox[4].IsEmpty()) CheckRX(); } } void DSi_NWifi::DrainRXBuffer() { - while (Mailbox[8]->Level() >= 6) + while (Mailbox[8].Level() >= 6) { - u16 len = Mailbox[8]->Peek(2) | (Mailbox[8]->Peek(3) << 8); + u16 len = Mailbox[8].Peek(2) | (Mailbox[8].Peek(3) << 8); u32 totallen = len + 6; u32 required = (totallen + 0x7F) & ~0x7F; - if (!Mailbox[4]->CanFit(required)) + if (!Mailbox[4].CanFit(required)) break; u32 i = 0; - for (; i < totallen; i++) Mailbox[4]->Write(Mailbox[8]->Read()); - for (; i < required; i++) Mailbox[4]->Write(0); + for (; i < totallen; i++) Mailbox[4].Write(Mailbox[8].Read()); + for (; i < required; i++) Mailbox[4].Write(0); } UpdateIRQ_F1(); diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 7efd40c7..72780d1c 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -84,40 +84,40 @@ private: u16 MB_Read16(int n) { - u16 ret = Mailbox[n]->Read(); - ret |= (Mailbox[n]->Read() << 8); + u16 ret = Mailbox[n].Read(); + ret |= (Mailbox[n].Read() << 8); return ret; } void MB_Write16(int n, u16 val) { - Mailbox[n]->Write(val & 0xFF); val >>= 8; - Mailbox[n]->Write(val & 0xFF); + Mailbox[n].Write(val & 0xFF); val >>= 8; + Mailbox[n].Write(val & 0xFF); } u32 MB_Read32(int n) { - u32 ret = Mailbox[n]->Read(); - ret |= (Mailbox[n]->Read() << 8); - ret |= (Mailbox[n]->Read() << 16); - ret |= (Mailbox[n]->Read() << 24); + u32 ret = Mailbox[n].Read(); + ret |= (Mailbox[n].Read() << 8); + ret |= (Mailbox[n].Read() << 16); + ret |= (Mailbox[n].Read() << 24); return ret; } void MB_Write32(int n, u32 val) { - Mailbox[n]->Write(val & 0xFF); val >>= 8; - Mailbox[n]->Write(val & 0xFF); val >>= 8; - Mailbox[n]->Write(val & 0xFF); val >>= 8; - Mailbox[n]->Write(val & 0xFF); + Mailbox[n].Write(val & 0xFF); val >>= 8; + Mailbox[n].Write(val & 0xFF); val >>= 8; + Mailbox[n].Write(val & 0xFF); val >>= 8; + Mailbox[n].Write(val & 0xFF); } void MB_Drain(int n) { - while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read(); + while (!Mailbox[n].IsEmpty()) Mailbox[n].Read(); } - FIFO* Mailbox[9]; + DynamicFIFO Mailbox[9]; u8 F0_IRQEnable; u8 F0_IRQStatus; diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index de82edb5..d6fd5f5e 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -52,20 +52,12 @@ DSi_SDHost::DSi_SDHost(u32 num) { Num = num; - DataFIFO[0] = new FIFO(0x100); - DataFIFO[1] = new FIFO(0x100); - DataFIFO32 = new FIFO(0x80); - Ports[0] = NULL; Ports[1] = NULL; } DSi_SDHost::~DSi_SDHost() { - delete DataFIFO[0]; - delete DataFIFO[1]; - delete DataFIFO32; - if (Ports[0]) delete Ports[0]; if (Ports[1]) delete Ports[1]; } @@ -89,10 +81,10 @@ void DSi_SDHost::Reset() Param = 0; memset(ResponseBuffer, 0, sizeof(ResponseBuffer)); - DataFIFO[0]->Clear(); - DataFIFO[1]->Clear(); + DataFIFO[0].Clear(); + DataFIFO[1].Clear(); CurFIFO = 0; - DataFIFO32->Clear(); + DataFIFO32.Clear(); IRQStatus = 0; IRQMask = 0x8B7F031D; @@ -160,8 +152,8 @@ void DSi_SDHost::UpdateData32IRQ() oldflags &= (Data32IRQ >> 11); Data32IRQ &= ~0x0300; - if (DataFIFO32->Level() >= (BlockLen32>>2)) Data32IRQ |= (1<<8); - if (!DataFIFO32->IsEmpty()) Data32IRQ |= (1<<9); + if (DataFIFO32.Level() >= (BlockLen32>>2)) Data32IRQ |= (1<<8); + if (!DataFIFO32.IsEmpty()) Data32IRQ |= (1<<9); u32 newflags = ((Data32IRQ >> 8) & 0x1) | (((~Data32IRQ) >> 8) & 0x2); newflags &= (Data32IRQ >> 11); @@ -256,7 +248,7 @@ u32 DSi_SDHost::DataRX(u8* data, u32 len) u32 f = CurFIFO ^ 1; for (u32 i = 0; i < len; i += 2) - DataFIFO[f]->Write(*(u16*)&data[i]); + DataFIFO[f].Write(*(u16*)&data[i]); //CurFIFO = f; //SetIRQ(24); @@ -304,9 +296,9 @@ u32 DSi_SDHost::DataTX(u8* data, u32 len) if (DataMode == 1) { - if ((DataFIFO32->Level() << 2) < len) + if ((DataFIFO32.Level() << 2) < len) { - if (DataFIFO32->IsEmpty()) + if (DataFIFO32.IsEmpty()) { SetIRQ(25); DSi::CheckNDMAs(1, Num ? 0x29 : 0x28); @@ -316,16 +308,16 @@ u32 DSi_SDHost::DataTX(u8* data, u32 len) // drain FIFO32 into FIFO16 - if (!DataFIFO[f]->IsEmpty()) printf("VERY BAD!! TRYING TO DRAIN FIFO32 INTO FIFO16 BUT IT CONTAINS SHIT ALREADY\n"); + if (!DataFIFO[f].IsEmpty()) printf("VERY BAD!! TRYING TO DRAIN FIFO32 INTO FIFO16 BUT IT CONTAINS SHIT ALREADY\n"); for (;;) { u32 f = CurFIFO; - if ((DataFIFO[f]->Level() << 1) >= BlockLen16) break; - if (DataFIFO32->IsEmpty()) break; + if ((DataFIFO[f].Level() << 1) >= BlockLen16) break; + if (DataFIFO32.IsEmpty()) break; - u32 val = DataFIFO32->Read(); - DataFIFO[f]->Write(val & 0xFFFF); - DataFIFO[f]->Write(val >> 16); + u32 val = DataFIFO32.Read(); + DataFIFO[f].Write(val & 0xFFFF); + DataFIFO[f].Write(val >> 16); } UpdateData32IRQ(); @@ -335,15 +327,15 @@ u32 DSi_SDHost::DataTX(u8* data, u32 len) } else { - if ((DataFIFO[f]->Level() << 1) < len) + if ((DataFIFO[f].Level() << 1) < len) { - if (DataFIFO[f]->IsEmpty()) SetIRQ(25); + if (DataFIFO[f].IsEmpty()) SetIRQ(25); return 0; } } for (u32 i = 0; i < len; i += 2) - *(u16*)&data[i] = DataFIFO[f]->Read(); + *(u16*)&data[i] = DataFIFO[f].Read(); CurFIFO ^= 1; BlockCountInternal--; @@ -392,13 +384,13 @@ void DSi_SDHost::CheckTX() if (DataMode == 1) { - if ((DataFIFO32->Level() << 2) < BlockLen32) + if ((DataFIFO32.Level() << 2) < BlockLen32) return; } else { u32 f = CurFIFO; - if ((DataFIFO[f]->Level() << 1) < BlockLen16) + if ((DataFIFO[f].Level() << 1) < BlockLen16) return; } @@ -481,7 +473,7 @@ u16 DSi_SDHost::Read(u32 addr) u16 DSi_SDHost::ReadFIFO16() { u32 f = CurFIFO; - if (DataFIFO[f]->IsEmpty()) + if (DataFIFO[f].IsEmpty()) { // TODO // on hardware it seems to wrap around. underflow bit is set upon the first 'empty' read. @@ -489,9 +481,9 @@ u16 DSi_SDHost::ReadFIFO16() } DSi_SDDevice* dev = Ports[PortSelect & 0x1]; - u16 ret = DataFIFO[f]->Read(); + u16 ret = DataFIFO[f].Read(); - if (DataFIFO[f]->IsEmpty()) + if (DataFIFO[f].IsEmpty()) { CheckRX(); } @@ -503,16 +495,16 @@ u32 DSi_SDHost::ReadFIFO32() { if (DataMode != 1) return 0; - if (DataFIFO32->IsEmpty()) + if (DataFIFO32.IsEmpty()) { // TODO return 0; } DSi_SDDevice* dev = Ports[PortSelect & 0x1]; - u32 ret = DataFIFO32->Read(); + u32 ret = DataFIFO32.Read(); - if (DataFIFO32->IsEmpty()) + if (DataFIFO32.IsEmpty()) { CheckRX(); } @@ -628,7 +620,7 @@ void DSi_SDHost::Write(u32 addr, u16 val) case 0x100: Data32IRQ = (val & 0x1802) | (Data32IRQ & 0x0300); - if (val & (1<<10)) DataFIFO32->Clear(); + if (val & (1<<10)) DataFIFO32.Clear(); DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); return; case 0x102: return; @@ -643,14 +635,14 @@ void DSi_SDHost::WriteFIFO16(u16 val) { DSi_SDDevice* dev = Ports[PortSelect & 0x1]; u32 f = CurFIFO; - if (DataFIFO[f]->IsFull()) + if (DataFIFO[f].IsFull()) { // TODO printf("!!!! %s FIFO (16) FULL\n", SD_DESC); return; } - DataFIFO[f]->Write(val); + DataFIFO[f].Write(val); CheckTX(); } @@ -659,14 +651,14 @@ void DSi_SDHost::WriteFIFO32(u32 val) { if (DataMode != 1) return; - if (DataFIFO32->IsFull()) + if (DataFIFO32.IsFull()) { // TODO printf("!!!! %s FIFO (32) FULL\n", SD_DESC); return; } - DataFIFO32->Write(val); + DataFIFO32.Write(val); CheckTX(); @@ -679,21 +671,21 @@ void DSi_SDHost::UpdateFIFO32() if (DataMode != 1) return; - if (!DataFIFO32->IsEmpty()) printf("VERY BAD!! TRYING TO DRAIN FIFO16 INTO FIFO32 BUT IT CONTAINS SHIT ALREADY\n"); + if (!DataFIFO32.IsEmpty()) printf("VERY BAD!! TRYING TO DRAIN FIFO16 INTO FIFO32 BUT IT CONTAINS SHIT ALREADY\n"); for (;;) { u32 f = CurFIFO; - if ((DataFIFO32->Level() << 2) >= BlockLen32) break; - if (DataFIFO[f]->IsEmpty()) break; + if ((DataFIFO32.Level() << 2) >= BlockLen32) break; + if (DataFIFO[f].IsEmpty()) break; - u32 val = DataFIFO[f]->Read(); - val |= (DataFIFO[f]->Read() << 16); - DataFIFO32->Write(val); + u32 val = DataFIFO[f].Read(); + val |= (DataFIFO[f].Read() << 16); + DataFIFO32.Write(val); } UpdateData32IRQ(); - if ((DataFIFO32->Level() << 2) >= BlockLen32) + if ((DataFIFO32.Level() << 2) >= BlockLen32) { DSi::CheckNDMAs(1, Num ? 0x29 : 0x28); } @@ -704,8 +696,8 @@ void DSi_SDHost::CheckSwapFIFO() // check whether we can swap the FIFOs u32 f = CurFIFO; - bool cur_empty = (DataMode == 1) ? DataFIFO32->IsEmpty() : DataFIFO[f]->IsEmpty(); - if (cur_empty && ((DataFIFO[f^1]->Level() << 1) >= BlockLen16)) + bool cur_empty = (DataMode == 1) ? DataFIFO32.IsEmpty() : DataFIFO[f].IsEmpty(); + if (cur_empty && ((DataFIFO[f^1].Level() << 1) >= BlockLen16)) { CurFIFO ^= 1; } diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 43f5a98e..1f9243f6 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -85,12 +85,12 @@ private: u32 Param; u16 ResponseBuffer[8]; - FIFO* DataFIFO[2]; - u32 CurFIFO; // FIFO accessible for read/write - FIFO* DataFIFO32; - DSi_SDDevice* Ports[2]; + u32 CurFIFO; // FIFO accessible for read/write + FIFO DataFIFO[2]; + FIFO DataFIFO32; + void UpdateData32IRQ(); void ClearIRQ(u32 irq); void SetIRQ(u32 irq); diff --git a/src/FIFO.h b/src/FIFO.h index 2b2c1020..ca146100 100644 --- a/src/FIFO.h +++ b/src/FIFO.h @@ -21,18 +21,95 @@ #include "types.h" -template +template class FIFO { public: - FIFO(u32 num) + void Clear() + { + NumOccupied = 0; + ReadPos = 0; + WritePos = 0; + memset(&Entries[ReadPos], 0, sizeof(T)); + } + + + void DoSavestate(Savestate* file) + { + file->Var32(&NumOccupied); + file->Var32(&ReadPos); + file->Var32(&WritePos); + + file->VarArray(Entries, sizeof(T)*NumEntries); + } + + + void Write(T val) + { + if (IsFull()) return; + + Entries[WritePos] = val; + + WritePos++; + if (WritePos >= NumEntries) + WritePos = 0; + + NumOccupied++; + } + + T Read() + { + T ret = Entries[ReadPos]; + if (IsEmpty()) + return ret; + + ReadPos++; + if (ReadPos >= NumEntries) + ReadPos = 0; + + NumOccupied--; + return ret; + } + + T Peek() + { + return Entries[ReadPos]; + } + + T Peek(u32 offset) + { + u32 pos = ReadPos + offset; + if (pos >= NumEntries) + pos -= NumEntries; + + return Entries[pos]; + } + + u32 Level() { return NumOccupied; } + bool IsEmpty() { return NumOccupied == 0; } + bool IsFull() { return NumOccupied >= NumEntries; } + + bool CanFit(u32 num) { return ((NumOccupied + num) <= NumEntries); } + +private: + T Entries[NumEntries] = {0}; + u32 NumOccupied = 0; + u32 ReadPos = 0, WritePos = 0; +}; + + +template +class DynamicFIFO +{ +public: + DynamicFIFO(u32 num) { NumEntries = num; Entries = new T[num]; Clear(); } - ~FIFO() + ~DynamicFIFO() { delete[] Entries; } diff --git a/src/GPU.cpp b/src/GPU.cpp index 35ebaba1..ed73e297 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -142,6 +142,9 @@ u8 VRAMFlat_BOBJExtPal[8*1024]; u8 VRAMFlat_Texture[512*1024]; u8 VRAMFlat_TexPal[128*1024]; +u32 OAMDirty; +u32 PaletteDirty; + bool Init() { GPU2D_A = new GPU2D_Soft(0); @@ -272,6 +275,9 @@ void Reset() ResetRenderer(); ResetVRAMCache(); + + OAMDirty = 0x3; + PaletteDirty = 0xF; } void Stop() diff --git a/src/GPU.h b/src/GPU.h index cc62e1ea..1bbb9fe2 100644 --- a/src/GPU.h +++ b/src/GPU.h @@ -147,14 +147,16 @@ bool MakeVRAMFlat_TexPalCoherent(NonStupidBitField<128*1024/VRAMDirtyGranularity void SyncDirtyFlags(); -typedef struct +extern u32 OAMDirty; +extern u32 PaletteDirty; + +struct RenderSettings { bool Soft_Threaded; int GL_ScaleFactor; bool GL_BetterPolygons; - -} RenderSettings; +}; bool Init(); @@ -509,6 +511,35 @@ T ReadVRAM_TexPal(u32 addr) return ret; } +template +T ReadPalette(u32 addr) +{ + return *(T*)&Palette[addr & 0x7FF]; +} + +template +void WritePalette(u32 addr, T val) +{ + addr &= 0x7FF; + + *(T*)&Palette[addr] = val; + PaletteDirty |= 1 << (addr / VRAMDirtyGranularity); +} + +template +T ReadOAM(u32 addr) +{ + return *(T*)&OAM[addr & 0x7FF]; +} + +template +void WriteOAM(u32 addr, T val) +{ + addr &= 0x7FF; + + *(T*)&OAM[addr] = val; + OAMDirty |= 1 << (addr / 1024); +} void SetPowerCnt(u32 val); diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 7b304268..53fafb3e 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -99,7 +99,7 @@ namespace GPU3D { -const u32 CmdNumParams[256] = +const u8 CmdNumParams[256] = { // 0x00 0, @@ -147,10 +147,10 @@ typedef union } CmdFIFOEntry; -FIFO* CmdFIFO; -FIFO* CmdPIPE; +FIFO CmdFIFO; +FIFO CmdPIPE; -FIFO* CmdStallQueue; +FIFO CmdStallQueue; u32 NumCommands, CurCommand, ParamCount, TotalParams; @@ -277,20 +277,11 @@ u32 FlushAttributes; bool Init() { - CmdFIFO = new FIFO(256); - CmdPIPE = new FIFO(4); - - CmdStallQueue = new FIFO(64); - return true; } void DeInit() { - delete CmdFIFO; - delete CmdPIPE; - - delete CmdStallQueue; } void ResetRenderingState() @@ -314,10 +305,10 @@ void ResetRenderingState() void Reset() { - CmdFIFO->Clear(); - CmdPIPE->Clear(); + CmdFIFO.Clear(); + CmdPIPE.Clear(); - CmdStallQueue->Clear(); + CmdStallQueue.Clear(); NumCommands = 0; CurCommand = 0; @@ -395,8 +386,8 @@ void DoSavestate(Savestate* file) { file->Section("GP3D"); - CmdFIFO->DoSavestate(file); - CmdPIPE->DoSavestate(file); + CmdFIFO.DoSavestate(file); + CmdPIPE.DoSavestate(file); file->Var32(&NumCommands); file->Var32(&CurCommand); @@ -593,7 +584,9 @@ void DoSavestate(Savestate* file) } } - CmdStallQueue->DoSavestate(file); + // probably not worth storing the vblank-latched Renderxxxxxx variables + CmdStallQueue.DoSavestate(file); + file->Var32((u32*)&VertexPipeline); file->Var32((u32*)&NormalPipeline); file->Var32((u32*)&PolygonPipeline); @@ -1731,24 +1724,24 @@ void VecTest(u32* params) void CmdFIFOWrite(CmdFIFOEntry& entry) { - if (CmdFIFO->IsEmpty() && !CmdPIPE->IsFull()) + if (CmdFIFO.IsEmpty() && !CmdPIPE.IsFull()) { - CmdPIPE->Write(entry); + CmdPIPE.Write(entry); } else { - if (CmdFIFO->IsFull()) + if (CmdFIFO.IsFull()) { // store it to the stall queue. stall the system. // worst case is if a STMxx opcode causes this, which is why our stall queue // has 64 entries. this is less complicated than trying to make STMxx stall-able. - CmdStallQueue->Write(entry); + CmdStallQueue.Write(entry); NDS::GXFIFOStall(); return; } - CmdFIFO->Write(entry); + CmdFIFO.Write(entry); } GXStat |= (1<<27); @@ -1767,27 +1760,27 @@ void CmdFIFOWrite(CmdFIFOEntry& entry) CmdFIFOEntry CmdFIFORead() { - CmdFIFOEntry ret = CmdPIPE->Read(); + CmdFIFOEntry ret = CmdPIPE.Read(); - if (CmdPIPE->Level() <= 2) + if (CmdPIPE.Level() <= 2) { - if (!CmdFIFO->IsEmpty()) - CmdPIPE->Write(CmdFIFO->Read()); - if (!CmdFIFO->IsEmpty()) - CmdPIPE->Write(CmdFIFO->Read()); + if (!CmdFIFO.IsEmpty()) + CmdPIPE.Write(CmdFIFO.Read()); + if (!CmdFIFO.IsEmpty()) + CmdPIPE.Write(CmdFIFO.Read()); // empty stall queue if needed // CmdFIFO should not be full at this point. - if (!CmdStallQueue->IsEmpty()) + if (!CmdStallQueue.IsEmpty()) { - while (!CmdStallQueue->IsEmpty()) + while (!CmdStallQueue.IsEmpty()) { - if (CmdFIFO->IsFull()) break; - CmdFIFOEntry entry = CmdStallQueue->Read(); + if (CmdFIFO.IsFull()) break; + CmdFIFOEntry entry = CmdStallQueue.Read(); CmdFIFOWrite(entry); } - if (CmdStallQueue->IsEmpty()) + if (CmdStallQueue.IsEmpty()) NDS::GXFIFOUnstall(); } @@ -1798,7 +1791,37 @@ CmdFIFOEntry CmdFIFORead() return ret; } +inline void VertexPipelineSubmitCmd() +{ + // vertex commands 0x24, 0x25, 0x26, 0x27, 0x28 + if (!(VertexSlotsFree & 0x1)) NextVertexSlot(); + else AddCycles(1); + NormalPipeline = 0; +} +inline void VertexPipelineCmdDelayed6() +{ + // commands 0x20, 0x30, 0x31, 0x72 that can run 6 cycles after a vertex + if (VertexPipeline > 2) AddCycles((VertexPipeline - 2) + 1); + else AddCycles(NormalPipeline + 1); + NormalPipeline = 0; +} + +inline void VertexPipelineCmdDelayed8() +{ + // commands 0x29, 0x2A, 0x2B, 0x33, 0x34, 0x41, 0x60, 0x71 that can run 8 cycles after a vertex + if (VertexPipeline > 0) AddCycles(VertexPipeline + 1); + else AddCycles(NormalPipeline + 1); + NormalPipeline = 0; +} + +inline void VertexPipelineCmdDelayed4() +{ + // all other commands can run 4 cycles after a vertex + // no need to do much here since that is the minimum + AddCycles(NormalPipeline + 1); + NormalPipeline = 0; +} void ExecuteCommand() { @@ -1809,81 +1832,23 @@ void ExecuteCommand() // each FIFO entry takes 1 cycle to be processed // commands (presumably) run when all the needed parameters have been read // which is where we add the remaining cycles if any - if (ExecParamCount == 0) + + u32 paramsRequiredCount = CmdNumParams[entry.Command]; + if (paramsRequiredCount <= 1) { - // delay the first command entry as needed - switch (entry.Command) - { - // commands that stall the polygon pipeline - case 0x32: StallPolygonPipeline(8 + 1, 2); break; // 32 can run 6 cycles after a vertex - case 0x40: StallPolygonPipeline(1, 0); break; - case 0x70: StallPolygonPipeline(10 + 1, 0); break; + // fast path for command which only have a single parameter - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - // vertex - if (!(VertexSlotsFree & 0x1)) NextVertexSlot(); - else AddCycles(1); - NormalPipeline = 0; - break; - - case 0x20: - case 0x30: - case 0x31: - case 0x72: - // commands that can run 6 cycles after a vertex - if (VertexPipeline > 2) AddCycles((VertexPipeline - 2) + 1); - else AddCycles(NormalPipeline + 1); - NormalPipeline = 0; - break; - - case 0x29: - case 0x2A: - case 0x2B: - case 0x33: - case 0x34: - case 0x41: - case 0x60: - case 0x71: - // command that can run 8 cycles after a vertex - if (VertexPipeline > 0) AddCycles(VertexPipeline + 1); - else AddCycles(NormalPipeline + 1); - NormalPipeline = 0; - break; - - default: - // all other commands can run 4 cycles after a vertex - // no need to do much here since that is the minimum - AddCycles(NormalPipeline + 1); - NormalPipeline = 0; - break; - } - } - else - AddCycles(1); - - ExecParams[ExecParamCount] = entry.Param; - ExecParamCount++; - - if (ExecParamCount >= CmdNumParams[entry.Command]) - { - /*printf("[GXS:%08X] 0x%02X, ", GXStat, entry.Command); - for (int k = 0; k < ExecParamCount; k++) printf("0x%08X, ", ExecParams[k]); - printf("\n");*/ - - ExecParamCount = 0; + /*printf("[GXS:%08X] 0x%02X, 0x%08X", GXStat, entry.Command, entry.Param);*/ switch (entry.Command) { case 0x10: // matrix mode - MatrixMode = ExecParams[0] & 0x3; + VertexPipelineCmdDelayed4(); + MatrixMode = entry.Param & 0x3; break; case 0x11: // push matrix + VertexPipelineCmdDelayed4(); NumPushPopCommands--; if (MatrixMode == 0) { @@ -1914,6 +1879,7 @@ void ExecuteCommand() break; case 0x12: // pop matrix + VertexPipelineCmdDelayed4(); NumPushPopCommands--; if (MatrixMode == 0) { @@ -1936,7 +1902,7 @@ void ExecuteCommand() } else { - s32 offset = (s32)(ExecParams[0] << 26) >> 26; + s32 offset = (s32)(entry.Param << 26) >> 26; PosMatrixStackPointer -= offset; PosMatrixStackPointer &= 0x3F; @@ -1950,6 +1916,7 @@ void ExecuteCommand() break; case 0x13: // store matrix + VertexPipelineCmdDelayed4(); if (MatrixMode == 0) { memcpy(ProjMatrixStack, ProjMatrix, 16*4); @@ -1960,7 +1927,7 @@ void ExecuteCommand() } else { - u32 addr = ExecParams[0] & 0x1F; + u32 addr = entry.Param & 0x1F; if (addr > 30) GXStat |= (1<<15); memcpy(PosMatrixStack[addr], PosMatrix, 16*4); @@ -1970,6 +1937,7 @@ void ExecuteCommand() break; case 0x14: // restore matrix + VertexPipelineCmdDelayed4(); if (MatrixMode == 0) { memcpy(ProjMatrix, ProjMatrixStack, 16*4); @@ -1983,7 +1951,7 @@ void ExecuteCommand() } else { - u32 addr = ExecParams[0] & 0x1F; + u32 addr = entry.Param & 0x1F; if (addr > 30) GXStat |= (1<<15); memcpy(PosMatrix, PosMatrixStack[addr], 16*4); @@ -1994,6 +1962,7 @@ void ExecuteCommand() break; case 0x15: // identity + VertexPipelineCmdDelayed4(); if (MatrixMode == 0) { MatrixLoadIdentity(ProjMatrix); @@ -2012,173 +1981,10 @@ void ExecuteCommand() } break; - case 0x16: // load 4x4 - if (MatrixMode == 0) - { - MatrixLoad4x4(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(18); - } - else if (MatrixMode == 3) - { - MatrixLoad4x4(TexMatrix, (s32*)ExecParams); - AddCycles(10); - } - else - { - MatrixLoad4x4(PosMatrix, (s32*)ExecParams); - if (MatrixMode == 2) - MatrixLoad4x4(VecMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(18); - } - break; - - case 0x17: // load 4x3 - if (MatrixMode == 0) - { - MatrixLoad4x3(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(18); - } - else if (MatrixMode == 3) - { - MatrixLoad4x3(TexMatrix, (s32*)ExecParams); - AddCycles(7); - } - else - { - MatrixLoad4x3(PosMatrix, (s32*)ExecParams); - if (MatrixMode == 2) - MatrixLoad4x3(VecMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(18); - } - break; - - case 0x18: // mult 4x4 - if (MatrixMode == 0) - { - MatrixMult4x4(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(35 - 16); - } - else if (MatrixMode == 3) - { - MatrixMult4x4(TexMatrix, (s32*)ExecParams); - AddCycles(33 - 16); - } - else - { - MatrixMult4x4(PosMatrix, (s32*)ExecParams); - if (MatrixMode == 2) - { - MatrixMult4x4(VecMatrix, (s32*)ExecParams); - AddCycles(35 + 30 - 16); - } - else AddCycles(35 - 16); - ClipMatrixDirty = true; - } - break; - - case 0x19: // mult 4x3 - if (MatrixMode == 0) - { - MatrixMult4x3(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(35 - 12); - } - else if (MatrixMode == 3) - { - MatrixMult4x3(TexMatrix, (s32*)ExecParams); - AddCycles(33 - 12); - } - else - { - MatrixMult4x3(PosMatrix, (s32*)ExecParams); - if (MatrixMode == 2) - { - MatrixMult4x3(VecMatrix, (s32*)ExecParams); - AddCycles(35 + 30 - 12); - } - else AddCycles(35 - 12); - ClipMatrixDirty = true; - } - break; - - case 0x1A: // mult 3x3 - if (MatrixMode == 0) - { - MatrixMult3x3(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(35 - 9); - } - else if (MatrixMode == 3) - { - MatrixMult3x3(TexMatrix, (s32*)ExecParams); - AddCycles(33 - 9); - } - else - { - MatrixMult3x3(PosMatrix, (s32*)ExecParams); - if (MatrixMode == 2) - { - MatrixMult3x3(VecMatrix, (s32*)ExecParams); - AddCycles(35 + 30 - 9); - } - else AddCycles(35 - 9); - ClipMatrixDirty = true; - } - break; - - case 0x1B: // scale - if (MatrixMode == 0) - { - MatrixScale(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(35 - 3); - } - else if (MatrixMode == 3) - { - MatrixScale(TexMatrix, (s32*)ExecParams); - AddCycles(33 - 3); - } - else - { - MatrixScale(PosMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(35 - 3); - } - break; - - case 0x1C: // translate - if (MatrixMode == 0) - { - MatrixTranslate(ProjMatrix, (s32*)ExecParams); - ClipMatrixDirty = true; - AddCycles(35 - 3); - } - else if (MatrixMode == 3) - { - MatrixTranslate(TexMatrix, (s32*)ExecParams); - AddCycles(33 - 3); - } - else - { - MatrixTranslate(PosMatrix, (s32*)ExecParams); - if (MatrixMode == 2) - { - MatrixTranslate(VecMatrix, (s32*)ExecParams); - AddCycles(35 + 30 - 3); - } - else AddCycles(35 - 3); - ClipMatrixDirty = true; - } - break; - case 0x20: // vertex color + VertexPipelineCmdDelayed6(); { - u32 c = ExecParams[0]; + u32 c = entry.Param; u32 r = c & 0x1F; u32 g = (c >> 5) & 0x1F; u32 b = (c >> 10) & 0x1F; @@ -2189,15 +1995,17 @@ void ExecuteCommand() break; case 0x21: // normal - Normal[0] = (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6; - Normal[1] = (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6; - Normal[2] = (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6; + VertexPipelineCmdDelayed4(); + Normal[0] = (s16)((entry.Param & 0x000003FF) << 6) >> 6; + Normal[1] = (s16)((entry.Param & 0x000FFC00) >> 4) >> 6; + Normal[2] = (s16)((entry.Param & 0x3FF00000) >> 14) >> 6; CalculateLighting(); break; case 0x22: // texcoord - RawTexCoords[0] = ExecParams[0] & 0xFFFF; - RawTexCoords[1] = ExecParams[0] >> 16; + VertexPipelineCmdDelayed4(); + RawTexCoords[0] = entry.Param & 0xFFFF; + RawTexCoords[1] = entry.Param >> 16; if ((TexParam >> 30) == 1) { TexCoords[0] = (RawTexCoords[0]*TexMatrix[0] + RawTexCoords[1]*TexMatrix[4] + TexMatrix[8] + TexMatrix[12]) >> 12; @@ -2210,65 +2018,67 @@ void ExecuteCommand() } break; - case 0x23: // full vertex - CurVertex[0] = ExecParams[0] & 0xFFFF; - CurVertex[1] = ExecParams[0] >> 16; - CurVertex[2] = ExecParams[1] & 0xFFFF; - SubmitVertex(); - break; - case 0x24: // 10-bit vertex - CurVertex[0] = (ExecParams[0] & 0x000003FF) << 6; - CurVertex[1] = (ExecParams[0] & 0x000FFC00) >> 4; - CurVertex[2] = (ExecParams[0] & 0x3FF00000) >> 14; + VertexPipelineSubmitCmd(); + CurVertex[0] = (entry.Param & 0x000003FF) << 6; + CurVertex[1] = (entry.Param & 0x000FFC00) >> 4; + CurVertex[2] = (entry.Param & 0x3FF00000) >> 14; SubmitVertex(); break; case 0x25: // vertex XY - CurVertex[0] = ExecParams[0] & 0xFFFF; - CurVertex[1] = ExecParams[0] >> 16; + VertexPipelineSubmitCmd(); + CurVertex[0] = entry.Param & 0xFFFF; + CurVertex[1] = entry.Param >> 16; SubmitVertex(); break; case 0x26: // vertex XZ - CurVertex[0] = ExecParams[0] & 0xFFFF; - CurVertex[2] = ExecParams[0] >> 16; + VertexPipelineSubmitCmd(); + CurVertex[0] = entry.Param & 0xFFFF; + CurVertex[2] = entry.Param >> 16; SubmitVertex(); break; case 0x27: // vertex YZ - CurVertex[1] = ExecParams[0] & 0xFFFF; - CurVertex[2] = ExecParams[0] >> 16; + VertexPipelineSubmitCmd(); + CurVertex[1] = entry.Param & 0xFFFF; + CurVertex[2] = entry.Param >> 16; SubmitVertex(); break; case 0x28: // 10-bit delta vertex - CurVertex[0] += (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6; - CurVertex[1] += (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6; - CurVertex[2] += (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6; + VertexPipelineSubmitCmd(); + CurVertex[0] += (s16)((entry.Param & 0x000003FF) << 6) >> 6; + CurVertex[1] += (s16)((entry.Param & 0x000FFC00) >> 4) >> 6; + CurVertex[2] += (s16)((entry.Param & 0x3FF00000) >> 14) >> 6; SubmitVertex(); break; case 0x29: // polygon attributes - PolygonAttr = ExecParams[0]; + VertexPipelineCmdDelayed8(); + PolygonAttr = entry.Param; break; case 0x2A: // texture param - TexParam = ExecParams[0]; + VertexPipelineCmdDelayed8(); + TexParam = entry.Param; break; case 0x2B: // texture palette - TexPalette = ExecParams[0] & 0x1FFF; + VertexPipelineCmdDelayed8(); + TexPalette = entry.Param & 0x1FFF; break; case 0x30: // diffuse/ambient material - MatDiffuse[0] = ExecParams[0] & 0x1F; - MatDiffuse[1] = (ExecParams[0] >> 5) & 0x1F; - MatDiffuse[2] = (ExecParams[0] >> 10) & 0x1F; - MatAmbient[0] = (ExecParams[0] >> 16) & 0x1F; - MatAmbient[1] = (ExecParams[0] >> 21) & 0x1F; - MatAmbient[2] = (ExecParams[0] >> 26) & 0x1F; - if (ExecParams[0] & 0x8000) + VertexPipelineCmdDelayed6(); + MatDiffuse[0] = entry.Param & 0x1F; + MatDiffuse[1] = (entry.Param >> 5) & 0x1F; + MatDiffuse[2] = (entry.Param >> 10) & 0x1F; + MatAmbient[0] = (entry.Param >> 16) & 0x1F; + MatAmbient[1] = (entry.Param >> 21) & 0x1F; + MatAmbient[2] = (entry.Param >> 26) & 0x1F; + if (entry.Param & 0x8000) { VertexColor[0] = MatDiffuse[0]; VertexColor[1] = MatDiffuse[1]; @@ -2278,23 +2088,25 @@ void ExecuteCommand() break; case 0x31: // specular/emission material - MatSpecular[0] = ExecParams[0] & 0x1F; - MatSpecular[1] = (ExecParams[0] >> 5) & 0x1F; - MatSpecular[2] = (ExecParams[0] >> 10) & 0x1F; - MatEmission[0] = (ExecParams[0] >> 16) & 0x1F; - MatEmission[1] = (ExecParams[0] >> 21) & 0x1F; - MatEmission[2] = (ExecParams[0] >> 26) & 0x1F; - UseShininessTable = (ExecParams[0] & 0x8000) != 0; + VertexPipelineCmdDelayed6(); + MatSpecular[0] = entry.Param & 0x1F; + MatSpecular[1] = (entry.Param >> 5) & 0x1F; + MatSpecular[2] = (entry.Param >> 10) & 0x1F; + MatEmission[0] = (entry.Param >> 16) & 0x1F; + MatEmission[1] = (entry.Param >> 21) & 0x1F; + MatEmission[2] = (entry.Param >> 26) & 0x1F; + UseShininessTable = (entry.Param & 0x8000) != 0; AddCycles(3); break; case 0x32: // light direction + StallPolygonPipeline(8 + 1, 2); // 0x32 can run 6 cycles after a vertex { - u32 l = ExecParams[0] >> 30; + u32 l = entry.Param >> 30; s16 dir[3]; - dir[0] = (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6; - dir[1] = (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6; - dir[2] = (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6; + dir[0] = (s16)((entry.Param & 0x000003FF) << 6) >> 6; + dir[1] = (s16)((entry.Param & 0x000FFC00) >> 4) >> 6; + dir[2] = (s16)((entry.Param & 0x3FF00000) >> 14) >> 6; LightDirection[l][0] = (dir[0]*VecMatrix[0] + dir[1]*VecMatrix[4] + dir[2]*VecMatrix[8]) >> 12; LightDirection[l][1] = (dir[0]*VecMatrix[1] + dir[1]*VecMatrix[5] + dir[2]*VecMatrix[9]) >> 12; LightDirection[l][2] = (dir[0]*VecMatrix[2] + dir[1]*VecMatrix[6] + dir[2]*VecMatrix[10]) >> 12; @@ -2303,32 +2115,21 @@ void ExecuteCommand() break; case 0x33: // light color + VertexPipelineCmdDelayed8(); { - u32 l = ExecParams[0] >> 30; - LightColor[l][0] = ExecParams[0] & 0x1F; - LightColor[l][1] = (ExecParams[0] >> 5) & 0x1F; - LightColor[l][2] = (ExecParams[0] >> 10) & 0x1F; + u32 l = entry.Param >> 30; + LightColor[l][0] = entry.Param & 0x1F; + LightColor[l][1] = (entry.Param >> 5) & 0x1F; + LightColor[l][2] = (entry.Param >> 10) & 0x1F; } AddCycles(1); break; - case 0x34: // shininess table - { - for (int i = 0; i < 128; i += 4) - { - u32 val = ExecParams[i >> 2]; - ShininessTable[i + 0] = val & 0xFF; - ShininessTable[i + 1] = (val >> 8) & 0xFF; - ShininessTable[i + 2] = (val >> 16) & 0xFF; - ShininessTable[i + 3] = val >> 24; - } - } - break; - case 0x40: // begin polygons + StallPolygonPipeline(1, 0); // TODO: check if there was a polygon being defined but incomplete // such cases seem to freeze the GPU - PolygonMode = ExecParams[0] & 0x3; + PolygonMode = entry.Param & 0x3; VertexNum = 0; VertexNumInPoly = 0; NumConsecutivePolygons = 0; @@ -2337,6 +2138,7 @@ void ExecuteCommand() break; case 0x41: // end polygons + VertexPipelineCmdDelayed8(); // TODO: research this? // it doesn't seem to have any effect whatsoever, but // its timing characteristics are different from those of other @@ -2344,8 +2146,9 @@ void ExecuteCommand() break; case 0x50: // flush + VertexPipelineCmdDelayed4(); FlushRequest = 1; - FlushAttributes = ExecParams[0] & 0x3; + FlushAttributes = entry.Param & 0x3; CycleCount = 325; // probably safe to just reset all pipelines // but needs checked @@ -2355,40 +2158,267 @@ void ExecuteCommand() VertexSlotCounter = 0; VertexSlotsFree = 1; break; - + case 0x60: // viewport x1,y1,x2,y2 + VertexPipelineCmdDelayed8(); // note: viewport Y coordinates are upside-down - Viewport[0] = ExecParams[0] & 0xFF; // x0 - Viewport[1] = (191 - ((ExecParams[0] >> 8) & 0xFF)) & 0xFF; // y0 - Viewport[2] = (ExecParams[0] >> 16) & 0xFF; // x1 - Viewport[3] = (191 - (ExecParams[0] >> 24)) & 0xFF; // y1 + Viewport[0] = entry.Param & 0xFF; // x0 + Viewport[1] = (191 - ((entry.Param >> 8) & 0xFF)) & 0xFF; // y0 + Viewport[2] = (entry.Param >> 16) & 0xFF; // x1 + Viewport[3] = (191 - (entry.Param >> 24)) & 0xFF; // y1 Viewport[4] = (Viewport[2] - Viewport[0] + 1) & 0x1FF; // width Viewport[5] = (Viewport[1] - Viewport[3] + 1) & 0xFF; // height break; - case 0x70: // box test - NumTestCommands -= 3; - BoxTest(ExecParams); - break; - - case 0x71: // pos test - NumTestCommands -= 2; - CurVertex[0] = ExecParams[0] & 0xFFFF; - CurVertex[1] = ExecParams[0] >> 16; - CurVertex[2] = ExecParams[1] & 0xFFFF; - PosTest(); - break; - - case 0x72: // vec test - NumTestCommands--; - VecTest(ExecParams); - break; - default: + VertexPipelineCmdDelayed4(); //printf("!! UNKNOWN GX COMMAND %02X %08X\n", entry.Command, entry.Param); break; } } + else + { + ExecParams[ExecParamCount] = entry.Param; + ExecParamCount++; + + if (ExecParamCount == 1) + { + // delay the first command entry as needed + switch (entry.Command) + { + // commands that stall the polygon pipeline + case 0x23: VertexPipelineSubmitCmd(); break; + case 0x34: + case 0x71: + VertexPipelineCmdDelayed8(); + break; + case 0x70: StallPolygonPipeline(10 + 1, 0); break; + case 0x72: VertexPipelineCmdDelayed6(); break; + default: VertexPipelineCmdDelayed4(); break; + } + } + else + { + AddCycles(1); + + if (ExecParamCount >= paramsRequiredCount) + { + /*printf("[GXS:%08X] 0x%02X, ", GXStat, entry.Command); + for (int k = 0; k < ExecParamCount; k++) printf("0x%08X, ", ExecParams[k]); + printf("\n");*/ + + ExecParamCount = 0; + + switch (entry.Command) + { + case 0x16: // load 4x4 + if (MatrixMode == 0) + { + MatrixLoad4x4(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(18); + } + else if (MatrixMode == 3) + { + MatrixLoad4x4(TexMatrix, (s32*)ExecParams); + AddCycles(10); + } + else + { + MatrixLoad4x4(PosMatrix, (s32*)ExecParams); + if (MatrixMode == 2) + MatrixLoad4x4(VecMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(18); + } + break; + + case 0x17: // load 4x3 + if (MatrixMode == 0) + { + MatrixLoad4x3(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(18); + } + else if (MatrixMode == 3) + { + MatrixLoad4x3(TexMatrix, (s32*)ExecParams); + AddCycles(7); + } + else + { + MatrixLoad4x3(PosMatrix, (s32*)ExecParams); + if (MatrixMode == 2) + MatrixLoad4x3(VecMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(18); + } + break; + + case 0x18: // mult 4x4 + if (MatrixMode == 0) + { + MatrixMult4x4(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(35 - 16); + } + else if (MatrixMode == 3) + { + MatrixMult4x4(TexMatrix, (s32*)ExecParams); + AddCycles(33 - 16); + } + else + { + MatrixMult4x4(PosMatrix, (s32*)ExecParams); + if (MatrixMode == 2) + { + MatrixMult4x4(VecMatrix, (s32*)ExecParams); + AddCycles(35 + 30 - 16); + } + else AddCycles(35 - 16); + ClipMatrixDirty = true; + } + break; + + case 0x19: // mult 4x3 + if (MatrixMode == 0) + { + MatrixMult4x3(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(35 - 12); + } + else if (MatrixMode == 3) + { + MatrixMult4x3(TexMatrix, (s32*)ExecParams); + AddCycles(33 - 12); + } + else + { + MatrixMult4x3(PosMatrix, (s32*)ExecParams); + if (MatrixMode == 2) + { + MatrixMult4x3(VecMatrix, (s32*)ExecParams); + AddCycles(35 + 30 - 12); + } + else AddCycles(35 - 12); + ClipMatrixDirty = true; + } + break; + + case 0x1A: // mult 3x3 + if (MatrixMode == 0) + { + MatrixMult3x3(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(35 - 9); + } + else if (MatrixMode == 3) + { + MatrixMult3x3(TexMatrix, (s32*)ExecParams); + AddCycles(33 - 9); + } + else + { + MatrixMult3x3(PosMatrix, (s32*)ExecParams); + if (MatrixMode == 2) + { + MatrixMult3x3(VecMatrix, (s32*)ExecParams); + AddCycles(35 + 30 - 9); + } + else AddCycles(35 - 9); + ClipMatrixDirty = true; + } + break; + + case 0x1B: // scale + if (MatrixMode == 0) + { + MatrixScale(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(35 - 3); + } + else if (MatrixMode == 3) + { + MatrixScale(TexMatrix, (s32*)ExecParams); + AddCycles(33 - 3); + } + else + { + MatrixScale(PosMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(35 - 3); + } + break; + + case 0x1C: // translate + if (MatrixMode == 0) + { + MatrixTranslate(ProjMatrix, (s32*)ExecParams); + ClipMatrixDirty = true; + AddCycles(35 - 3); + } + else if (MatrixMode == 3) + { + MatrixTranslate(TexMatrix, (s32*)ExecParams); + AddCycles(33 - 3); + } + else + { + MatrixTranslate(PosMatrix, (s32*)ExecParams); + if (MatrixMode == 2) + { + MatrixTranslate(VecMatrix, (s32*)ExecParams); + AddCycles(35 + 30 - 3); + } + else AddCycles(35 - 3); + ClipMatrixDirty = true; + } + break; + + case 0x23: // full vertex + CurVertex[0] = ExecParams[0] & 0xFFFF; + CurVertex[1] = ExecParams[0] >> 16; + CurVertex[2] = ExecParams[1] & 0xFFFF; + SubmitVertex(); + break; + + case 0x34: // shininess table + { + for (int i = 0; i < 128; i += 4) + { + u32 val = ExecParams[i >> 2]; + ShininessTable[i + 0] = val & 0xFF; + ShininessTable[i + 1] = (val >> 8) & 0xFF; + ShininessTable[i + 2] = (val >> 16) & 0xFF; + ShininessTable[i + 3] = val >> 24; + } + } + break; + + case 0x71: // pos test + NumTestCommands -= 2; + CurVertex[0] = ExecParams[0] & 0xFFFF; + CurVertex[1] = ExecParams[0] >> 16; + CurVertex[2] = ExecParams[1] & 0xFFFF; + PosTest(); + break; + + case 0x70: // box test + NumTestCommands -= 3; + BoxTest(ExecParams); + break; + + case 0x72: // vec test + NumTestCommands--; + VecTest(ExecParams); + break; + + default: + __builtin_unreachable(); + } + } + } + } } s32 CyclesToRunFor() @@ -2414,7 +2444,7 @@ void FinishWork(s32 cycles) void Run() { if (!GeometryEnabled || FlushRequest || - (CmdPIPE->IsEmpty() && !(GXStat & (1<<27)))) + (CmdPIPE.IsEmpty() && !(GXStat & (1<<27)))) { Timestamp = NDS::ARM9Timestamp >> NDS::ARM9ClockShift; return; @@ -2426,7 +2456,7 @@ void Run() if (CycleCount <= 0) { - while (CycleCount <= 0 && !CmdPIPE->IsEmpty()) + while (CycleCount <= 0 && !CmdPIPE.IsEmpty()) { if (NumPushPopCommands == 0) GXStat &= ~(1<<14); if (NumTestCommands == 0) GXStat &= ~(1<<0); @@ -2435,7 +2465,7 @@ void Run() } } - if (CycleCount <= 0 && CmdPIPE->IsEmpty()) + if (CycleCount <= 0 && CmdPIPE.IsEmpty()) { if (GXStat & (1<<27)) FinishWork(-CycleCount); else CycleCount = 0; @@ -2451,8 +2481,8 @@ void CheckFIFOIRQ() bool irq = false; switch (GXStat >> 30) { - case 1: irq = (CmdFIFO->Level() < 128); break; - case 2: irq = CmdFIFO->IsEmpty(); break; + case 1: irq = (CmdFIFO.Level() < 128); break; + case 2: irq = CmdFIFO.IsEmpty(); break; } if (irq) NDS::SetIRQ(0, NDS::IRQ_GXFIFO); @@ -2461,7 +2491,7 @@ void CheckFIFOIRQ() void CheckFIFODMA() { - if (CmdFIFO->Level() < 128) + if (CmdFIFO.Level() < 128) NDS::CheckDMAs(0, 0x07); } @@ -2668,7 +2698,7 @@ u8 Read8(u32 addr) { Run(); - u32 fifolevel = CmdFIFO->Level(); + u32 fifolevel = CmdFIFO.Level(); return fifolevel & 0xFF; } @@ -2676,7 +2706,7 @@ u8 Read8(u32 addr) { Run(); - u32 fifolevel = CmdFIFO->Level(); + u32 fifolevel = CmdFIFO.Level(); return ((GXStat >> 24) & 0xFF) | (fifolevel >> 8) | @@ -2711,7 +2741,7 @@ u16 Read16(u32 addr) { Run(); - u32 fifolevel = CmdFIFO->Level(); + u32 fifolevel = CmdFIFO.Level(); return (GXStat >> 16) | fifolevel | @@ -2747,7 +2777,7 @@ u32 Read32(u32 addr) { Run(); - u32 fifolevel = CmdFIFO->Level(); + u32 fifolevel = CmdFIFO.Level(); return GXStat | ((PosMatrixStackPointer & 0x1F) << 8) | diff --git a/src/GPU3D.h b/src/GPU3D.h index 69b67fa7..62fe92c9 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -25,7 +25,7 @@ namespace GPU3D { -typedef struct +struct Vertex { s32 Position[4]; s32 Color[3]; @@ -43,9 +43,9 @@ typedef struct // TODO maybe: hi-res color? (that survives clipping) s32 HiresPosition[2]; -} Vertex; +}; -typedef struct +struct Polygon { Vertex* Vertices[10]; u32 NumVertices; @@ -74,7 +74,7 @@ typedef struct u32 SortKey; -} Polygon; +}; extern u32 RenderDispCnt; extern u8 RenderAlphaRef; diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index 88ae77a9..eb8fa62e 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -70,7 +70,7 @@ struct GLuint ShaderConfigUBO; -typedef struct +struct RendererPolygon { Polygon* PolyData; @@ -82,8 +82,7 @@ typedef struct u32 EdgeIndicesOffset; u32 RenderKey; - -} RendererPolygon; +}; RendererPolygon PolygonList[2048]; int NumFinalPolys, NumOpaqueFinalPolys; diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index d66eb76e..7fcafb18 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -538,7 +538,7 @@ private: s32 ycoverage, ycov_incr; }; -typedef struct +struct RendererPolygon { Polygon* PolyData; @@ -548,7 +548,7 @@ typedef struct u32 CurVL, CurVR; u32 NextVL, NextVR; -} RendererPolygon; +}; RendererPolygon PolygonList[2048]; diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp index 0c6cf004..fb04ca01 100644 --- a/src/GPU_OpenGL.cpp +++ b/src/GPU_OpenGL.cpp @@ -40,7 +40,13 @@ GLuint Comp3DXPosLoc[1]; GLuint CompVertexBufferID; GLuint CompVertexArrayID; -float CompVertices[2 * 3*2 * 2]; // position + +struct CompVertex +{ + float Position[2]; + float Texcoord[2]; +}; +CompVertex CompVertices[2 * 3*2]; GLuint CompScreenInputTex; GLuint CompScreenOutputTex; @@ -59,6 +65,7 @@ bool Init() GLint uni_id; glBindAttribLocation(CompShader[i][2], 0, "vPosition"); + glBindAttribLocation(CompShader[i][2], 1, "vTexcoord"); glBindFragDataLocation(CompShader[i][2], 0, "oColor"); if (!OpenGL::LinkShaderProgram(CompShader[i])) @@ -74,25 +81,29 @@ bool Init() glUniform1i(uni_id, 1); } -#define SETVERTEX(i, x, y) \ - CompVertices[2*(i) + 0] = x; \ - CompVertices[2*(i) + 1] = y; + // all this mess is to prevent bleeding +#define SETVERTEX(i, x, y, offset) \ + CompVertices[i].Position[0] = x; \ + CompVertices[i].Position[1] = y + offset; \ + CompVertices[i].Texcoord[0] = (x + 1.f) * (256.f / 2.f); \ + CompVertices[i].Texcoord[1] = (y + 1.f) * (384.f / 2.f) + const float padOffset = 1.f/(192*2.f+2.f)*2.f; // top screen - SETVERTEX(0, -1, 1); - SETVERTEX(1, 1, 0); - SETVERTEX(2, 1, 1); - SETVERTEX(3, -1, 1); - SETVERTEX(4, -1, 0); - SETVERTEX(5, 1, 0); + SETVERTEX(0, -1, 1, 0); + SETVERTEX(1, 1, 0, padOffset); + SETVERTEX(2, 1, 1, 0); + SETVERTEX(3, -1, 1, 0); + SETVERTEX(4, -1, 0, padOffset); + SETVERTEX(5, 1, 0, padOffset); // bottom screen - SETVERTEX(6, -1, 0); - SETVERTEX(7, 1, -1); - SETVERTEX(8, 1, 0); - SETVERTEX(9, -1, 0); - SETVERTEX(10, -1, -1); - SETVERTEX(11, 1, -1); + SETVERTEX(6, -1, 0, -padOffset); + SETVERTEX(7, 1, -1, 0); + SETVERTEX(8, 1, 0, -padOffset); + SETVERTEX(9, -1, 0, -padOffset); + SETVERTEX(10, -1, -1, 0); + SETVERTEX(11, 1, -1, 0); #undef SETVERTEX @@ -103,7 +114,9 @@ bool Init() glGenVertexArrays(1, &CompVertexArrayID); glBindVertexArray(CompVertexArrayID); glEnableVertexAttribArray(0); // position - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*4, (void*)(0)); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CompVertex), (void*)(offsetof(CompVertex, Position))); + glEnableVertexAttribArray(1); // texcoord + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(CompVertex), (void*)(offsetof(CompVertex, Texcoord))); glGenFramebuffers(1, &CompScreenOutputFB); @@ -152,10 +165,14 @@ void SetRenderSettings(RenderSettings& settings) Scale = scale; ScreenW = 256 * scale; - ScreenH = 384 * scale; + ScreenH = (384+2) * scale; glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + // fill the padding + u8 zeroPixels[ScreenW*2*scale*4]; + memset(zeroPixels, 0, sizeof(zeroPixels)); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192*scale, ScreenW, 2*scale, GL_RGBA, GL_UNSIGNED_BYTE, zeroPixels); GLenum fbassign[] = {GL_COLOR_ATTACHMENT0}; glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB); diff --git a/src/GPU_OpenGL_shaders.h b/src/GPU_OpenGL_shaders.h index 03ddb7af..44be4d05 100644 --- a/src/GPU_OpenGL_shaders.h +++ b/src/GPU_OpenGL_shaders.h @@ -22,6 +22,7 @@ const char* kCompositorVS = R"(#version 140 in vec2 vPosition; +in vec2 vTexcoord; smooth out vec2 fTexcoord; @@ -33,7 +34,7 @@ void main() fpos.w = 1.0; gl_Position = fpos; - fTexcoord = (vPosition + vec2(1.0, 1.0)) * (vec2(256.0, 384.0) / 2.0); + fTexcoord = vTexcoord; } )"; diff --git a/src/NDS.cpp b/src/NDS.cpp index 8b49328f..7131bae0 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -139,8 +139,8 @@ u32 DMA9Fill[4]; u16 IPCSync9, IPCSync7; u16 IPCFIFOCnt9, IPCFIFOCnt7; -FIFO* IPCFIFO9; // FIFO in which the ARM9 writes -FIFO* IPCFIFO7; +FIFO IPCFIFO9; // FIFO in which the ARM9 writes +FIFO IPCFIFO7; u16 DivCnt; u32 DivNumerator[2]; @@ -190,9 +190,6 @@ bool Init() DMAs[6] = new DMA(1, 2); DMAs[7] = new DMA(1, 3); - IPCFIFO9 = new FIFO(16); - IPCFIFO7 = new FIFO(16); - if (!NDSCart::Init()) return false; if (!GBACart::Init()) return false; if (!GPU::Init()) return false; @@ -220,9 +217,6 @@ void DeInit() for (int i = 0; i < 8; i++) delete DMAs[i]; - delete IPCFIFO9; - delete IPCFIFO7; - NDSCart::DeInit(); GBACart::DeInit(); GPU::DeInit(); @@ -557,8 +551,8 @@ void Reset() IPCSync7 = 0; IPCFIFOCnt9 = 0; IPCFIFOCnt7 = 0; - IPCFIFO9->Clear(); - IPCFIFO7->Clear(); + IPCFIFO9.Clear(); + IPCFIFO7.Clear(); DivCnt = 0; SqrtCnt = 0; @@ -736,8 +730,8 @@ bool DoSavestate(Savestate* file) file->Var16(&IPCSync7); file->Var16(&IPCFIFOCnt9); file->Var16(&IPCFIFOCnt7); - IPCFIFO9->DoSavestate(file); - IPCFIFO7->DoSavestate(file); + IPCFIFO9.DoSavestate(file); + IPCFIFO7.DoSavestate(file); file->Var16(&DivCnt); file->Var16(&SqrtCnt); @@ -1881,7 +1875,7 @@ u8 ARM9Read8(u32 addr) case 0x05000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; - return *(u8*)&GPU::Palette[addr & 0x7FF]; + return GPU::ReadPalette(addr); case 0x06000000: switch (addr & 0x00E00000) @@ -1895,7 +1889,7 @@ u8 ARM9Read8(u32 addr) case 0x07000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; - return *(u8*)&GPU::OAM[addr & 0x7FF]; + return GPU::ReadOAM(addr); case 0x08000000: case 0x09000000: @@ -1946,7 +1940,7 @@ u16 ARM9Read16(u32 addr) case 0x05000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; - return *(u16*)&GPU::Palette[addr & 0x7FF]; + return GPU::ReadPalette(addr); case 0x06000000: switch (addr & 0x00E00000) @@ -1960,7 +1954,7 @@ u16 ARM9Read16(u32 addr) case 0x07000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; - return *(u16*)&GPU::OAM[addr & 0x7FF]; + return GPU::ReadOAM(addr); case 0x08000000: case 0x09000000: @@ -2011,7 +2005,7 @@ u32 ARM9Read32(u32 addr) case 0x05000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; - return *(u32*)&GPU::Palette[addr & 0x7FF]; + return GPU::ReadPalette(addr); case 0x06000000: switch (addr & 0x00E00000) @@ -2025,7 +2019,7 @@ u32 ARM9Read32(u32 addr) case 0x07000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return 0; - return *(u32*)&GPU::OAM[addr & 0x7FF]; + return GPU::ReadOAM(addr & 0x7FF); case 0x08000000: case 0x09000000: @@ -2132,7 +2126,7 @@ void ARM9Write16(u32 addr, u16 val) case 0x05000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; - *(u16*)&GPU::Palette[addr & 0x7FF] = val; + GPU::WritePalette(addr, val); return; case 0x06000000: @@ -2150,7 +2144,7 @@ void ARM9Write16(u32 addr, u16 val) case 0x07000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; - *(u16*)&GPU::OAM[addr & 0x7FF] = val; + GPU::WriteOAM(addr, val); return; case 0x08000000: @@ -2207,7 +2201,7 @@ void ARM9Write32(u32 addr, u32 val) case 0x05000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; - *(u32*)&GPU::Palette[addr & 0x7FF] = val; + GPU::WritePalette(addr, val); return; case 0x06000000: @@ -2225,7 +2219,7 @@ void ARM9Write32(u32 addr, u32 val) case 0x07000000: if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; - *(u32*)&GPU::OAM[addr & 0x7FF] = val; + GPU::WriteOAM(addr, val); return; case 0x08000000: @@ -2899,10 +2893,10 @@ u16 ARM9IORead16(u32 addr) case 0x04000184: { u16 val = IPCFIFOCnt9; - if (IPCFIFO9->IsEmpty()) val |= 0x0001; - else if (IPCFIFO9->IsFull()) val |= 0x0002; - if (IPCFIFO7->IsEmpty()) val |= 0x0100; - else if (IPCFIFO7->IsFull()) val |= 0x0200; + if (IPCFIFO9.IsEmpty()) val |= 0x0001; + else if (IPCFIFO9.IsFull()) val |= 0x0002; + if (IPCFIFO7.IsEmpty()) val |= 0x0100; + else if (IPCFIFO7.IsFull()) val |= 0x0200; return val; } @@ -3057,22 +3051,22 @@ u32 ARM9IORead32(u32 addr) if (IPCFIFOCnt9 & 0x8000) { u32 ret; - if (IPCFIFO7->IsEmpty()) + if (IPCFIFO7.IsEmpty()) { IPCFIFOCnt9 |= 0x4000; - ret = IPCFIFO7->Peek(); + ret = IPCFIFO7.Peek(); } else { - ret = IPCFIFO7->Read(); + ret = IPCFIFO7.Read(); - if (IPCFIFO7->IsEmpty() && (IPCFIFOCnt7 & 0x0004)) + if (IPCFIFO7.IsEmpty() && (IPCFIFOCnt7 & 0x0004)) SetIRQ(1, IRQ_IPCSendDone); } return ret; } else - return IPCFIFO7->Peek(); + return IPCFIFO7.Peek(); case 0x04100010: if (!(ExMemCnt[0] & (1<<11))) return NDSCart::ReadROMData(); @@ -3238,10 +3232,10 @@ void ARM9IOWrite16(u32 addr, u16 val) case 0x04000184: if (val & 0x0008) - IPCFIFO9->Clear(); - if ((val & 0x0004) && (!(IPCFIFOCnt9 & 0x0004)) && IPCFIFO9->IsEmpty()) + IPCFIFO9.Clear(); + if ((val & 0x0004) && (!(IPCFIFOCnt9 & 0x0004)) && IPCFIFO9.IsEmpty()) SetIRQ(0, IRQ_IPCSendDone); - if ((val & 0x0400) && (!(IPCFIFOCnt9 & 0x0400)) && (!IPCFIFO7->IsEmpty())) + if ((val & 0x0400) && (!(IPCFIFOCnt9 & 0x0400)) && (!IPCFIFO7.IsEmpty())) SetIRQ(0, IRQ_IPCRecv); if (val & 0x4000) IPCFIFOCnt9 &= ~0x4000; @@ -3407,12 +3401,12 @@ void ARM9IOWrite32(u32 addr, u32 val) case 0x04000188: if (IPCFIFOCnt9 & 0x8000) { - if (IPCFIFO9->IsFull()) + if (IPCFIFO9.IsFull()) IPCFIFOCnt9 |= 0x4000; else { - bool wasempty = IPCFIFO9->IsEmpty(); - IPCFIFO9->Write(val); + bool wasempty = IPCFIFO9.IsEmpty(); + IPCFIFO9.Write(val); if ((IPCFIFOCnt7 & 0x0400) && wasempty) SetIRQ(1, IRQ_IPCRecv); } @@ -3590,10 +3584,10 @@ u16 ARM7IORead16(u32 addr) case 0x04000184: { u16 val = IPCFIFOCnt7; - if (IPCFIFO7->IsEmpty()) val |= 0x0001; - else if (IPCFIFO7->IsFull()) val |= 0x0002; - if (IPCFIFO9->IsEmpty()) val |= 0x0100; - else if (IPCFIFO9->IsFull()) val |= 0x0200; + if (IPCFIFO7.IsEmpty()) val |= 0x0001; + else if (IPCFIFO7.IsFull()) val |= 0x0002; + if (IPCFIFO9.IsEmpty()) val |= 0x0100; + else if (IPCFIFO9.IsFull()) val |= 0x0200; return val; } @@ -3689,22 +3683,22 @@ u32 ARM7IORead32(u32 addr) if (IPCFIFOCnt7 & 0x8000) { u32 ret; - if (IPCFIFO9->IsEmpty()) + if (IPCFIFO9.IsEmpty()) { IPCFIFOCnt7 |= 0x4000; - ret = IPCFIFO9->Peek(); + ret = IPCFIFO9.Peek(); } else { - ret = IPCFIFO9->Read(); + ret = IPCFIFO9.Read(); - if (IPCFIFO9->IsEmpty() && (IPCFIFOCnt9 & 0x0004)) + if (IPCFIFO9.IsEmpty() && (IPCFIFOCnt9 & 0x0004)) SetIRQ(0, IRQ_IPCSendDone); } return ret; } else - return IPCFIFO9->Peek(); + return IPCFIFO9.Peek(); case 0x04100010: if (ExMemCnt[0] & (1<<11)) return NDSCart::ReadROMData(); @@ -3841,10 +3835,10 @@ void ARM7IOWrite16(u32 addr, u16 val) case 0x04000184: if (val & 0x0008) - IPCFIFO7->Clear(); - if ((val & 0x0004) && (!(IPCFIFOCnt7 & 0x0004)) && IPCFIFO7->IsEmpty()) + IPCFIFO7.Clear(); + if ((val & 0x0004) && (!(IPCFIFOCnt7 & 0x0004)) && IPCFIFO7.IsEmpty()) SetIRQ(1, IRQ_IPCSendDone); - if ((val & 0x0400) && (!(IPCFIFOCnt7 & 0x0400)) && (!IPCFIFO9->IsEmpty())) + if ((val & 0x0400) && (!(IPCFIFOCnt7 & 0x0400)) && (!IPCFIFO9.IsEmpty())) SetIRQ(1, IRQ_IPCRecv); if (val & 0x4000) IPCFIFOCnt7 &= ~0x4000; @@ -3977,12 +3971,12 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x04000188: if (IPCFIFOCnt7 & 0x8000) { - if (IPCFIFO7->IsFull()) + if (IPCFIFO7.IsFull()) IPCFIFOCnt7 |= 0x4000; else { - bool wasempty = IPCFIFO7->IsEmpty(); - IPCFIFO7->Write(val); + bool wasempty = IPCFIFO7.IsEmpty(); + IPCFIFO7.Write(val); if ((IPCFIFOCnt9 & 0x0400) && wasempty) SetIRQ(0, IRQ_IPCRecv); } diff --git a/src/NDS.h b/src/NDS.h index 98a0f7d6..46a57a49 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -54,13 +54,12 @@ enum Event_MAX }; -typedef struct +struct SchedEvent { void (*Func)(u32 param); u64 Timestamp; u32 Param; - -} SchedEvent; +}; enum { @@ -121,21 +120,19 @@ enum IRQ2_DSi_MicExt }; -typedef struct +struct Timer { u16 Reload; u16 Cnt; u32 Counter; u32 CycleShift; +}; -} Timer; - -typedef struct +struct MemRegion { u8* Mem; u32 Mask; - -} MemRegion; +}; extern int ConsoleType; extern int CurCPU; diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 2d8396ad..fa235a4e 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -22,7 +22,6 @@ #include "DSi.h" #include "NDSCart.h" #include "ARM.h" -#include "CRC32.h" #include "DSi_AES.h" #include "Platform.h" #include "Config.h" @@ -485,7 +484,6 @@ u8 TransferCmd[8]; bool CartInserted; u8* CartROM; u32 CartROMSize; -u32 CartCRC; u32 CartID; bool CartIsHomebrew; bool CartIsDSi; @@ -932,9 +930,6 @@ bool LoadROM(const char* path, const char* sram, bool direct) fclose(f); //CartROM = f; - CartCRC = CRC32(CartROM, CartROMSize); - printf("ROM CRC32: %08X\n", CartCRC); - ROMListEntry romparams; if (!ReadROMParams(gamecode, &romparams)) { diff --git a/src/ROMList.h b/src/ROMList.h index 03252bb0..685d8a5e 100644 --- a/src/ROMList.h +++ b/src/ROMList.h @@ -19,13 +19,12 @@ #ifndef ROMLIST_H #define ROMLIST_H -typedef struct +struct ROMListEntry { u32 GameCode; u32 ROMSize; u32 SaveMemType; - -} ROMListEntry; +}; ROMListEntry ROMList[] = @@ -4006,6 +4005,7 @@ ROMListEntry ROMList[] = {0x4A555143, 0x02000000, 0x00000002}, {0x4A555159, 0x08000000, 0x00000003}, {0x4A555241, 0x02000000, 0x00000003}, + {0x4A555243, 0x10000000, 0x00000006}, {0x4A555259, 0x00800000, 0x00000001}, {0x4A555341, 0x04000000, 0x00000003}, {0x4A555359, 0x00800000, 0x00000003}, diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 29570076..4502f18c 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -55,7 +55,7 @@ u16 RFData1; u16 RFData2; u32 RFRegs[0x40]; -typedef struct +struct TXSlot { u16 Addr; u16 Length; @@ -63,8 +63,7 @@ typedef struct u8 CurPhase; u32 CurPhaseTime; u32 HalfwordTimeMask; - -} TXSlot; +}; TXSlot TXSlots[6]; diff --git a/src/dolphin/Arm64Emitter.cpp b/src/dolphin/Arm64Emitter.cpp index 289b20c5..ae6258d3 100644 --- a/src/dolphin/Arm64Emitter.cpp +++ b/src/dolphin/Arm64Emitter.cpp @@ -15,6 +15,10 @@ #include "../types.h" #include "MathUtil.h" +#ifdef __APPLE__ + #include +#endif + namespace Arm64Gen { namespace @@ -384,7 +388,7 @@ void ARM64XEmitter::FlushIcacheSection(u8* start, u8* end) if (start == end) return; -#if defined(IOS) +#if defined(__APPLE__) // Header file says this is equivalent to: sys_icache_invalidate(start, end - start); sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); #else diff --git a/src/frontend/qt_sdl/LAN_PCap.h b/src/frontend/qt_sdl/LAN_PCap.h index 250b8e90..f636e128 100644 --- a/src/frontend/qt_sdl/LAN_PCap.h +++ b/src/frontend/qt_sdl/LAN_PCap.h @@ -24,7 +24,7 @@ namespace LAN_PCap { -typedef struct +struct AdapterData { char DeviceName[128]; char FriendlyName[128]; @@ -34,8 +34,7 @@ typedef struct u8 IP_v4[4]; void* Internal; - -} AdapterData; +}; extern AdapterData* Adapters; diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 458c931d..c147e690 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -48,7 +48,7 @@ const u32 kClientIP = kSubnet | 0x10; const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44}; -FIFO* RXBuffer = nullptr; +FIFO> 2)> RXBuffer; u32 IPv4ID; @@ -86,16 +86,16 @@ void RXEnqueue(const void* buf, int len) int alignedlen = (len + 3) & ~3; int totallen = alignedlen + 4; - if (!RXBuffer->CanFit(totallen >> 2)) + if (!RXBuffer.CanFit(totallen >> 2)) { printf("slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n"); return; } u32 header = (alignedlen & 0xFFFF) | (len << 16); - RXBuffer->Write(header); + RXBuffer.Write(header); for (int i = 0; i < alignedlen; i += 4) - RXBuffer->Write(((u32*)buf)[i>>2]); + RXBuffer.Write(((u32*)buf)[i>>2]); } ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) @@ -202,8 +202,6 @@ bool Init() //FDListSize = 0; //memset(FDList, 0, sizeof(FDList)); - RXBuffer = new FIFO(0x8000 >> 2); - SlirpConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.version = 1; @@ -228,12 +226,6 @@ void DeInit() slirp_cleanup(Ctx); Ctx = nullptr; } - - if (RXBuffer) - { - delete RXBuffer; - RXBuffer = nullptr; - } } @@ -530,13 +522,13 @@ int RecvPacket(u8* data) slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr); } - if (!RXBuffer->IsEmpty()) + if (!RXBuffer.IsEmpty()) { - u32 header = RXBuffer->Read(); + u32 header = RXBuffer.Read(); u32 len = header & 0xFFFF; for (int i = 0; i < len; i += 4) - ((u32*)data)[i>>2] = RXBuffer->Read(); + ((u32*)data)[i>>2] = RXBuffer.Read(); ret = header >> 16; } diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index 98616623..46f8717f 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -72,6 +72,8 @@ char MicWavPath[1024]; char LastROMFolder[1024]; +char RecentROMList[10][1024]; + int EnableCheats; bool EnableJIT; @@ -166,6 +168,17 @@ ConfigEntry PlatformConfigFile[] = {"LastROMFolder", 1, LastROMFolder, 0, "", 1023}, + {"RecentROM_0", 1, RecentROMList[0], 0, "", 1023}, + {"RecentROM_1", 1, RecentROMList[1], 0, "", 1023}, + {"RecentROM_2", 1, RecentROMList[2], 0, "", 1023}, + {"RecentROM_3", 1, RecentROMList[3], 0, "", 1023}, + {"RecentROM_4", 1, RecentROMList[4], 0, "", 1023}, + {"RecentROM_5", 1, RecentROMList[5], 0, "", 1023}, + {"RecentROM_6", 1, RecentROMList[6], 0, "", 1023}, + {"RecentROM_7", 1, RecentROMList[7], 0, "", 1023}, + {"RecentROM_8", 1, RecentROMList[8], 0, "", 1023}, + {"RecentROM_9", 1, RecentROMList[9], 0, "", 1023}, + {"EnableCheats", 0, &EnableCheats, 0, NULL, 0}, {"", -1, NULL, 0, NULL, 0} diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h index ca03d80b..2d73dea0 100644 --- a/src/frontend/qt_sdl/PlatformConfig.h +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -86,6 +86,8 @@ extern char MicWavPath[1024]; extern char LastROMFolder[1024]; +extern char RecentROMList[10][1024]; + extern int EnableCheats; } diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index 1397ccd9..934090de 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -84,6 +84,14 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( ui->cbxGLResolution->setEnabled(true); ui->cbBetterPolygons->setEnabled(true); } + + // sorry + ui->cbVSync->hide(); + ui->cbVSync->setEnabled(false); + ui->sbVSyncInterval->hide(); + ui->sbVSyncInterval->setEnabled(false); + ui->label_2->hide(); + ui->groupBox->layout()->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); } VideoSettingsDialog::~VideoSettingsDialog() diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index a4730627..91e56f0a 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -875,22 +875,26 @@ void ScreenPanelGL::initializeGL() screenShader->setUniformValue("ScreenTex", (GLint)0); screenShader->release(); + // to prevent bleeding between both parts of the screen + // with bilinear filtering enabled + const int paddedHeight = 192*2+2; + const float padPixels = 1.f / paddedHeight; - float vertices[] = + const float vertices[] = { - 0, 0, 0, 0, - 0, 192, 0, 0.5, - 256, 192, 1, 0.5, - 0, 0, 0, 0, - 256, 192, 1, 0.5, - 256, 0, 1, 0, + 0.f, 0.f, 0.f, 0.f, + 0.f, 192.f, 0.f, 0.5f - padPixels, + 256.f, 192.f, 1.f, 0.5f - padPixels, + 0.f, 0.f, 0.f, 0.f, + 256.f, 192.f, 1.f, 0.5f - padPixels, + 256.f, 0.f, 1.f, 0.f, - 0, 0, 0, 0.5, - 0, 192, 0, 1, - 256, 192, 1, 1, - 0, 0, 0, 0.5, - 256, 192, 1, 1, - 256, 0, 1, 0.5 + 0.f, 0.f, 0.f, 0.5f + padPixels, + 0.f, 192.f, 0.f, 1.f, + 256.f, 192.f, 1.f, 1.f, + 0.f, 0.f, 0.f, 0.5f + padPixels, + 256.f, 192.f, 1.f, 1.f, + 256.f, 0.f, 1.f, 0.5f + padPixels }; glGenBuffers(1, &screenVertexBuffer); @@ -911,7 +915,11 @@ void ScreenPanelGL::initializeGL() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, paddedHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + // fill the padding + u8 zeroData[256*4*4]; + memset(zeroData, 0, sizeof(zeroData)); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 2, GL_RGBA, GL_UNSIGNED_BYTE, zeroData); OSD::Init(this); } @@ -949,7 +957,7 @@ void ScreenPanelGL::paintGL() { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA, GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA, + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA, GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); } } @@ -1021,6 +1029,14 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actOpenROM = menu->addAction("Open ROM..."); connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile); + recentMenu = menu->addMenu("Open Recent"); + for(int i = 0; i < 10; ++i) + { + if(strlen(Config::RecentROMList[i]) > 0) + recentFileList.push_back(Config::RecentROMList[i]); + } + updateRecentFilesMenu(); + //actBootFirmware = menu->addAction("Launch DS menu"); actBootFirmware = menu->addAction("Boot firmware"); connect(actBootFirmware, &QAction::triggered, this, &MainWindow::onBootFirmware); @@ -1333,7 +1349,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event) if (event->isAutoRepeat()) return; // TODO!! REMOVE ME IN RELEASE BUILDS!! - if (event->key() == Qt::Key_F11) NDS::debug(0); + //if (event->key() == Qt::Key_F11) NDS::debug(0); Input::KeyPress(event); } @@ -1457,7 +1473,20 @@ void MainWindow::onOpenFile() "Open ROM", Config::LastROMFolder, "DS ROMs (*.nds *.dsi *.srl *.zip *.7z);;GBA ROMs (*.gba *.zip *.7z);;Other Compressed ROMs (*.zip *.7z *.rar *.tar *.tar.gz *.tar.xz *tar.bz2);;Any file (*.*)"); + + if (filename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } +void MainWindow::loadROM(QString filename) +{ + recentFileList.removeAll(filename); + recentFileList.prepend(filename); + updateRecentFilesMenu(); + + static const QSet compressedExts = {"zip", "7z", "rar", "tar", "tar.gz", "tar.xz", "tar.bz2"}; if (compressedExts.contains(QFileInfo(filename).completeSuffix())) { @@ -1502,13 +1531,7 @@ void MainWindow::onOpenFile() } } - - if (filename.isEmpty()) - { - emuThread->emuUnpause(); - return; - } - + // TODO: validate the input file!! // * check that it is a proper ROM // * ensure the binary offsets are sane @@ -1554,6 +1577,60 @@ void MainWindow::onOpenFile() } } +void MainWindow::onOpenFile() +{ + emuThread->emuPause(); + + QString filename = QFileDialog::getOpenFileName(this, + "Open ROM", + Config::LastROMFolder, + "DS ROMs (*.nds *.dsi *.srl);;GBA ROMs (*.gba);;Any file (*.*)"); + if (filename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + loadROM(filename); +} + +void MainWindow::onClearRecentFiles() +{ + recentFileList.clear(); + memset(Config::RecentROMList, 0, 10 * 1024); + updateRecentFilesMenu(); +} + +void MainWindow::updateRecentFilesMenu() +{ + recentMenu->clear(); + + for(int i = 0; i < recentFileList.size(); ++i) + { + QAction *actRecentFile_i = recentMenu->addAction(QString("%1. %2").arg(i+1).arg(recentFileList.at(i))); + actRecentFile_i->setData(recentFileList.at(i)); + connect(actRecentFile_i, &QAction::triggered, this, &MainWindow::onClickRecentFile); + + if(i < 10) + strncpy(Config::RecentROMList[i], recentFileList.at(i).toStdString().c_str(), 1024); + } + + QAction *actClearRecentList = recentMenu->addAction("Clear"); + connect(actClearRecentList, &QAction::triggered, this, &MainWindow::onClearRecentFiles); + + if(recentFileList.empty()) + actClearRecentList->setEnabled(false); + + Config::Save(); +} + +void MainWindow::onClickRecentFile() +{ + emuThread->emuPause(); + QAction *act = (QAction *)sender(); + loadROM(act->data().toString()); +} + void MainWindow::onBootFirmware() { // TODO: check the whole GBA cart shito diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 978df9e2..d31e7069 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -191,6 +191,8 @@ signals: private slots: void onOpenFile(); + void onClickRecentFile(); + void onClearRecentFiles(); void onBootFirmware(); void onSaveState(); void onLoadState(); @@ -236,6 +238,11 @@ private slots: void onFullscreenToggled(); private: + QList recentFileList; + QMenu *recentMenu; + void updateRecentFilesMenu(); + void loadROM(QString filename); + void createScreenPanel(); QString loadErrorStr(int error); diff --git a/src/version.h b/src/version.h index f0498d7f..54f60dfa 100644 --- a/src/version.h +++ b/src/version.h @@ -19,7 +19,7 @@ #ifndef VERSION_H #define VERSION_H -#define MELONDS_VERSION "0.9" +#define MELONDS_VERSION "0.9.1" #define MELONDS_URL "http://melonds.kuribo64.net/"