diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 1d4b9171..4178157d 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v3 - name: Install dependencies for package building run: | - brew install autoconf automake autoconf-archive libtool && pip3 install setuptools + brew install autoconf automake autoconf-archive libtool python-setuptools - name: Set up CMake uses: lukka/get-cmake@latest - name: Set up vcpkg diff --git a/src/Args.h b/src/Args.h index d836b643..0b20bbf0 100644 --- a/src/Args.h +++ b/src/Args.h @@ -69,6 +69,10 @@ struct JITArgs bool FastMemory = true; }; +using ARM9BIOSImage = std::array; +using ARM7BIOSImage = std::array; +using DSiBIOSImage = std::array; + struct GDBArgs { u16 PortARM7 = 0; @@ -95,11 +99,11 @@ struct NDSArgs /// NDS ARM9 BIOS to install. /// Defaults to FreeBIOS, which is not compatible with DSi mode. - std::array ARM9BIOS = bios_arm9_bin; + std::unique_ptr ARM9BIOS = std::make_unique(bios_arm9_bin); /// NDS ARM7 BIOS to install. /// Defaults to FreeBIOS, which is not compatible with DSi mode. - std::array ARM7BIOS = bios_arm7_bin; + std::unique_ptr ARM7BIOS = std::make_unique(bios_arm7_bin); /// Firmware image to install. /// Defaults to generated NDS firmware. @@ -131,8 +135,8 @@ struct NDSArgs /// Contains no virtual methods, so there's no vtable. struct DSiArgs final : public NDSArgs { - std::array ARM9iBIOS = BrokenBIOS; - std::array ARM7iBIOS = BrokenBIOS; + std::unique_ptr ARM9iBIOS = std::make_unique(BrokenBIOS); + std::unique_ptr ARM7iBIOS = std::make_unique(BrokenBIOS); /// NAND image to install. /// Required, there is no default value. diff --git a/src/DSi.cpp b/src/DSi.cpp index c929c6d2..306c5d1c 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -82,8 +82,8 @@ DSi::DSi(DSiArgs&& args) noexcept : DSi_NDMA(1, 2, *this), DSi_NDMA(1, 3, *this), }, - ARM7iBIOS(args.ARM7iBIOS), - ARM9iBIOS(args.ARM9iBIOS), + ARM7iBIOS(*args.ARM7iBIOS), + ARM9iBIOS(*args.ARM9iBIOS), DSP(*this), SDMMC(*this, std::move(args.NANDImage), std::move(args.DSiSDCard)), SDIO(*this), diff --git a/src/FATStorage.cpp b/src/FATStorage.cpp index 0f1bf235..f735d4b8 100644 --- a/src/FATStorage.cpp +++ b/src/FATStorage.cpp @@ -110,6 +110,7 @@ bool FATStorage::InjectFile(const std::string& path, u8* data, u32 len) res = f_mount(&fs, "0:", 1); if (res != FR_OK) { + f_unmount("0:"); ff_disk_close(); return false; } @@ -146,6 +147,7 @@ u32 FATStorage::ReadFile(const std::string& path, u32 start, u32 len, u8* data) res = f_mount(&fs, "0:", 1); if (res != FR_OK) { + f_unmount("0:"); ff_disk_close(); return false; } @@ -1144,6 +1146,7 @@ bool FATStorage::Save() res = f_mount(&fs, "0:", 1); if (res != FR_OK) { + f_unmount("0:"); ff_disk_close(); return false; } diff --git a/src/NDS.cpp b/src/NDS.cpp index 1f9597ce..68227ea5 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -80,8 +80,8 @@ NDS::NDS() noexcept : NDSArgs { nullptr, nullptr, - bios_arm9_bin, - bios_arm7_bin, + std::make_unique(bios_arm9_bin), + std::make_unique(bios_arm7_bin), Firmware(0), } ) @@ -90,8 +90,8 @@ NDS::NDS() noexcept : NDS::NDS(NDSArgs&& args, int type) noexcept : ConsoleType(type), - ARM7BIOS(args.ARM7BIOS), - ARM9BIOS(args.ARM9BIOS), + ARM7BIOS(*args.ARM7BIOS), + ARM9BIOS(*args.ARM9BIOS), ARM7BIOSNative(CRC32(ARM7BIOS.data(), ARM7BIOS.size()) == ARM7BIOSCRC32), ARM9BIOSNative(CRC32(ARM9BIOS.data(), ARM9BIOS.size()) == ARM9BIOSCRC32), JIT(*this, args.JIT), @@ -1845,7 +1845,7 @@ void NDS::debug(u32 param) //for (int i = 0; i < 9; i++) // printf("VRAM %c: %02X\n", 'A'+i, GPU->VRAMCNT[i]); - Platform::FileHandle* shit = Platform::OpenFile("debug/DSfirmware.bin", FileMode::Write); + Platform::FileHandle* shit = Platform::OpenFile("debug/pokeplat.bin", FileMode::Write); Platform::FileWrite(ARM9.ITCM, 0x8000, 1, shit); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { diff --git a/src/SPU.cpp b/src/SPU.cpp index 86307097..69c0b9de 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -140,6 +140,41 @@ constexpr array2d InterpCubic = []() constexpr { return interp; }(); +const std::array InterpSNESGauss = { + 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, + 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x002, 0x002, 0x002, 0x002, 0x002, + 0x002, 0x002, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004, 0x004, 0x004, 0x004, 0x004, 0x005, 0x005, 0x005, 0x005, + 0x006, 0x006, 0x006, 0x006, 0x007, 0x007, 0x007, 0x008, 0x008, 0x008, 0x009, 0x009, 0x009, 0x00A, 0x00A, 0x00A, + 0x00B, 0x00B, 0x00B, 0x00C, 0x00C, 0x00D, 0x00D, 0x00E, 0x00E, 0x00F, 0x00F, 0x00F, 0x010, 0x010, 0x011, 0x011, + 0x012, 0x013, 0x013, 0x014, 0x014, 0x015, 0x015, 0x016, 0x017, 0x017, 0x018, 0x018, 0x019, 0x01A, 0x01B, 0x01B, + 0x01C, 0x01D, 0x01D, 0x01E, 0x01F, 0x020, 0x020, 0x021, 0x022, 0x023, 0x024, 0x024, 0x025, 0x026, 0x027, 0x028, + 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038, + 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x040, 0x041, 0x042, 0x043, 0x045, 0x046, 0x047, 0x049, 0x04A, 0x04C, 0x04D, + 0x04E, 0x050, 0x051, 0x053, 0x054, 0x056, 0x057, 0x059, 0x05A, 0x05C, 0x05E, 0x05F, 0x061, 0x063, 0x064, 0x066, + 0x068, 0x06A, 0x06B, 0x06D, 0x06F, 0x071, 0x073, 0x075, 0x076, 0x078, 0x07A, 0x07C, 0x07E, 0x080, 0x082, 0x084, + 0x086, 0x089, 0x08B, 0x08D, 0x08F, 0x091, 0x093, 0x096, 0x098, 0x09A, 0x09C, 0x09F, 0x0A1, 0x0A3, 0x0A6, 0x0A8, + 0x0AB, 0x0AD, 0x0AF, 0x0B2, 0x0B4, 0x0B7, 0x0BA, 0x0BC, 0x0BF, 0x0C1, 0x0C4, 0x0C7, 0x0C9, 0x0CC, 0x0CF, 0x0D2, + 0x0D4, 0x0D7, 0x0DA, 0x0DD, 0x0E0, 0x0E3, 0x0E6, 0x0E9, 0x0EC, 0x0EF, 0x0F2, 0x0F5, 0x0F8, 0x0FB, 0x0FE, 0x101, + 0x104, 0x107, 0x10B, 0x10E, 0x111, 0x114, 0x118, 0x11B, 0x11E, 0x122, 0x125, 0x129, 0x12C, 0x130, 0x133, 0x137, + 0x13A, 0x13E, 0x141, 0x145, 0x148, 0x14C, 0x150, 0x153, 0x157, 0x15B, 0x15F, 0x162, 0x166, 0x16A, 0x16E, 0x172, + 0x176, 0x17A, 0x17D, 0x181, 0x185, 0x189, 0x18D, 0x191, 0x195, 0x19A, 0x19E, 0x1A2, 0x1A6, 0x1AA, 0x1AE, 0x1B2, + 0x1B7, 0x1BB, 0x1BF, 0x1C3, 0x1C8, 0x1CC, 0x1D0, 0x1D5, 0x1D9, 0x1DD, 0x1E2, 0x1E6, 0x1EB, 0x1EF, 0x1F3, 0x1F8, + 0x1FC, 0x201, 0x205, 0x20A, 0x20F, 0x213, 0x218, 0x21C, 0x221, 0x226, 0x22A, 0x22F, 0x233, 0x238, 0x23D, 0x241, + 0x246, 0x24B, 0x250, 0x254, 0x259, 0x25E, 0x263, 0x267, 0x26C, 0x271, 0x276, 0x27B, 0x280, 0x284, 0x289, 0x28E, + 0x293, 0x298, 0x29D, 0x2A2, 0x2A6, 0x2AB, 0x2B0, 0x2B5, 0x2BA, 0x2BF, 0x2C4, 0x2C9, 0x2CE, 0x2D3, 0x2D8, 0x2DC, + 0x2E1, 0x2E6, 0x2EB, 0x2F0, 0x2F5, 0x2FA, 0x2FF, 0x304, 0x309, 0x30E, 0x313, 0x318, 0x31D, 0x322, 0x326, 0x32B, + 0x330, 0x335, 0x33A, 0x33F, 0x344, 0x349, 0x34E, 0x353, 0x357, 0x35C, 0x361, 0x366, 0x36B, 0x370, 0x374, 0x379, + 0x37E, 0x383, 0x388, 0x38C, 0x391, 0x396, 0x39B, 0x39F, 0x3A4, 0x3A9, 0x3AD, 0x3B2, 0x3B7, 0x3BB, 0x3C0, 0x3C5, + 0x3C9, 0x3CE, 0x3D2, 0x3D7, 0x3DC, 0x3E0, 0x3E5, 0x3E9, 0x3ED, 0x3F2, 0x3F6, 0x3FB, 0x3FF, 0x403, 0x408, 0x40C, + 0x410, 0x415, 0x419, 0x41D, 0x421, 0x425, 0x42A, 0x42E, 0x432, 0x436, 0x43A, 0x43E, 0x442, 0x446, 0x44A, 0x44E, + 0x452, 0x455, 0x459, 0x45D, 0x461, 0x465, 0x468, 0x46C, 0x470, 0x473, 0x477, 0x47A, 0x47E, 0x481, 0x485, 0x488, + 0x48C, 0x48F, 0x492, 0x496, 0x499, 0x49C, 0x49F, 0x4A2, 0x4A6, 0x4A9, 0x4AC, 0x4AF, 0x4B2, 0x4B5, 0x4B7, 0x4BA, + 0x4BD, 0x4C0, 0x4C3, 0x4C5, 0x4C8, 0x4CB, 0x4CD, 0x4D0, 0x4D2, 0x4D5, 0x4D7, 0x4D9, 0x4DC, 0x4DE, 0x4E0, 0x4E3, + 0x4E5, 0x4E7, 0x4E9, 0x4EB, 0x4ED, 0x4EF, 0x4F1, 0x4F3, 0x4F5, 0x4F6, 0x4F8, 0x4FA, 0x4FB, 0x4FD, 0x4FF, 0x500, + 0x502, 0x503, 0x504, 0x506, 0x507, 0x508, 0x50A, 0x50B, 0x50C, 0x50D, 0x50E, 0x50F, 0x510, 0x511, 0x511, 0x512, + 0x513, 0x514, 0x514, 0x515, 0x516, 0x516, 0x517, 0x517, 0x517, 0x518, 0x518, 0x518, 0x518, 0x518, 0x519, 0x519 +}; + SPU::SPU(melonDS::NDS& nds, AudioBitDepth bitdepth, AudioInterpolation interpolation) : NDS(nds), Channels { @@ -621,6 +656,19 @@ s32 SPUChannel::Run() (PrevSample[0] * InterpCubic[samplepos][2]) + (val * InterpCubic[samplepos][3])) >> 14; break; + + case AudioInterpolation::SNESGaussian: { + // Avoid clipping (from fullsnes) +#define CLAMP(s) (std::clamp((s) >> 1, -0x3FFA, 0x3FF8)) + s32 out = (InterpSNESGauss[0x0FF - samplepos] * CLAMP(PrevSample[2]) >> 10); + out = out + ((InterpSNESGauss[0x1FF - samplepos] * CLAMP(PrevSample[1])) >> 10); + out = out + ((InterpSNESGauss[0x100 + samplepos] * CLAMP(PrevSample[0])) >> 10); + out = out + ((InterpSNESGauss[0x000 + samplepos] * CLAMP(val)) >> 10); + val = std::clamp(out, -0x8000, 0x7FFF); +#undef CLAMP + break; + } + default: break; } @@ -1257,4 +1305,4 @@ void SPU::Write32(u32 addr, u32 val) } } -} \ No newline at end of file +} diff --git a/src/SPU.h b/src/SPU.h index b2b05ac7..6e3d1aae 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -40,6 +40,7 @@ enum class AudioInterpolation Linear, Cosine, Cubic, + SNESGaussian }; class SPUChannel diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 4da253ef..d8f440b4 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -159,11 +159,45 @@ void Wifi::Reset() #undef BBREG_FIXED const Firmware& fw = NDS.SPI.GetFirmware(); + const auto& fwheader = fw.GetHeader(); - RFVersion = fw.GetHeader().RFChipType; + RFVersion = fwheader.RFChipType; memset(RFRegs, 0, 4*0x40); - Firmware::FirmwareConsoleType console = fw.GetHeader().ConsoleType; + // load channel index/data from the firmware + // the current channel will be determined by RF settings + // so we compare the two 'most important' RF registers to these values to figure out which channel is selected + + if (RFVersion == 3) + { + RFChannelIndex[0] = fwheader.Type3Config.RFIndex1; + RFChannelIndex[1] = fwheader.Type3Config.RFIndex2; + + for (int i = 0; i < 14; i++) + { + RFChannelData[i][0] = fwheader.Type3Config.RFData1[i]; + RFChannelData[i][1] = fwheader.Type3Config.RFData2[i]; + } + } + else + { + RFChannelIndex[0] = fwheader.Type2Config.InitialRF56Values[2] >> 2; + RFChannelIndex[1] = fwheader.Type2Config.InitialRF56Values[5] >> 2; + + for (int i = 0; i < 14; i++) + { + RFChannelData[i][0] = fwheader.Type2Config.InitialRF56Values[i*6 + 0] | + (fwheader.Type2Config.InitialRF56Values[i*6 + 1] << 8) | + ((fwheader.Type2Config.InitialRF56Values[i*6 + 2] & 0x03) << 16); + RFChannelData[i][1] = fwheader.Type2Config.InitialRF56Values[i*6 + 3] | + (fwheader.Type2Config.InitialRF56Values[i*6 + 4] << 8) | + ((fwheader.Type2Config.InitialRF56Values[i*6 + 5] & 0x03) << 16); + } + } + + CurChannel = 0; + + Firmware::FirmwareConsoleType console = fwheader.ConsoleType; if (console == Firmware::FirmwareConsoleType::DS) IOPORT(0x000) = 0x1440; else if (console == Firmware::FirmwareConsoleType::DSLite) @@ -182,6 +216,8 @@ void Wifi::Reset() // TODO: find out what the initial values are IOPORT(W_PowerUS) = 0x0001; + //IOPORT(W_BeaconInterval) = 100; + USTimestamp = 0; USCounter = 0; @@ -209,7 +245,6 @@ void Wifi::Reset() CmdCounter = 0; USUntilPowerOn = 0; - ForcePowerOn = false; IsMP = false; IsMPClient = false; @@ -244,6 +279,8 @@ void Wifi::DoSavestate(Savestate* file) file->Var8(&RFVersion); file->VarArray(RFRegs, 4*0x40); + file->Var32((u32*)&CurChannel); + file->Var64(&USCounter); file->Var64(&USCompare); file->Bool32(&BlockBeaconIRQ14); @@ -285,7 +322,6 @@ void Wifi::DoSavestate(Savestate* file) file->Var16(&MPLastSeqno); file->Var32((u32*)&USUntilPowerOn); - file->Bool32(&ForcePowerOn); file->Bool32(&IsMP); file->Bool32(&IsMPClient); @@ -351,33 +387,38 @@ void Wifi::SetPowerCnt(u32 val) } -void Wifi::SetIRQ(u32 irq) +void Wifi::CheckIRQ(u16 oldflags) { - u32 oldflags = IOPORT(W_IF) & IOPORT(W_IE); - - IOPORT(W_IF) |= (1<CurPhase = 13; slot->CurPhaseTime = CmdCounter - 100; } + + // starting a CMD transfer wakes up the transceiver automatically + UpdatePowerStatus(1); } void Wifi::StartTX_Beacon() @@ -678,6 +819,9 @@ void Wifi::SendMPDefaultReply() // TODO reply[0x8] = 0x14; + if (CurChannel == 0) return; + reply[0x9] = CurChannel; + *(u16*)&reply[0xC + 0x00] = 0x0158; *(u16*)&reply[0xC + 0x02] = 0x00F0;//0; // TODO?? *(u16*)&reply[0xC + 0x04] = IOPORT(W_BSSID0); @@ -767,6 +911,9 @@ void Wifi::SendMPAck(u16 cmdcount, u16 clientfail) if (TXSlots[1].Rate == 2) ack[0x8] = 0x14; else ack[0x8] = 0xA; + if (CurChannel == 0) return; + ack[0x9] = CurChannel; + *(u16*)&ack[0xC + 0x00] = 0x0218; *(u16*)&ack[0xC + 0x02] = 0; *(u16*)&ack[0xC + 0x04] = 0x0903; @@ -1110,8 +1257,11 @@ void Wifi::FinishRX() if (!ComStatus) { - if (IOPORT(W_PowerState) & 0x0300) + if (IOPORT(W_PowerState) & (1<<9)) + { + IOPORT(W_TRXPower) = 0; SetStatus(9); + } else SetStatus(1); } @@ -1380,7 +1530,7 @@ void Wifi::FinishRX() void Wifi::MPClientReplyRX(int client) { - if (IOPORT(W_PowerState) & 0x0300) + if (IOPORT(W_PowerState) & (1<<9)) return; if (!(IOPORT(W_RXCnt) & 0x8000)) @@ -1421,7 +1571,7 @@ void Wifi::MPClientReplyRX(int client) bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames { - if (IOPORT(W_PowerState) & 0x0300) + if (IOPORT(W_PowerState) & (1<<9)) return false; if (!(IOPORT(W_RXCnt) & 0x8000)) @@ -1433,7 +1583,7 @@ bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames int rxlen; int framelen; u16 framectl; - u8 txrate; + u8 txrate, chan; u64 timestamp; for (;;) @@ -1468,6 +1618,24 @@ bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames continue; } + chan = RXBuffer[9]; + if (chan != CurChannel || CurChannel == 0) + { + Log(LogLevel::Debug, "received frame but bad channel %d (expected %d)\n", chan, CurChannel); + continue; + } + + // hack: ignore MP frames if not engaged in a MP comm + if (type == 0 && (!IsMP)) + { + if (MACEqual(&RXBuffer[12 + 16], MPReplyMAC) || + MACEqual(&RXBuffer[12 + 4], MPCmdMAC) || + MACEqual(&RXBuffer[12 + 4], MPReplyMAC)) + { + continue; + } + } + framectl = *(u16*)&RXBuffer[12+0]; txrate = RXBuffer[8]; @@ -1528,7 +1696,6 @@ bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames // we also need to determine how far we can run after having received this frame RXTimestamp = timestamp; - //if (RXTimestamp < USTimestamp) printf("CRAP!! %04X %016llX %016llX\n", framectl, RXTimestamp, USTimestamp); if (RXTimestamp < USTimestamp) RXTimestamp = USTimestamp; NextSync = RXTimestamp + (framelen * (txrate==0x14 ? 4:8)); @@ -1570,11 +1737,13 @@ void Wifi::MSTimer() } } - IOPORT(W_BeaconCount1)--; - if (IOPORT(W_BeaconCount1) == 0) + if (IOPORT(W_BeaconCount1) != 0) { - SetIRQ14(1); + IOPORT(W_BeaconCount1)--; + if (IOPORT(W_BeaconCount1) == 0) SetIRQ14(1); } + if (IOPORT(W_BeaconCount1) == 0) + IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval); if (IOPORT(W_BeaconCount2) != 0) { @@ -1605,19 +1774,19 @@ void Wifi::USTimer(u32 param) if (!(USTimestamp & 0x3FF & kTimeCheckMask)) WifiAP->MSTimer(); - bool switchOffPowerSaving = false; if (USUntilPowerOn < 0) { USUntilPowerOn += kTimerInterval; - switchOffPowerSaving = (USUntilPowerOn >= 0) && (IOPORT(W_PowerUnk) & 0x0001 || ForcePowerOn); - } - if ((USUntilPowerOn >= 0) && (IOPORT(W_PowerState) & 0x0002 || switchOffPowerSaving)) - { - IOPORT(W_PowerState) = 0; - IOPORT(W_RFPins) = 1; - IOPORT(W_RFPins) = 0x0084; - SetIRQ(11); + if (USUntilPowerOn >= 0) + { + USUntilPowerOn = 0; + + IOPORT(W_PowerState) = 0; + SetStatus(1); + + UpdatePowerStatus(0); + } } if (IOPORT(W_USCountCnt)) @@ -1660,7 +1829,7 @@ void Wifi::USTimer(u32 param) u16 txbusy = IOPORT(W_TXBusy); if (txbusy) { - if (IOPORT(W_PowerState) & 0x0300) + if (IOPORT(W_PowerState) & (1<<9)) { ComStatus = 0; TXCurSlot = -1; @@ -1695,9 +1864,10 @@ void Wifi::USTimer(u32 param) bool finished = ProcessTX(&TXSlots[TXCurSlot], TXCurSlot); if (finished) { - if (IOPORT(W_PowerState) & 0x0300) + if (IOPORT(W_PowerState) & (1<<9)) { IOPORT(W_TXBusy) = 0; + IOPORT(W_TRXPower) = 0; SetStatus(9); } @@ -1754,8 +1924,9 @@ void Wifi::USTimer(u32 param) RXCounter = 0; } // TODO: proper error management - if ((!ComStatus) && (IOPORT(W_PowerState) & 0x0300)) + if ((!ComStatus) && (IOPORT(W_PowerState) & (1<<9))) { + IOPORT(W_TRXPower) = 0; SetStatus(9); } } @@ -1766,6 +1937,28 @@ void Wifi::USTimer(u32 param) } +void Wifi::ChangeChannel() +{ + u32 val1 = RFRegs[RFChannelIndex[0]]; + u32 val2 = RFRegs[RFChannelIndex[1]]; + + CurChannel = 0; + + for (int i = 0; i < 14; i++) + { + if (val1 == RFChannelData[i][0] && val2 == RFChannelData[i][1]) + { + CurChannel = i+1; + break; + } + } + + if (CurChannel > 0) + Log(LogLevel::Debug, "wifi: switching to channel %d\n", CurChannel); + else + Log(LogLevel::Debug, "wifi: invalid channel values %05X:%05X\n", val1, val2); +} + void Wifi::RFTransfer_Type2() { u32 id = (IOPORT(W_RFData2) >> 2) & 0x1F; @@ -1780,6 +1973,9 @@ void Wifi::RFTransfer_Type2() { u32 data = IOPORT(W_RFData1) | ((IOPORT(W_RFData2) & 0x0003) << 16); RFRegs[id] = data; + + if (id == RFChannelIndex[0] || id == RFChannelIndex[1]) + ChangeChannel(); } } @@ -1796,6 +1992,9 @@ void Wifi::RFTransfer_Type3() { u32 data = IOPORT(W_RFData1) & 0xFF; RFRegs[id] = data; + + if (id == RFChannelIndex[0] || id == RFChannelIndex[1]) + ChangeChannel(); } } @@ -1819,6 +2018,7 @@ u16 Wifi::Read(u32 addr) switch (addr) { case W_Random: // random generator. not accurate + // TODO: rotate the sequence based on the ARM7 cycle counter (if this is important) Random = (Random & 0x1) ^ (((Random & 0x3FF) << 1) | (Random >> 10)); return Random; @@ -1899,7 +2099,6 @@ u16 Wifi::Read(u32 addr) } } - //printf("WIFI: read %08X\n", addr); return IOPORT(addr&0xFFF); } @@ -1923,28 +2122,20 @@ void Wifi::Write(u32 addr, u16 val) case W_ModeReset: { u16 oldval = IOPORT(W_ModeReset); + IOPORT(W_ModeReset) = val & 0x0001; if (!(oldval & 0x0001) && (val & 0x0001)) { - if (!(USUntilPowerOn < 0 && ForcePowerOn)) - { - //printf("mode reset power on %08x\n", NDS::ARM7->R[15]); - IOPORT(0x034) = 0x0002; - IOPORT(0x27C) = 0x0005; - // TODO: 02A2?? + IOPORT(0x27C) = 0x0005; + // TODO: 02A2?? - if (IOPORT(W_PowerUnk) & 0x0002) - { - USUntilPowerOn = -2048; - IOPORT(W_PowerState) |= 0x100; - } - } + UpdatePowerStatus(0); } else if ((oldval & 0x0001) && !(val & 0x0001)) { - //printf("mode reset shutdown %08x\n", NDS::ARM7->R[15]); IOPORT(0x27C) = 0x000A; - PowerDown(); + + UpdatePowerStatus(0); } if (val & 0x2000) @@ -1986,23 +2177,43 @@ void Wifi::Write(u32 addr, u16 val) IOPORT(0x230) = 0x0047; } } - break; + return; case W_ModeWEP: val &= 0x007F; - //printf("writing mode web %x\n", val); - if ((val & 0x7) == 1) - IOPORT(W_PowerUnk) |= 0x0002; - if ((val & 0x7) == 2) - IOPORT(W_PowerUnk) = 0x0003; - break; + IOPORT(W_ModeWEP) = val; + if (IOPORT(W_PowerTX) & (1<<1)) + { + if ((val & 0x7) == 1) + IOPORT(W_PowerDownCtrl) |= (1<<1); + else if ((val & 0x7) == 2) + IOPORT(W_PowerDownCtrl) = 3; + + if ((val & 0x7) != 3) + IOPORT(W_PowerState) &= 0x0300; + + UpdatePowerStatus(0); + } + return; + + case W_IE: + { + u16 oldflags = IOPORT(W_IF) & IOPORT(W_IE); + IOPORT(W_IE) = val; + CheckIRQ(oldflags); + } + return; case W_IF: IOPORT(W_IF) &= ~val; return; case W_IFSet: - IOPORT(W_IF) |= (val & 0xFBFF); - Log(LogLevel::Debug, "wifi: force-setting IF %04X\n", val); + { + u16 oldflags = IOPORT(W_IF) & IOPORT(W_IE); + IOPORT(W_IF) |= (val & 0xFBFF); + CheckIRQ(oldflags); + Log(LogLevel::Debug, "wifi: force-setting IF %04X\n", val); + } return; case W_AIDLow: @@ -2012,67 +2223,63 @@ void Wifi::Write(u32 addr, u16 val) IOPORT(W_AIDFull) = val & 0x07FF; return; - case W_PowerState: - //printf("writing power state %x %08x\n", val, NDS::ARM7->R[15]); - IOPORT(W_PowerState) |= val & 0x0002; - - if (IOPORT(W_ModeReset) & 0x0001 && IOPORT(W_PowerState) & 0x0002) - { - /*if (IOPORT(W_PowerState) & 0x100) - { - AlwaysPowerOn = true; - USUntilPowerOn = -1; - } - else */ - if (IOPORT(W_PowerForce) == 1) - { - //printf("power on\n"); - IOPORT(W_PowerState) |= 0x100; - USUntilPowerOn = -2048; - ForcePowerOn = false; - } - } - return; - case W_PowerForce: - //if ((val&0x8001)==0x8000) printf("WIFI: forcing power %04X\n", val); - - val &= 0x8001; - //printf("writing power force %x %08x\n", val, NDS::ARM7->R[15]); - if (val == 0x8001) - { - //printf("force power off\n"); - IOPORT(0x034) = 0x0002; - IOPORT(W_PowerState) = 0x0200; - IOPORT(W_TXReqRead) = 0; - PowerDown(); - } - if (val == 1 && IOPORT(W_PowerState) & 0x0002) - { - //printf("power on\n"); - IOPORT(W_PowerState) |= 0x100; - USUntilPowerOn = -2048; - ForcePowerOn = false; - } - if (val == 0x8000) - { - //printf("force power on\n"); - IOPORT(W_PowerState) |= 0x100; - USUntilPowerOn = -2048; - ForcePowerOn = true; - } - break; case W_PowerUS: IOPORT(W_PowerUS) = val & 0x0003; UpdatePowerOn(); return; - case W_PowerUnk: - val &= 0x0003; - //printf("writing power unk %x\n", val); - if ((IOPORT(W_ModeWEP) & 0x7) == 1) - val |= 2; - else if ((IOPORT(W_ModeWEP) & 0x7) == 2) - val = 3; - break; + + case W_PowerTX: + IOPORT(W_PowerTX) = val & 0x0003; + if (val & (1<<1)) + { + if ((IOPORT(W_ModeWEP) & 0x7) == 1) + IOPORT(W_PowerDownCtrl) |= (1<<1); + else if ((IOPORT(W_ModeWEP) & 0x7) == 2) + IOPORT(W_PowerDownCtrl) = 3; + + UpdatePowerStatus(0); + } + return; + + case W_PowerState: + if ((IOPORT(W_ModeWEP) & 0x7) != 3) + return; + + val = (IOPORT(W_PowerState) & 0x0300) | (val & 0x0003); + if ((val & 0x0300) == 0x0200) + val &= ~(1<<0); + else + val &= ~(1<<1); + + if (!(val & (1<<9))) + val &= ~(1<<8); + + IOPORT(W_PowerState) = val; + UpdatePowerStatus(0); + return; + + case W_PowerForce: + val &= 0x8001; + IOPORT(W_PowerForce) = val; + UpdatePowerStatus(0); + return; + + case W_PowerDownCtrl: + IOPORT(W_PowerDownCtrl) = val & 0x0003; + + if (IOPORT(W_PowerTX) & (1<<1)) + { + if ((IOPORT(W_ModeWEP) & 0x7) == 1) + IOPORT(W_PowerDownCtrl) |= (1<<1); + else if ((IOPORT(W_ModeWEP) & 0x7) == 2) + IOPORT(W_PowerDownCtrl) = 3; + } + + if (val != 0 && val != 3) + Log(LogLevel::Warn, "wifi: unusual W_PowerDownCtrl value %04X\n", val); + + UpdatePowerStatus(0); + return; case W_USCountCnt: val &= 0x0001; break; case W_USCompareCnt: @@ -2231,6 +2438,7 @@ void Wifi::Write(u32 addr, u16 val) // read-only ports case 0x000: + case 0x034: case 0x044: case 0x054: case 0x098: diff --git a/src/Wifi.h b/src/Wifi.h index 5553a6f5..2e0465a6 100644 --- a/src/Wifi.h +++ b/src/Wifi.h @@ -52,11 +52,12 @@ public: W_RXCnt = 0x030, W_WEPCnt = 0x032, + W_TRXPower = 0x034, W_PowerUS = 0x036, W_PowerTX = 0x038, W_PowerState = 0x03C, W_PowerForce = 0x040, - W_PowerUnk = 0x48, + W_PowerDownCtrl = 0x48, W_Random = 0x044, @@ -206,6 +207,10 @@ private: u8 RFVersion; u32 RFRegs[0x40]; + u32 RFChannelIndex[2]; + u32 RFChannelData[14][2]; + int CurChannel; + struct TXSlot { bool Valid; @@ -240,7 +245,6 @@ private: bool LANInited; int USUntilPowerOn; - bool ForcePowerOn; // MULTIPLAYER SYNC APPARATUS bool IsMP; @@ -253,13 +257,15 @@ private: void ScheduleTimer(bool first); void UpdatePowerOn(); + void CheckIRQ(u16 oldflags); void SetIRQ(u32 irq); void SetIRQ13(); void SetIRQ14(int source); void SetIRQ15(); void SetStatus(u32 status); - void PowerDown(); + + void UpdatePowerStatus(int power); int PreambleLen(int rate) const; u32 NumClients(u16 bitmask) const; @@ -284,6 +290,8 @@ private: void MSTimer(); + void ChangeChannel(); + void RFTransfer_Type2(); void RFTransfer_Type3(); }; diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp index 4c645203..855dc244 100644 --- a/src/WifiAP.cpp +++ b/src/WifiAP.cpp @@ -35,6 +35,7 @@ using Platform::LogLevel; const char* WifiAP::APName = "melonAP"; const u8 WifiAP::APMac[6] = {0x00, 0xF0, 0x77, 0x77, 0x77, 0x77}; +const u8 WifiAP::APChannel = 6; #define PWRITE_8(p, v) *p++ = v; #define PWRITE_16(p, v) *(u16*)p = v; p += 2; @@ -55,7 +56,7 @@ const u8 WifiAP::APMac[6] = {0x00, 0xF0, 0x77, 0x77, 0x77, 0x77}; PWRITE_16(p, 0); \ PWRITE_16(p, 0); \ PWRITE_8(p, rate); \ - PWRITE_8(p, 0); \ + PWRITE_8(p, APChannel); \ PWRITE_16(p, len); //#define PALIGN_4(p, base) p += ((4 - ((ptrdiff_t)(p-base) & 0x3)) & 0x3); @@ -174,7 +175,7 @@ int WifiAP::HandleManagementFrame(const u8* data, int len) PWRITE_16(p, 128); // beacon interval PWRITE_16(p, 0x0021); // capability PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates - PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel + PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, APChannel); // current channel PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName)); memcpy(p, APName, strlen(APName)); p += strlen(APName); @@ -260,6 +261,9 @@ int WifiAP::HandleManagementFrame(const u8* data, int len) int WifiAP::SendPacket(const u8* data, int len) { + if (data[9] != APChannel) + return 0; + data += 12; u16 framectl = *(u16*)&data[0]; @@ -327,7 +331,7 @@ int WifiAP::RecvPacket(u8* data) PWRITE_16(p, 128); // beacon interval PWRITE_16(p, 0x0021); // capability PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates - PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel + PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, APChannel); // current channel PWRITE_8(p, 0x05); PWRITE_8(p, 0x04); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); // TIM PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName)); memcpy(p, APName, strlen(APName)); p += strlen(APName); diff --git a/src/WifiAP.h b/src/WifiAP.h index 8f3ed111..a9e80c3b 100644 --- a/src/WifiAP.h +++ b/src/WifiAP.h @@ -34,6 +34,7 @@ public: static const char* APName; static const u8 APMac[6]; + static const u8 APChannel; void MSTimer(); diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp index 02b3026e..25e04db3 100644 --- a/src/frontend/Util_Audio.cpp +++ b/src/frontend/Util_Audio.cpp @@ -63,21 +63,28 @@ int AudioOut_GetNumSamples(int outlen) void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume) { - float res_incr = inlen / (float)outlen; - float res_timer = 0; - int res_pos = 0; + double factor = (double) inlen / (double) outlen; + double inpos = -(factor / 2); + double vol = (double) volume / 256.f; - for (int i = 0; i < outlen; i++) + for (int i = 0; i < outlen * 2; i += 2) { - outbuf[i*2 ] = (inbuf[res_pos*2 ] * volume) >> 8; - outbuf[i*2+1] = (inbuf[res_pos*2+1] * volume) >> 8; + double intpart_d; + double frac = modf(inpos, &intpart_d); + int intpart = (int) intpart_d; - res_timer += res_incr; - while (res_timer >= 1.0) - { - res_timer -= 1.0; - res_pos++; - } + double l1 = inbuf[ intpart * 2]; + double l2 = inbuf[(intpart * 2) + 2]; + double r1 = inbuf[(intpart * 2) + 1]; + double r2 = inbuf[(intpart * 2) + 3]; + + double ldiff = l2 - l1; + double rdiff = r2 - r1; + + outbuf[i] = (s16) round((l1 + ldiff * frac) * vol); + outbuf[i+1] = (s16) round((r1 + rdiff * frac) * vol); + + inpos += factor; } } diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.cpp b/src/frontend/qt_sdl/AudioSettingsDialog.cpp index 5e8812e9..8e08ef2b 100644 --- a/src/frontend/qt_sdl/AudioSettingsDialog.cpp +++ b/src/frontend/qt_sdl/AudioSettingsDialog.cpp @@ -51,6 +51,7 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent, bool emuActive, EmuThr ui->cbInterpolation->addItem("Linear"); ui->cbInterpolation->addItem("Cosine"); ui->cbInterpolation->addItem("Cubic"); + ui->cbInterpolation->addItem("Gaussian (SNES)"); ui->cbInterpolation->setCurrentIndex(Config::AudioInterp); ui->cbBitDepth->addItem("Automatic"); @@ -173,7 +174,7 @@ void AudioSettingsDialog::on_cbBitDepth_currentIndexChanged(int idx) void AudioSettingsDialog::on_cbInterpolation_currentIndexChanged(int idx) { // prevent a spurious change - if (ui->cbInterpolation->count() < 4) return; + if (ui->cbInterpolation->count() < 5) return; Config::AudioInterp = ui->cbInterpolation->currentIndex(); diff --git a/src/frontend/qt_sdl/EmuThread.cpp b/src/frontend/qt_sdl/EmuThread.cpp index 0728a085..d16aead4 100644 --- a/src/frontend/qt_sdl/EmuThread.cpp +++ b/src/frontend/qt_sdl/EmuThread.cpp @@ -131,8 +131,8 @@ std::unique_ptr EmuThread::CreateConsole( NDSArgs ndsargs { std::move(ndscart), std::move(gbacart), - *arm9bios, - *arm7bios, + std::move(arm9bios), + std::move(arm7bios), std::move(*firmware), #ifdef JIT_ENABLED Config::JIT_Enable ? std::make_optional(jitargs) : std::nullopt, @@ -165,8 +165,8 @@ std::unique_ptr EmuThread::CreateConsole( auto sdcard = ROMManager::LoadDSiSDCard(); DSiArgs args { std::move(ndsargs), - *arm9ibios, - *arm7ibios, + std::move(arm9ibios), + std::move(arm7ibios), std::move(*nand), std::move(sdcard), Config::DSiFullBIOSBoot, diff --git a/src/frontend/qt_sdl/Input.cpp b/src/frontend/qt_sdl/Input.cpp index c429cd36..7ebd7e2a 100644 --- a/src/frontend/qt_sdl/Input.cpp +++ b/src/frontend/qt_sdl/Input.cpp @@ -128,6 +128,11 @@ void KeyRelease(QKeyEvent* event) KeyHotkeyMask &= ~(1<> LoadARM9BIOS() noexcept +std::unique_ptr LoadARM9BIOS() noexcept { if (!Config::ExternalBIOSEnable) { - return Config::ConsoleType == 0 ? std::make_optional(bios_arm9_bin) : std::nullopt; + return Config::ConsoleType == 0 ? std::make_unique(bios_arm9_bin) : nullptr; } if (FileHandle* f = OpenLocalFile(Config::BIOS9Path, Read)) { - std::array bios {}; + std::unique_ptr bios = std::make_unique(); FileRewind(f); - FileRead(bios.data(), sizeof(bios), 1, f); + FileRead(bios->data(), bios->size(), 1, f); CloseFile(f); Log(Info, "ARM9 BIOS loaded from %s\n", Config::BIOS9Path.c_str()); return bios; } Log(Warn, "ARM9 BIOS not found\n"); - return std::nullopt; + return nullptr; } -std::optional> LoadARM7BIOS() noexcept +std::unique_ptr LoadARM7BIOS() noexcept { if (!Config::ExternalBIOSEnable) { - return Config::ConsoleType == 0 ? std::make_optional(bios_arm7_bin) : std::nullopt; + return Config::ConsoleType == 0 ? std::make_unique(bios_arm7_bin) : nullptr; } if (FileHandle* f = OpenLocalFile(Config::BIOS7Path, Read)) { - std::array bios {}; - FileRead(bios.data(), sizeof(bios), 1, f); + std::unique_ptr bios = std::make_unique(); + FileRead(bios->data(), bios->size(), 1, f); CloseFile(f); Log(Info, "ARM7 BIOS loaded from %s\n", Config::BIOS7Path.c_str()); return bios; } Log(Warn, "ARM7 BIOS not found\n"); - return std::nullopt; + return nullptr; } -std::optional> LoadDSiARM9BIOS() noexcept +std::unique_ptr LoadDSiARM9BIOS() noexcept { if (FileHandle* f = OpenLocalFile(Config::DSiBIOS9Path, Read)) { - std::array bios {}; - FileRead(bios.data(), sizeof(bios), 1, f); + std::unique_ptr bios = std::make_unique(); + FileRead(bios->data(), bios->size(), 1, f); CloseFile(f); if (!Config::DSiFullBIOSBoot) { // herp - *(u32*)&bios[0] = 0xEAFFFFFE; // overwrites the reset vector + *(u32*)bios->data() = 0xEAFFFFFE; // overwrites the reset vector // TODO!!!! // hax the upper 32K out of the goddamn DSi @@ -575,21 +575,21 @@ std::optional> LoadDSiARM9BIOS() noexcept } Log(Warn, "ARM9i BIOS not found\n"); - return std::nullopt; + return nullptr; } -std::optional> LoadDSiARM7BIOS() noexcept +std::unique_ptr LoadDSiARM7BIOS() noexcept { if (FileHandle* f = OpenLocalFile(Config::DSiBIOS7Path, Read)) { - std::array bios {}; - FileRead(bios.data(), sizeof(bios), 1, f); + std::unique_ptr bios = std::make_unique(); + FileRead(bios->data(), bios->size(), 1, f); CloseFile(f); if (!Config::DSiFullBIOSBoot) { // herp - *(u32*)&bios[0] = 0xEAFFFFFE; // overwrites the reset vector + *(u32*)bios->data() = 0xEAFFFFFE; // overwrites the reset vector // TODO!!!! // hax the upper 32K out of the goddamn DSi @@ -600,7 +600,7 @@ std::optional> LoadDSiARM7BIOS() noexcept } Log(Warn, "ARM7i BIOS not found\n"); - return std::nullopt; + return nullptr; } Firmware GenerateFirmware(int type) noexcept @@ -642,7 +642,7 @@ Firmware GenerateFirmware(int type) noexcept } } - CustomizeFirmware(firmware); + CustomizeFirmware(firmware, true); // If we don't have Wi-fi settings to load, // then the defaults will have already been populated by the constructor. @@ -681,10 +681,7 @@ std::optional LoadFirmware(int type) noexcept return std::nullopt; } - if (Config::FirmwareOverrideSettings) - { - CustomizeFirmware(firmware); - } + CustomizeFirmware(firmware, Config::FirmwareOverrideSettings); return firmware; } @@ -916,6 +913,8 @@ void Reset(EmuThread* thread) thread->NDS->SetupDirectBoot(BaseROMName); } } + + thread->NDS->Start(); } @@ -1118,54 +1117,59 @@ bool ParseMacAddress(void* data) return false; } -void CustomizeFirmware(Firmware& firmware) noexcept +void CustomizeFirmware(Firmware& firmware, bool overridesettings) noexcept { - auto& currentData = firmware.GetEffectiveUserData(); - - // setting up username - std::string orig_username = Config::FirmwareUsername; - if (!orig_username.empty()) - { // If the frontend defines a username, take it. If not, leave the existing one. - std::u16string username = std::wstring_convert, char16_t>{}.from_bytes(orig_username); - size_t usernameLength = std::min(username.length(), (size_t) 10); - currentData.NameLength = usernameLength; - memcpy(currentData.Nickname, username.data(), usernameLength * sizeof(char16_t)); - } - - auto language = static_cast(Config::FirmwareLanguage); - if (language != Firmware::Language::Reserved) - { // If the frontend specifies a language (rather than using the existing value)... - currentData.Settings &= ~Firmware::Language::Reserved; // ..clear the existing language... - currentData.Settings |= language; // ...and set the new one. - } - - // setting up color - u8 favoritecolor = Config::FirmwareFavouriteColour; - if (favoritecolor != 0xFF) + if (overridesettings) { - currentData.FavoriteColor = favoritecolor; - } + auto ¤tData = firmware.GetEffectiveUserData(); - u8 birthmonth = Config::FirmwareBirthdayMonth; - if (birthmonth != 0) - { // If the frontend specifies a birth month (rather than using the existing value)... - currentData.BirthdayMonth = birthmonth; - } + // setting up username + std::string orig_username = Config::FirmwareUsername; + if (!orig_username.empty()) + { // If the frontend defines a username, take it. If not, leave the existing one. + std::u16string username = std::wstring_convert, char16_t>{}.from_bytes( + orig_username); + size_t usernameLength = std::min(username.length(), (size_t) 10); + currentData.NameLength = usernameLength; + memcpy(currentData.Nickname, username.data(), usernameLength * sizeof(char16_t)); + } - u8 birthday = Config::FirmwareBirthdayDay; - if (birthday != 0) - { // If the frontend specifies a birthday (rather than using the existing value)... - currentData.BirthdayDay = birthday; - } + auto language = static_cast(Config::FirmwareLanguage); + if (language != Firmware::Language::Reserved) + { // If the frontend specifies a language (rather than using the existing value)... + currentData.Settings &= ~Firmware::Language::Reserved; // ..clear the existing language... + currentData.Settings |= language; // ...and set the new one. + } - // setup message - std::string orig_message = Config::FirmwareMessage; - if (!orig_message.empty()) - { - std::u16string message = std::wstring_convert, char16_t>{}.from_bytes(orig_message); - size_t messageLength = std::min(message.length(), (size_t) 26); - currentData.MessageLength = messageLength; - memcpy(currentData.Message, message.data(), messageLength * sizeof(char16_t)); + // setting up color + u8 favoritecolor = Config::FirmwareFavouriteColour; + if (favoritecolor != 0xFF) + { + currentData.FavoriteColor = favoritecolor; + } + + u8 birthmonth = Config::FirmwareBirthdayMonth; + if (birthmonth != 0) + { // If the frontend specifies a birth month (rather than using the existing value)... + currentData.BirthdayMonth = birthmonth; + } + + u8 birthday = Config::FirmwareBirthdayDay; + if (birthday != 0) + { // If the frontend specifies a birthday (rather than using the existing value)... + currentData.BirthdayDay = birthday; + } + + // setup message + std::string orig_message = Config::FirmwareMessage; + if (!orig_message.empty()) + { + std::u16string message = std::wstring_convert, char16_t>{}.from_bytes( + orig_message); + size_t messageLength = std::min(message.length(), (size_t) 26); + currentData.MessageLength = messageLength; + memcpy(currentData.Message, message.data(), messageLength * sizeof(char16_t)); + } } MacAddress mac; @@ -1174,14 +1178,16 @@ void CustomizeFirmware(Firmware& firmware) noexcept memcpy(&mac, header.MacAddr.data(), sizeof(MacAddress)); - - MacAddress configuredMac; - rep = ParseMacAddress(&configuredMac); - rep &= (configuredMac != MacAddress()); - - if (rep) + if (overridesettings) { - mac = configuredMac; + MacAddress configuredMac; + rep = ParseMacAddress(&configuredMac); + rep &= (configuredMac != MacAddress()); + + if (rep) + { + mac = configuredMac; + } } int inst = Platform::InstanceID(); @@ -1566,23 +1572,28 @@ QString GBACartLabel() void ROMIcon(const u8 (&data)[512], const u16 (&palette)[16], u32 (&iconRef)[32*32]) { - int index = 0; - for (int i = 0; i < 4; i++) + u32 paletteRGBA[16]; + for (int i = 0; i < 16; i++) { - for (int j = 0; j < 4; j++) + u8 r = ((palette[i] >> 0) & 0x1F) * 255 / 31; + u8 g = ((palette[i] >> 5) & 0x1F) * 255 / 31; + u8 b = ((palette[i] >> 10) & 0x1F) * 255 / 31; + u8 a = i ? 255 : 0; + paletteRGBA[i] = r | (g << 8) | (b << 16) | (a << 24); + } + + int count = 0; + for (int ytile = 0; ytile < 4; ytile++) + { + for (int xtile = 0; xtile < 4; xtile++) { - for (int k = 0; k < 8; k++) + for (int ypixel = 0; ypixel < 8; ypixel++) { - for (int l = 0; l < 8; l++) + for (int xpixel = 0; xpixel < 8; xpixel++) { - u8 pal_index = index % 2 ? data[index/2] >> 4 : data[index/2] & 0x0F; - u8 r = ((palette[pal_index] >> 0) & 0x1F) * 255 / 31; - u8 g = ((palette[pal_index] >> 5) & 0x1F) * 255 / 31; - u8 b = ((palette[pal_index] >> 10) & 0x1F) * 255 / 31; - u8 a = pal_index ? 255: 0; - u32* row = &iconRef[256 * i + 32 * k + 8 * j]; - row[l] = r | (g << 8) | (b << 16) | (a << 24); - index++; + u8 pal_index = count % 2 ? data[count/2] >> 4 : data[count/2] & 0x0F; + iconRef[ytile*256 + ypixel*32 + xtile*8 + xpixel] = paletteRGBA[pal_index]; + count++; } } } diff --git a/src/frontend/qt_sdl/ROMManager.h b/src/frontend/qt_sdl/ROMManager.h index 38ed65cd..ae854617 100644 --- a/src/frontend/qt_sdl/ROMManager.h +++ b/src/frontend/qt_sdl/ROMManager.h @@ -26,6 +26,8 @@ #include #include "MemConstants.h" + +#include #include #include #include @@ -56,16 +58,16 @@ void ClearBackupState(); /// Returns the configured ARM9 BIOS loaded from disk, /// the FreeBIOS if external BIOS is disabled and we're in NDS mode, -/// or nullopt if loading failed. -std::optional> LoadARM9BIOS() noexcept; -std::optional> LoadARM7BIOS() noexcept; -std::optional> LoadDSiARM9BIOS() noexcept; -std::optional> LoadDSiARM7BIOS() noexcept; +/// or nullptr if loading failed. +std::unique_ptr LoadARM9BIOS() noexcept; +std::unique_ptr LoadARM7BIOS() noexcept; +std::unique_ptr LoadDSiARM9BIOS() noexcept; +std::unique_ptr LoadDSiARM7BIOS() noexcept; std::optional GetDSiSDCardArgs() noexcept; std::optional LoadDSiSDCard() noexcept; std::optional GetDLDISDCardArgs() noexcept; std::optional LoadDLDISDCard() noexcept; -void CustomizeFirmware(Firmware& firmware) noexcept; +void CustomizeFirmware(Firmware& firmware, bool overridesettings) noexcept; Firmware GenerateFirmware(int type) noexcept; /// Loads and customizes a firmware image based on the values in Config std::optional LoadFirmware(int type) noexcept; diff --git a/src/frontend/qt_sdl/Screen.cpp b/src/frontend/qt_sdl/Screen.cpp index cfcbeed9..73236504 100644 --- a/src/frontend/qt_sdl/Screen.cpp +++ b/src/frontend/qt_sdl/Screen.cpp @@ -214,7 +214,7 @@ void ScreenPanel::mouseMoveEvent(QMouseEvent* event) showCursor(); - if (!(event->buttons() & Qt::LeftButton)) return; + //if (!(event->buttons() & Qt::LeftButton)) return; if (!touching) return; int x = event->pos().x(); diff --git a/src/frontend/qt_sdl/Window.cpp b/src/frontend/qt_sdl/Window.cpp index 0f0b71fd..23ba784e 100644 --- a/src/frontend/qt_sdl/Window.cpp +++ b/src/frontend/qt_sdl/Window.cpp @@ -805,7 +805,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) emuThread->NDS->debug(0); Input::KeyPress(event); } @@ -916,6 +916,7 @@ void MainWindow::onAppStateChanged(Qt::ApplicationState state) { if (state == Qt::ApplicationInactive) { + Input::KeyReleaseAll(); if (Config::PauseLostFocus && emuThread->emuIsRunning()) emuThread->emuPause(); } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 6e87d5bb..01ba52c7 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -348,7 +348,7 @@ int main(int argc, char** argv) #endif SANITIZE(Config::ScreenVSyncInterval, 1, 20); SANITIZE(Config::GL_ScaleFactor, 1, 16); - SANITIZE(Config::AudioInterp, 0, 3); + SANITIZE(Config::AudioInterp, 0, 4); SANITIZE(Config::AudioVolume, 0, 256); SANITIZE(Config::MicInputType, 0, (int)micInputType_MAX); SANITIZE(Config::ScreenRotation, 0, (int)Frontend::screenRot_MAX); diff --git a/vcpkg.json b/vcpkg.json index a1bd0be5..3e23ff1b 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,11 @@ { "dependencies": [ "sdl2", - "libarchive", + { + "name": "libarchive", + "default-features": false, + "features": ["bzip2", "crypto", "lz4", "zstd"] + }, "libslirp", "zstd", {