mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
Merge remote-tracking branch 'upstream/master' into RDLines
This commit is contained in:
commit
ae1890a8db
2
.github/workflows/build-macos.yml
vendored
2
.github/workflows/build-macos.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies for package building
|
- name: Install dependencies for package building
|
||||||
run: |
|
run: |
|
||||||
brew install autoconf automake autoconf-archive libtool && pip3 install setuptools
|
brew install autoconf automake autoconf-archive libtool python-setuptools
|
||||||
- name: Set up CMake
|
- name: Set up CMake
|
||||||
uses: lukka/get-cmake@latest
|
uses: lukka/get-cmake@latest
|
||||||
- name: Set up vcpkg
|
- name: Set up vcpkg
|
||||||
|
12
src/Args.h
12
src/Args.h
@ -69,6 +69,10 @@ struct JITArgs
|
|||||||
bool FastMemory = true;
|
bool FastMemory = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using ARM9BIOSImage = std::array<u8, ARM9BIOSSize>;
|
||||||
|
using ARM7BIOSImage = std::array<u8, ARM7BIOSSize>;
|
||||||
|
using DSiBIOSImage = std::array<u8, DSiBIOSSize>;
|
||||||
|
|
||||||
struct GDBArgs
|
struct GDBArgs
|
||||||
{
|
{
|
||||||
u16 PortARM7 = 0;
|
u16 PortARM7 = 0;
|
||||||
@ -95,11 +99,11 @@ struct NDSArgs
|
|||||||
|
|
||||||
/// NDS ARM9 BIOS to install.
|
/// NDS ARM9 BIOS to install.
|
||||||
/// Defaults to FreeBIOS, which is not compatible with DSi mode.
|
/// Defaults to FreeBIOS, which is not compatible with DSi mode.
|
||||||
std::array<u8, ARM9BIOSSize> ARM9BIOS = bios_arm9_bin;
|
std::unique_ptr<ARM9BIOSImage> ARM9BIOS = std::make_unique<ARM9BIOSImage>(bios_arm9_bin);
|
||||||
|
|
||||||
/// NDS ARM7 BIOS to install.
|
/// NDS ARM7 BIOS to install.
|
||||||
/// Defaults to FreeBIOS, which is not compatible with DSi mode.
|
/// Defaults to FreeBIOS, which is not compatible with DSi mode.
|
||||||
std::array<u8, ARM7BIOSSize> ARM7BIOS = bios_arm7_bin;
|
std::unique_ptr<ARM7BIOSImage> ARM7BIOS = std::make_unique<ARM7BIOSImage>(bios_arm7_bin);
|
||||||
|
|
||||||
/// Firmware image to install.
|
/// Firmware image to install.
|
||||||
/// Defaults to generated NDS firmware.
|
/// Defaults to generated NDS firmware.
|
||||||
@ -131,8 +135,8 @@ struct NDSArgs
|
|||||||
/// Contains no virtual methods, so there's no vtable.
|
/// Contains no virtual methods, so there's no vtable.
|
||||||
struct DSiArgs final : public NDSArgs
|
struct DSiArgs final : public NDSArgs
|
||||||
{
|
{
|
||||||
std::array<u8, DSiBIOSSize> ARM9iBIOS = BrokenBIOS<DSiBIOSSize>;
|
std::unique_ptr<DSiBIOSImage> ARM9iBIOS = std::make_unique<DSiBIOSImage>(BrokenBIOS<DSiBIOSSize>);
|
||||||
std::array<u8, DSiBIOSSize> ARM7iBIOS = BrokenBIOS<DSiBIOSSize>;
|
std::unique_ptr<DSiBIOSImage> ARM7iBIOS = std::make_unique<DSiBIOSImage>(BrokenBIOS<DSiBIOSSize>);
|
||||||
|
|
||||||
/// NAND image to install.
|
/// NAND image to install.
|
||||||
/// Required, there is no default value.
|
/// Required, there is no default value.
|
||||||
|
@ -82,8 +82,8 @@ DSi::DSi(DSiArgs&& args) noexcept :
|
|||||||
DSi_NDMA(1, 2, *this),
|
DSi_NDMA(1, 2, *this),
|
||||||
DSi_NDMA(1, 3, *this),
|
DSi_NDMA(1, 3, *this),
|
||||||
},
|
},
|
||||||
ARM7iBIOS(args.ARM7iBIOS),
|
ARM7iBIOS(*args.ARM7iBIOS),
|
||||||
ARM9iBIOS(args.ARM9iBIOS),
|
ARM9iBIOS(*args.ARM9iBIOS),
|
||||||
DSP(*this),
|
DSP(*this),
|
||||||
SDMMC(*this, std::move(args.NANDImage), std::move(args.DSiSDCard)),
|
SDMMC(*this, std::move(args.NANDImage), std::move(args.DSiSDCard)),
|
||||||
SDIO(*this),
|
SDIO(*this),
|
||||||
|
@ -110,6 +110,7 @@ bool FATStorage::InjectFile(const std::string& path, u8* data, u32 len)
|
|||||||
res = f_mount(&fs, "0:", 1);
|
res = f_mount(&fs, "0:", 1);
|
||||||
if (res != FR_OK)
|
if (res != FR_OK)
|
||||||
{
|
{
|
||||||
|
f_unmount("0:");
|
||||||
ff_disk_close();
|
ff_disk_close();
|
||||||
return false;
|
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);
|
res = f_mount(&fs, "0:", 1);
|
||||||
if (res != FR_OK)
|
if (res != FR_OK)
|
||||||
{
|
{
|
||||||
|
f_unmount("0:");
|
||||||
ff_disk_close();
|
ff_disk_close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1144,6 +1146,7 @@ bool FATStorage::Save()
|
|||||||
res = f_mount(&fs, "0:", 1);
|
res = f_mount(&fs, "0:", 1);
|
||||||
if (res != FR_OK)
|
if (res != FR_OK)
|
||||||
{
|
{
|
||||||
|
f_unmount("0:");
|
||||||
ff_disk_close();
|
ff_disk_close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
10
src/NDS.cpp
10
src/NDS.cpp
@ -80,8 +80,8 @@ NDS::NDS() noexcept :
|
|||||||
NDSArgs {
|
NDSArgs {
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
bios_arm9_bin,
|
std::make_unique<ARM9BIOSImage>(bios_arm9_bin),
|
||||||
bios_arm7_bin,
|
std::make_unique<ARM7BIOSImage>(bios_arm7_bin),
|
||||||
Firmware(0),
|
Firmware(0),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -90,8 +90,8 @@ NDS::NDS() noexcept :
|
|||||||
|
|
||||||
NDS::NDS(NDSArgs&& args, int type) noexcept :
|
NDS::NDS(NDSArgs&& args, int type) noexcept :
|
||||||
ConsoleType(type),
|
ConsoleType(type),
|
||||||
ARM7BIOS(args.ARM7BIOS),
|
ARM7BIOS(*args.ARM7BIOS),
|
||||||
ARM9BIOS(args.ARM9BIOS),
|
ARM9BIOS(*args.ARM9BIOS),
|
||||||
ARM7BIOSNative(CRC32(ARM7BIOS.data(), ARM7BIOS.size()) == ARM7BIOSCRC32),
|
ARM7BIOSNative(CRC32(ARM7BIOS.data(), ARM7BIOS.size()) == ARM7BIOSCRC32),
|
||||||
ARM9BIOSNative(CRC32(ARM9BIOS.data(), ARM9BIOS.size()) == ARM9BIOSCRC32),
|
ARM9BIOSNative(CRC32(ARM9BIOS.data(), ARM9BIOS.size()) == ARM9BIOSCRC32),
|
||||||
JIT(*this, args.JIT),
|
JIT(*this, args.JIT),
|
||||||
@ -1845,7 +1845,7 @@ void NDS::debug(u32 param)
|
|||||||
//for (int i = 0; i < 9; i++)
|
//for (int i = 0; i < 9; i++)
|
||||||
// printf("VRAM %c: %02X\n", 'A'+i, GPU->VRAMCNT[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);
|
Platform::FileWrite(ARM9.ITCM, 0x8000, 1, shit);
|
||||||
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
||||||
{
|
{
|
||||||
|
48
src/SPU.cpp
48
src/SPU.cpp
@ -140,6 +140,41 @@ constexpr array2d<s16, 0x100, 4> InterpCubic = []() constexpr {
|
|||||||
return interp;
|
return interp;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
const std::array<s16, 0x200> 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) :
|
SPU::SPU(melonDS::NDS& nds, AudioBitDepth bitdepth, AudioInterpolation interpolation) :
|
||||||
NDS(nds),
|
NDS(nds),
|
||||||
Channels {
|
Channels {
|
||||||
@ -621,6 +656,19 @@ s32 SPUChannel::Run()
|
|||||||
(PrevSample[0] * InterpCubic[samplepos][2]) +
|
(PrevSample[0] * InterpCubic[samplepos][2]) +
|
||||||
(val * InterpCubic[samplepos][3])) >> 14;
|
(val * InterpCubic[samplepos][3])) >> 14;
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ enum class AudioInterpolation
|
|||||||
Linear,
|
Linear,
|
||||||
Cosine,
|
Cosine,
|
||||||
Cubic,
|
Cubic,
|
||||||
|
SNESGaussian
|
||||||
};
|
};
|
||||||
|
|
||||||
class SPUChannel
|
class SPUChannel
|
||||||
|
440
src/Wifi.cpp
440
src/Wifi.cpp
@ -159,11 +159,45 @@ void Wifi::Reset()
|
|||||||
#undef BBREG_FIXED
|
#undef BBREG_FIXED
|
||||||
|
|
||||||
const Firmware& fw = NDS.SPI.GetFirmware();
|
const Firmware& fw = NDS.SPI.GetFirmware();
|
||||||
|
const auto& fwheader = fw.GetHeader();
|
||||||
|
|
||||||
RFVersion = fw.GetHeader().RFChipType;
|
RFVersion = fwheader.RFChipType;
|
||||||
memset(RFRegs, 0, 4*0x40);
|
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)
|
if (console == Firmware::FirmwareConsoleType::DS)
|
||||||
IOPORT(0x000) = 0x1440;
|
IOPORT(0x000) = 0x1440;
|
||||||
else if (console == Firmware::FirmwareConsoleType::DSLite)
|
else if (console == Firmware::FirmwareConsoleType::DSLite)
|
||||||
@ -182,6 +216,8 @@ void Wifi::Reset()
|
|||||||
// TODO: find out what the initial values are
|
// TODO: find out what the initial values are
|
||||||
IOPORT(W_PowerUS) = 0x0001;
|
IOPORT(W_PowerUS) = 0x0001;
|
||||||
|
|
||||||
|
//IOPORT(W_BeaconInterval) = 100;
|
||||||
|
|
||||||
USTimestamp = 0;
|
USTimestamp = 0;
|
||||||
|
|
||||||
USCounter = 0;
|
USCounter = 0;
|
||||||
@ -209,7 +245,6 @@ void Wifi::Reset()
|
|||||||
CmdCounter = 0;
|
CmdCounter = 0;
|
||||||
|
|
||||||
USUntilPowerOn = 0;
|
USUntilPowerOn = 0;
|
||||||
ForcePowerOn = false;
|
|
||||||
|
|
||||||
IsMP = false;
|
IsMP = false;
|
||||||
IsMPClient = false;
|
IsMPClient = false;
|
||||||
@ -244,6 +279,8 @@ void Wifi::DoSavestate(Savestate* file)
|
|||||||
file->Var8(&RFVersion);
|
file->Var8(&RFVersion);
|
||||||
file->VarArray(RFRegs, 4*0x40);
|
file->VarArray(RFRegs, 4*0x40);
|
||||||
|
|
||||||
|
file->Var32((u32*)&CurChannel);
|
||||||
|
|
||||||
file->Var64(&USCounter);
|
file->Var64(&USCounter);
|
||||||
file->Var64(&USCompare);
|
file->Var64(&USCompare);
|
||||||
file->Bool32(&BlockBeaconIRQ14);
|
file->Bool32(&BlockBeaconIRQ14);
|
||||||
@ -285,7 +322,6 @@ void Wifi::DoSavestate(Savestate* file)
|
|||||||
file->Var16(&MPLastSeqno);
|
file->Var16(&MPLastSeqno);
|
||||||
|
|
||||||
file->Var32((u32*)&USUntilPowerOn);
|
file->Var32((u32*)&USUntilPowerOn);
|
||||||
file->Bool32(&ForcePowerOn);
|
|
||||||
|
|
||||||
file->Bool32(&IsMP);
|
file->Bool32(&IsMP);
|
||||||
file->Bool32(&IsMPClient);
|
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);
|
u16 newflags = IOPORT(W_IF) & IOPORT(W_IE);
|
||||||
|
|
||||||
IOPORT(W_IF) |= (1<<irq);
|
|
||||||
u32 newflags = IOPORT(W_IF) & IOPORT(W_IE);
|
|
||||||
|
|
||||||
if ((oldflags == 0) && (newflags != 0))
|
if ((oldflags == 0) && (newflags != 0))
|
||||||
NDS.SetIRQ(1, IRQ_Wifi);
|
NDS.SetIRQ(1, IRQ_Wifi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wifi::SetIRQ(u32 irq)
|
||||||
|
{
|
||||||
|
u16 oldflags = IOPORT(W_IF) & IOPORT(W_IE);
|
||||||
|
|
||||||
|
IOPORT(W_IF) |= (1<<irq);
|
||||||
|
CheckIRQ(oldflags);
|
||||||
|
}
|
||||||
|
|
||||||
void Wifi::SetIRQ13()
|
void Wifi::SetIRQ13()
|
||||||
{
|
{
|
||||||
SetIRQ(13);
|
SetIRQ(13);
|
||||||
|
|
||||||
if (!(IOPORT(W_PowerTX) & 0x0002))
|
if ((IOPORT(W_ModeWEP) & 0x7) != 3)
|
||||||
{
|
{
|
||||||
IOPORT(0x034) = 0x0002;
|
if (!(IOPORT(W_PowerTX) & (1<<1)))
|
||||||
//PowerDown();
|
{
|
||||||
// FIXME!!
|
UpdatePowerStatus(-1);
|
||||||
IOPORT(W_RFPins) = 0x0046;
|
}
|
||||||
IOPORT(W_RFStatus) = 9;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wifi::SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced
|
void Wifi::SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced
|
||||||
{
|
{
|
||||||
|
// CHECKME: is this also done for USCOMPARE IRQ?
|
||||||
if (source != 2)
|
if (source != 2)
|
||||||
IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval);
|
IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval);
|
||||||
|
|
||||||
@ -409,10 +450,10 @@ void Wifi::SetIRQ15()
|
|||||||
{
|
{
|
||||||
SetIRQ(15);
|
SetIRQ(15);
|
||||||
|
|
||||||
if (IOPORT(W_PowerTX) & 0x0001)
|
// unlike auto sleep, auto wakeup works under all power management modes
|
||||||
|
if (IOPORT(W_PowerTX) & (1<<0))
|
||||||
{
|
{
|
||||||
IOPORT(W_RFPins) |= 0x0080;
|
UpdatePowerStatus(1);
|
||||||
IOPORT(W_RFStatus) = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,19 +467,113 @@ void Wifi::SetStatus(u32 status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Wifi::PowerDown()
|
void Wifi::UpdatePowerStatus(int power) // 1=on 0=no change -1=off
|
||||||
{
|
{
|
||||||
IOPORT(W_TXReqRead) &= ~0x000F;
|
// TRANSCEIVER POWER MANAGEMENT
|
||||||
IOPORT(W_PowerState) |= 0x0200;
|
//
|
||||||
|
// * W_PowerForce overrides all else
|
||||||
|
// * W_ModeReset bit0 forcibly turns off the transceiver when cleared
|
||||||
|
// * power is normally turned on or off either by IRQ15/IRQ13 or by W_PowerState
|
||||||
|
// depending on the power management mode selected in W_ModeWEP
|
||||||
|
// * W_PowerDownCtrl controls how deep a regular power-down is
|
||||||
|
|
||||||
|
int curflags = 0;
|
||||||
|
if (IOPORT(W_TRXPower) == 1) curflags |= 1;
|
||||||
|
if (!(IOPORT(W_PowerState) & (1<<9))) curflags |= 2;
|
||||||
|
int reqflags = curflags;
|
||||||
|
|
||||||
|
if (IOPORT(W_PowerForce) & (1<<15))
|
||||||
|
{
|
||||||
|
reqflags = (IOPORT(W_PowerForce) & (1<<0)) ? 0 : 3;
|
||||||
|
}
|
||||||
|
else if (!(IOPORT(W_ModeReset) & (1<<0)))
|
||||||
|
{
|
||||||
|
reqflags = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (power == 0)
|
||||||
|
{
|
||||||
|
if ((IOPORT(W_PowerState) & 0x0202) == 0x0202)
|
||||||
|
power = 1;
|
||||||
|
else if ((IOPORT(W_PowerState) & 0x0201) == 0x0001)
|
||||||
|
power = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// W_PowerDownCtrl:
|
||||||
|
// * bit 0 inhibits a regular power-down
|
||||||
|
// * bit 1 forces a wakeup, atleast partial
|
||||||
|
|
||||||
|
if ((power == -1) && (IOPORT(W_PowerDownCtrl) & (1<<0)))
|
||||||
|
power = 0;
|
||||||
|
|
||||||
|
/*if (power == 1)
|
||||||
|
reqflags = 3;
|
||||||
|
else if (power == -1)
|
||||||
|
reqflags = IOPORT(W_PowerDownCtrl);
|
||||||
|
else if (IOPORT(W_PowerDownCtrl) & (1<<1))
|
||||||
|
reqflags = (curflags == 3) ? 3 : IOPORT(W_PowerDownCtrl);*/
|
||||||
|
|
||||||
|
// TODO: support partial power statuses (W_PowerDownCtrl=1 or 2)
|
||||||
|
|
||||||
|
if (power == 1)
|
||||||
|
reqflags = 3;
|
||||||
|
else if (power == -1)
|
||||||
|
reqflags = IOPORT(W_PowerDownCtrl) ? 3 : 0;
|
||||||
|
else if (IOPORT(W_PowerDownCtrl) & (1<<1))
|
||||||
|
reqflags = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reqflags == curflags)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (reqflags & 1)
|
||||||
|
{
|
||||||
|
if (!(curflags & 1))
|
||||||
|
{
|
||||||
|
IOPORT(W_TRXPower) = 1;
|
||||||
|
SetStatus(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// signal the transceiver is going to turn off (checkme)
|
||||||
|
IOPORT(W_TRXPower) = 2;
|
||||||
|
|
||||||
// if the RF hardware is powered down while still sending or receiving,
|
|
||||||
// the current frame is completed before going idle
|
|
||||||
if (!ComStatus)
|
if (!ComStatus)
|
||||||
{
|
{
|
||||||
|
IOPORT(W_TRXPower) = 0;
|
||||||
SetStatus(9);
|
SetStatus(9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reqflags & 2)
|
||||||
|
{
|
||||||
|
// power on
|
||||||
|
|
||||||
|
IOPORT(W_PowerState) |= (1<<8);
|
||||||
|
if ((!(curflags & 2)) && (USUntilPowerOn == 0))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Debug, "wifi: TRX power ON\n");
|
||||||
|
|
||||||
|
USUntilPowerOn = -2048;
|
||||||
|
SetIRQ(11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// power off
|
||||||
|
|
||||||
|
if (curflags & 2)
|
||||||
|
Log(LogLevel::Debug, "wifi: TRX power OFF\n");
|
||||||
|
|
||||||
|
IOPORT(W_PowerState) &= ~(1<<0);
|
||||||
|
IOPORT(W_PowerState) &= ~(1<<8);
|
||||||
|
IOPORT(W_PowerState) |= (1<<9);
|
||||||
|
USUntilPowerOn = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Wifi::PreambleLen(int rate) const
|
int Wifi::PreambleLen(int rate) const
|
||||||
{
|
{
|
||||||
@ -521,6 +656,9 @@ void Wifi::TXSendFrame(const TXSlot* slot, int num)
|
|||||||
if (noseqno == 2)
|
if (noseqno == 2)
|
||||||
*(u16*)&TXBuffer[0xC] |= (1<<11);
|
*(u16*)&TXBuffer[0xC] |= (1<<11);
|
||||||
|
|
||||||
|
if (CurChannel == 0) return;
|
||||||
|
TXBuffer[9] = CurChannel;
|
||||||
|
|
||||||
switch (num)
|
switch (num)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -600,6 +738,9 @@ void Wifi::StartTX_Cmd()
|
|||||||
slot->CurPhase = 13;
|
slot->CurPhase = 13;
|
||||||
slot->CurPhaseTime = CmdCounter - 100;
|
slot->CurPhaseTime = CmdCounter - 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// starting a CMD transfer wakes up the transceiver automatically
|
||||||
|
UpdatePowerStatus(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wifi::StartTX_Beacon()
|
void Wifi::StartTX_Beacon()
|
||||||
@ -678,6 +819,9 @@ void Wifi::SendMPDefaultReply()
|
|||||||
// TODO
|
// TODO
|
||||||
reply[0x8] = 0x14;
|
reply[0x8] = 0x14;
|
||||||
|
|
||||||
|
if (CurChannel == 0) return;
|
||||||
|
reply[0x9] = CurChannel;
|
||||||
|
|
||||||
*(u16*)&reply[0xC + 0x00] = 0x0158;
|
*(u16*)&reply[0xC + 0x00] = 0x0158;
|
||||||
*(u16*)&reply[0xC + 0x02] = 0x00F0;//0; // TODO??
|
*(u16*)&reply[0xC + 0x02] = 0x00F0;//0; // TODO??
|
||||||
*(u16*)&reply[0xC + 0x04] = IOPORT(W_BSSID0);
|
*(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;
|
if (TXSlots[1].Rate == 2) ack[0x8] = 0x14;
|
||||||
else ack[0x8] = 0xA;
|
else ack[0x8] = 0xA;
|
||||||
|
|
||||||
|
if (CurChannel == 0) return;
|
||||||
|
ack[0x9] = CurChannel;
|
||||||
|
|
||||||
*(u16*)&ack[0xC + 0x00] = 0x0218;
|
*(u16*)&ack[0xC + 0x00] = 0x0218;
|
||||||
*(u16*)&ack[0xC + 0x02] = 0;
|
*(u16*)&ack[0xC + 0x02] = 0;
|
||||||
*(u16*)&ack[0xC + 0x04] = 0x0903;
|
*(u16*)&ack[0xC + 0x04] = 0x0903;
|
||||||
@ -1110,8 +1257,11 @@ void Wifi::FinishRX()
|
|||||||
|
|
||||||
if (!ComStatus)
|
if (!ComStatus)
|
||||||
{
|
{
|
||||||
if (IOPORT(W_PowerState) & 0x0300)
|
if (IOPORT(W_PowerState) & (1<<9))
|
||||||
|
{
|
||||||
|
IOPORT(W_TRXPower) = 0;
|
||||||
SetStatus(9);
|
SetStatus(9);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SetStatus(1);
|
SetStatus(1);
|
||||||
}
|
}
|
||||||
@ -1380,7 +1530,7 @@ void Wifi::FinishRX()
|
|||||||
|
|
||||||
void Wifi::MPClientReplyRX(int client)
|
void Wifi::MPClientReplyRX(int client)
|
||||||
{
|
{
|
||||||
if (IOPORT(W_PowerState) & 0x0300)
|
if (IOPORT(W_PowerState) & (1<<9))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(IOPORT(W_RXCnt) & 0x8000))
|
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
|
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;
|
return false;
|
||||||
|
|
||||||
if (!(IOPORT(W_RXCnt) & 0x8000))
|
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 rxlen;
|
||||||
int framelen;
|
int framelen;
|
||||||
u16 framectl;
|
u16 framectl;
|
||||||
u8 txrate;
|
u8 txrate, chan;
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -1468,6 +1618,24 @@ bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames
|
|||||||
continue;
|
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];
|
framectl = *(u16*)&RXBuffer[12+0];
|
||||||
txrate = RXBuffer[8];
|
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
|
// we also need to determine how far we can run after having received this frame
|
||||||
|
|
||||||
RXTimestamp = timestamp;
|
RXTimestamp = timestamp;
|
||||||
//if (RXTimestamp < USTimestamp) printf("CRAP!! %04X %016llX %016llX\n", framectl, RXTimestamp, USTimestamp);
|
|
||||||
if (RXTimestamp < USTimestamp) RXTimestamp = USTimestamp;
|
if (RXTimestamp < USTimestamp) RXTimestamp = USTimestamp;
|
||||||
NextSync = RXTimestamp + (framelen * (txrate==0x14 ? 4:8));
|
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)
|
if (IOPORT(W_BeaconCount2) != 0)
|
||||||
{
|
{
|
||||||
@ -1605,19 +1774,19 @@ void Wifi::USTimer(u32 param)
|
|||||||
if (!(USTimestamp & 0x3FF & kTimeCheckMask))
|
if (!(USTimestamp & 0x3FF & kTimeCheckMask))
|
||||||
WifiAP->MSTimer();
|
WifiAP->MSTimer();
|
||||||
|
|
||||||
bool switchOffPowerSaving = false;
|
|
||||||
if (USUntilPowerOn < 0)
|
if (USUntilPowerOn < 0)
|
||||||
{
|
{
|
||||||
USUntilPowerOn += kTimerInterval;
|
USUntilPowerOn += kTimerInterval;
|
||||||
|
|
||||||
switchOffPowerSaving = (USUntilPowerOn >= 0) && (IOPORT(W_PowerUnk) & 0x0001 || ForcePowerOn);
|
if (USUntilPowerOn >= 0)
|
||||||
}
|
|
||||||
if ((USUntilPowerOn >= 0) && (IOPORT(W_PowerState) & 0x0002 || switchOffPowerSaving))
|
|
||||||
{
|
{
|
||||||
|
USUntilPowerOn = 0;
|
||||||
|
|
||||||
IOPORT(W_PowerState) = 0;
|
IOPORT(W_PowerState) = 0;
|
||||||
IOPORT(W_RFPins) = 1;
|
SetStatus(1);
|
||||||
IOPORT(W_RFPins) = 0x0084;
|
|
||||||
SetIRQ(11);
|
UpdatePowerStatus(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IOPORT(W_USCountCnt))
|
if (IOPORT(W_USCountCnt))
|
||||||
@ -1660,7 +1829,7 @@ void Wifi::USTimer(u32 param)
|
|||||||
u16 txbusy = IOPORT(W_TXBusy);
|
u16 txbusy = IOPORT(W_TXBusy);
|
||||||
if (txbusy)
|
if (txbusy)
|
||||||
{
|
{
|
||||||
if (IOPORT(W_PowerState) & 0x0300)
|
if (IOPORT(W_PowerState) & (1<<9))
|
||||||
{
|
{
|
||||||
ComStatus = 0;
|
ComStatus = 0;
|
||||||
TXCurSlot = -1;
|
TXCurSlot = -1;
|
||||||
@ -1695,9 +1864,10 @@ void Wifi::USTimer(u32 param)
|
|||||||
bool finished = ProcessTX(&TXSlots[TXCurSlot], TXCurSlot);
|
bool finished = ProcessTX(&TXSlots[TXCurSlot], TXCurSlot);
|
||||||
if (finished)
|
if (finished)
|
||||||
{
|
{
|
||||||
if (IOPORT(W_PowerState) & 0x0300)
|
if (IOPORT(W_PowerState) & (1<<9))
|
||||||
{
|
{
|
||||||
IOPORT(W_TXBusy) = 0;
|
IOPORT(W_TXBusy) = 0;
|
||||||
|
IOPORT(W_TRXPower) = 0;
|
||||||
SetStatus(9);
|
SetStatus(9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1754,8 +1924,9 @@ void Wifi::USTimer(u32 param)
|
|||||||
RXCounter = 0;
|
RXCounter = 0;
|
||||||
}
|
}
|
||||||
// TODO: proper error management
|
// TODO: proper error management
|
||||||
if ((!ComStatus) && (IOPORT(W_PowerState) & 0x0300))
|
if ((!ComStatus) && (IOPORT(W_PowerState) & (1<<9)))
|
||||||
{
|
{
|
||||||
|
IOPORT(W_TRXPower) = 0;
|
||||||
SetStatus(9);
|
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()
|
void Wifi::RFTransfer_Type2()
|
||||||
{
|
{
|
||||||
u32 id = (IOPORT(W_RFData2) >> 2) & 0x1F;
|
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);
|
u32 data = IOPORT(W_RFData1) | ((IOPORT(W_RFData2) & 0x0003) << 16);
|
||||||
RFRegs[id] = data;
|
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;
|
u32 data = IOPORT(W_RFData1) & 0xFF;
|
||||||
RFRegs[id] = data;
|
RFRegs[id] = data;
|
||||||
|
|
||||||
|
if (id == RFChannelIndex[0] || id == RFChannelIndex[1])
|
||||||
|
ChangeChannel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1819,6 +2018,7 @@ u16 Wifi::Read(u32 addr)
|
|||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case W_Random: // random generator. not accurate
|
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));
|
Random = (Random & 0x1) ^ (((Random & 0x3FF) << 1) | (Random >> 10));
|
||||||
return Random;
|
return Random;
|
||||||
|
|
||||||
@ -1899,7 +2099,6 @@ u16 Wifi::Read(u32 addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("WIFI: read %08X\n", addr);
|
|
||||||
return IOPORT(addr&0xFFF);
|
return IOPORT(addr&0xFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1923,28 +2122,20 @@ void Wifi::Write(u32 addr, u16 val)
|
|||||||
case W_ModeReset:
|
case W_ModeReset:
|
||||||
{
|
{
|
||||||
u16 oldval = IOPORT(W_ModeReset);
|
u16 oldval = IOPORT(W_ModeReset);
|
||||||
|
IOPORT(W_ModeReset) = val & 0x0001;
|
||||||
|
|
||||||
if (!(oldval & 0x0001) && (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;
|
IOPORT(0x27C) = 0x0005;
|
||||||
// TODO: 02A2??
|
// TODO: 02A2??
|
||||||
|
|
||||||
if (IOPORT(W_PowerUnk) & 0x0002)
|
UpdatePowerStatus(0);
|
||||||
{
|
|
||||||
USUntilPowerOn = -2048;
|
|
||||||
IOPORT(W_PowerState) |= 0x100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ((oldval & 0x0001) && !(val & 0x0001))
|
else if ((oldval & 0x0001) && !(val & 0x0001))
|
||||||
{
|
{
|
||||||
//printf("mode reset shutdown %08x\n", NDS::ARM7->R[15]);
|
|
||||||
IOPORT(0x27C) = 0x000A;
|
IOPORT(0x27C) = 0x000A;
|
||||||
PowerDown();
|
|
||||||
|
UpdatePowerStatus(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val & 0x2000)
|
if (val & 0x2000)
|
||||||
@ -1986,23 +2177,43 @@ void Wifi::Write(u32 addr, u16 val)
|
|||||||
IOPORT(0x230) = 0x0047;
|
IOPORT(0x230) = 0x0047;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case W_ModeWEP:
|
case W_ModeWEP:
|
||||||
val &= 0x007F;
|
val &= 0x007F;
|
||||||
//printf("writing mode web %x\n", val);
|
IOPORT(W_ModeWEP) = val;
|
||||||
if ((val & 0x7) == 1)
|
|
||||||
IOPORT(W_PowerUnk) |= 0x0002;
|
|
||||||
if ((val & 0x7) == 2)
|
|
||||||
IOPORT(W_PowerUnk) = 0x0003;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
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:
|
case W_IF:
|
||||||
IOPORT(W_IF) &= ~val;
|
IOPORT(W_IF) &= ~val;
|
||||||
return;
|
return;
|
||||||
case W_IFSet:
|
case W_IFSet:
|
||||||
|
{
|
||||||
|
u16 oldflags = IOPORT(W_IF) & IOPORT(W_IE);
|
||||||
IOPORT(W_IF) |= (val & 0xFBFF);
|
IOPORT(W_IF) |= (val & 0xFBFF);
|
||||||
|
CheckIRQ(oldflags);
|
||||||
Log(LogLevel::Debug, "wifi: force-setting IF %04X\n", val);
|
Log(LogLevel::Debug, "wifi: force-setting IF %04X\n", val);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case W_AIDLow:
|
case W_AIDLow:
|
||||||
@ -2012,67 +2223,63 @@ void Wifi::Write(u32 addr, u16 val)
|
|||||||
IOPORT(W_AIDFull) = val & 0x07FF;
|
IOPORT(W_AIDFull) = val & 0x07FF;
|
||||||
return;
|
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:
|
case W_PowerUS:
|
||||||
IOPORT(W_PowerUS) = val & 0x0003;
|
IOPORT(W_PowerUS) = val & 0x0003;
|
||||||
UpdatePowerOn();
|
UpdatePowerOn();
|
||||||
return;
|
return;
|
||||||
case W_PowerUnk:
|
|
||||||
val &= 0x0003;
|
case W_PowerTX:
|
||||||
//printf("writing power unk %x\n", val);
|
IOPORT(W_PowerTX) = val & 0x0003;
|
||||||
|
if (val & (1<<1))
|
||||||
|
{
|
||||||
if ((IOPORT(W_ModeWEP) & 0x7) == 1)
|
if ((IOPORT(W_ModeWEP) & 0x7) == 1)
|
||||||
val |= 2;
|
IOPORT(W_PowerDownCtrl) |= (1<<1);
|
||||||
else if ((IOPORT(W_ModeWEP) & 0x7) == 2)
|
else if ((IOPORT(W_ModeWEP) & 0x7) == 2)
|
||||||
val = 3;
|
IOPORT(W_PowerDownCtrl) = 3;
|
||||||
break;
|
|
||||||
|
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_USCountCnt: val &= 0x0001; break;
|
||||||
case W_USCompareCnt:
|
case W_USCompareCnt:
|
||||||
@ -2231,6 +2438,7 @@ void Wifi::Write(u32 addr, u16 val)
|
|||||||
|
|
||||||
// read-only ports
|
// read-only ports
|
||||||
case 0x000:
|
case 0x000:
|
||||||
|
case 0x034:
|
||||||
case 0x044:
|
case 0x044:
|
||||||
case 0x054:
|
case 0x054:
|
||||||
case 0x098:
|
case 0x098:
|
||||||
|
14
src/Wifi.h
14
src/Wifi.h
@ -52,11 +52,12 @@ public:
|
|||||||
W_RXCnt = 0x030,
|
W_RXCnt = 0x030,
|
||||||
W_WEPCnt = 0x032,
|
W_WEPCnt = 0x032,
|
||||||
|
|
||||||
|
W_TRXPower = 0x034,
|
||||||
W_PowerUS = 0x036,
|
W_PowerUS = 0x036,
|
||||||
W_PowerTX = 0x038,
|
W_PowerTX = 0x038,
|
||||||
W_PowerState = 0x03C,
|
W_PowerState = 0x03C,
|
||||||
W_PowerForce = 0x040,
|
W_PowerForce = 0x040,
|
||||||
W_PowerUnk = 0x48,
|
W_PowerDownCtrl = 0x48,
|
||||||
|
|
||||||
W_Random = 0x044,
|
W_Random = 0x044,
|
||||||
|
|
||||||
@ -206,6 +207,10 @@ private:
|
|||||||
u8 RFVersion;
|
u8 RFVersion;
|
||||||
u32 RFRegs[0x40];
|
u32 RFRegs[0x40];
|
||||||
|
|
||||||
|
u32 RFChannelIndex[2];
|
||||||
|
u32 RFChannelData[14][2];
|
||||||
|
int CurChannel;
|
||||||
|
|
||||||
struct TXSlot
|
struct TXSlot
|
||||||
{
|
{
|
||||||
bool Valid;
|
bool Valid;
|
||||||
@ -240,7 +245,6 @@ private:
|
|||||||
bool LANInited;
|
bool LANInited;
|
||||||
|
|
||||||
int USUntilPowerOn;
|
int USUntilPowerOn;
|
||||||
bool ForcePowerOn;
|
|
||||||
|
|
||||||
// MULTIPLAYER SYNC APPARATUS
|
// MULTIPLAYER SYNC APPARATUS
|
||||||
bool IsMP;
|
bool IsMP;
|
||||||
@ -253,13 +257,15 @@ private:
|
|||||||
void ScheduleTimer(bool first);
|
void ScheduleTimer(bool first);
|
||||||
void UpdatePowerOn();
|
void UpdatePowerOn();
|
||||||
|
|
||||||
|
void CheckIRQ(u16 oldflags);
|
||||||
void SetIRQ(u32 irq);
|
void SetIRQ(u32 irq);
|
||||||
void SetIRQ13();
|
void SetIRQ13();
|
||||||
void SetIRQ14(int source);
|
void SetIRQ14(int source);
|
||||||
void SetIRQ15();
|
void SetIRQ15();
|
||||||
|
|
||||||
void SetStatus(u32 status);
|
void SetStatus(u32 status);
|
||||||
void PowerDown();
|
|
||||||
|
void UpdatePowerStatus(int power);
|
||||||
|
|
||||||
int PreambleLen(int rate) const;
|
int PreambleLen(int rate) const;
|
||||||
u32 NumClients(u16 bitmask) const;
|
u32 NumClients(u16 bitmask) const;
|
||||||
@ -284,6 +290,8 @@ private:
|
|||||||
|
|
||||||
void MSTimer();
|
void MSTimer();
|
||||||
|
|
||||||
|
void ChangeChannel();
|
||||||
|
|
||||||
void RFTransfer_Type2();
|
void RFTransfer_Type2();
|
||||||
void RFTransfer_Type3();
|
void RFTransfer_Type3();
|
||||||
};
|
};
|
||||||
|
@ -35,6 +35,7 @@ using Platform::LogLevel;
|
|||||||
|
|
||||||
const char* WifiAP::APName = "melonAP";
|
const char* WifiAP::APName = "melonAP";
|
||||||
const u8 WifiAP::APMac[6] = {0x00, 0xF0, 0x77, 0x77, 0x77, 0x77};
|
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_8(p, v) *p++ = v;
|
||||||
#define PWRITE_16(p, v) *(u16*)p = v; p += 2;
|
#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_16(p, 0); \
|
PWRITE_16(p, 0); \
|
||||||
PWRITE_8(p, rate); \
|
PWRITE_8(p, rate); \
|
||||||
PWRITE_8(p, 0); \
|
PWRITE_8(p, APChannel); \
|
||||||
PWRITE_16(p, len);
|
PWRITE_16(p, len);
|
||||||
|
|
||||||
//#define PALIGN_4(p, base) p += ((4 - ((ptrdiff_t)(p-base) & 0x3)) & 0x3);
|
//#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, 128); // beacon interval
|
||||||
PWRITE_16(p, 0x0021); // capability
|
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, 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));
|
PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName));
|
||||||
memcpy(p, APName, strlen(APName)); 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)
|
int WifiAP::SendPacket(const u8* data, int len)
|
||||||
{
|
{
|
||||||
|
if (data[9] != APChannel)
|
||||||
|
return 0;
|
||||||
|
|
||||||
data += 12;
|
data += 12;
|
||||||
|
|
||||||
u16 framectl = *(u16*)&data[0];
|
u16 framectl = *(u16*)&data[0];
|
||||||
@ -327,7 +331,7 @@ int WifiAP::RecvPacket(u8* data)
|
|||||||
PWRITE_16(p, 128); // beacon interval
|
PWRITE_16(p, 128); // beacon interval
|
||||||
PWRITE_16(p, 0x0021); // capability
|
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, 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, 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));
|
PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName));
|
||||||
memcpy(p, APName, strlen(APName)); p += strlen(APName);
|
memcpy(p, APName, strlen(APName)); p += strlen(APName);
|
||||||
|
@ -34,6 +34,7 @@ public:
|
|||||||
|
|
||||||
static const char* APName;
|
static const char* APName;
|
||||||
static const u8 APMac[6];
|
static const u8 APMac[6];
|
||||||
|
static const u8 APChannel;
|
||||||
|
|
||||||
void MSTimer();
|
void MSTimer();
|
||||||
|
|
||||||
|
@ -63,21 +63,28 @@ int AudioOut_GetNumSamples(int outlen)
|
|||||||
|
|
||||||
void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume)
|
void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume)
|
||||||
{
|
{
|
||||||
float res_incr = inlen / (float)outlen;
|
double factor = (double) inlen / (double) outlen;
|
||||||
float res_timer = 0;
|
double inpos = -(factor / 2);
|
||||||
int res_pos = 0;
|
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;
|
double intpart_d;
|
||||||
outbuf[i*2+1] = (inbuf[res_pos*2+1] * volume) >> 8;
|
double frac = modf(inpos, &intpart_d);
|
||||||
|
int intpart = (int) intpart_d;
|
||||||
|
|
||||||
res_timer += res_incr;
|
double l1 = inbuf[ intpart * 2];
|
||||||
while (res_timer >= 1.0)
|
double l2 = inbuf[(intpart * 2) + 2];
|
||||||
{
|
double r1 = inbuf[(intpart * 2) + 1];
|
||||||
res_timer -= 1.0;
|
double r2 = inbuf[(intpart * 2) + 3];
|
||||||
res_pos++;
|
|
||||||
}
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent, bool emuActive, EmuThr
|
|||||||
ui->cbInterpolation->addItem("Linear");
|
ui->cbInterpolation->addItem("Linear");
|
||||||
ui->cbInterpolation->addItem("Cosine");
|
ui->cbInterpolation->addItem("Cosine");
|
||||||
ui->cbInterpolation->addItem("Cubic");
|
ui->cbInterpolation->addItem("Cubic");
|
||||||
|
ui->cbInterpolation->addItem("Gaussian (SNES)");
|
||||||
ui->cbInterpolation->setCurrentIndex(Config::AudioInterp);
|
ui->cbInterpolation->setCurrentIndex(Config::AudioInterp);
|
||||||
|
|
||||||
ui->cbBitDepth->addItem("Automatic");
|
ui->cbBitDepth->addItem("Automatic");
|
||||||
@ -173,7 +174,7 @@ void AudioSettingsDialog::on_cbBitDepth_currentIndexChanged(int idx)
|
|||||||
void AudioSettingsDialog::on_cbInterpolation_currentIndexChanged(int idx)
|
void AudioSettingsDialog::on_cbInterpolation_currentIndexChanged(int idx)
|
||||||
{
|
{
|
||||||
// prevent a spurious change
|
// prevent a spurious change
|
||||||
if (ui->cbInterpolation->count() < 4) return;
|
if (ui->cbInterpolation->count() < 5) return;
|
||||||
|
|
||||||
Config::AudioInterp = ui->cbInterpolation->currentIndex();
|
Config::AudioInterp = ui->cbInterpolation->currentIndex();
|
||||||
|
|
||||||
|
@ -131,8 +131,8 @@ std::unique_ptr<NDS> EmuThread::CreateConsole(
|
|||||||
NDSArgs ndsargs {
|
NDSArgs ndsargs {
|
||||||
std::move(ndscart),
|
std::move(ndscart),
|
||||||
std::move(gbacart),
|
std::move(gbacart),
|
||||||
*arm9bios,
|
std::move(arm9bios),
|
||||||
*arm7bios,
|
std::move(arm7bios),
|
||||||
std::move(*firmware),
|
std::move(*firmware),
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
Config::JIT_Enable ? std::make_optional(jitargs) : std::nullopt,
|
Config::JIT_Enable ? std::make_optional(jitargs) : std::nullopt,
|
||||||
@ -165,8 +165,8 @@ std::unique_ptr<NDS> EmuThread::CreateConsole(
|
|||||||
auto sdcard = ROMManager::LoadDSiSDCard();
|
auto sdcard = ROMManager::LoadDSiSDCard();
|
||||||
DSiArgs args {
|
DSiArgs args {
|
||||||
std::move(ndsargs),
|
std::move(ndsargs),
|
||||||
*arm9ibios,
|
std::move(arm9ibios),
|
||||||
*arm7ibios,
|
std::move(arm7ibios),
|
||||||
std::move(*nand),
|
std::move(*nand),
|
||||||
std::move(sdcard),
|
std::move(sdcard),
|
||||||
Config::DSiFullBIOSBoot,
|
Config::DSiFullBIOSBoot,
|
||||||
|
@ -128,6 +128,11 @@ void KeyRelease(QKeyEvent* event)
|
|||||||
KeyHotkeyMask &= ~(1<<i);
|
KeyHotkeyMask &= ~(1<<i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyReleaseAll()
|
||||||
|
{
|
||||||
|
KeyInputMask = 0xFFF;
|
||||||
|
KeyHotkeyMask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool JoystickButtonDown(int val)
|
bool JoystickButtonDown(int val)
|
||||||
{
|
{
|
||||||
@ -204,16 +209,22 @@ void Process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
JoyInputMask = 0xFFF;
|
JoyInputMask = 0xFFF;
|
||||||
|
if (Joystick)
|
||||||
|
{
|
||||||
for (int i = 0; i < 12; i++)
|
for (int i = 0; i < 12; i++)
|
||||||
if (JoystickButtonDown(Config::JoyMapping[i]))
|
if (JoystickButtonDown(Config::JoyMapping[i]))
|
||||||
JoyInputMask &= ~(1 << i);
|
JoyInputMask &= ~(1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
InputMask = KeyInputMask & JoyInputMask;
|
InputMask = KeyInputMask & JoyInputMask;
|
||||||
|
|
||||||
JoyHotkeyMask = 0;
|
JoyHotkeyMask = 0;
|
||||||
|
if (Joystick)
|
||||||
|
{
|
||||||
for (int i = 0; i < HK_MAX; i++)
|
for (int i = 0; i < HK_MAX; i++)
|
||||||
if (JoystickButtonDown(Config::HKJoyMapping[i]))
|
if (JoystickButtonDown(Config::HKJoyMapping[i]))
|
||||||
JoyHotkeyMask |= (1 << i);
|
JoyHotkeyMask |= (1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
HotkeyMask = KeyHotkeyMask | JoyHotkeyMask;
|
HotkeyMask = KeyHotkeyMask | JoyHotkeyMask;
|
||||||
HotkeyPress = HotkeyMask & ~LastHotkeyMask;
|
HotkeyPress = HotkeyMask & ~LastHotkeyMask;
|
||||||
|
@ -40,6 +40,7 @@ void CloseJoystick();
|
|||||||
|
|
||||||
void KeyPress(QKeyEvent* event);
|
void KeyPress(QKeyEvent* event);
|
||||||
void KeyRelease(QKeyEvent* event);
|
void KeyRelease(QKeyEvent* event);
|
||||||
|
void KeyReleaseAll();
|
||||||
|
|
||||||
void Process();
|
void Process();
|
||||||
|
|
||||||
|
@ -216,9 +216,30 @@ std::string InstanceFileSuffix()
|
|||||||
return suffix;
|
return suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QIODevice::OpenMode GetQMode(FileMode mode)
|
||||||
|
{
|
||||||
|
QIODevice::OpenMode qmode = QIODevice::OpenModeFlag::NotOpen;
|
||||||
|
if (mode & FileMode::Read)
|
||||||
|
qmode |= QIODevice::OpenModeFlag::ReadOnly;
|
||||||
|
if (mode & FileMode::Write)
|
||||||
|
qmode |= QIODevice::OpenModeFlag::WriteOnly;
|
||||||
|
if (mode & FileMode::Append)
|
||||||
|
qmode |= QIODevice::OpenModeFlag::Append;
|
||||||
|
|
||||||
|
if ((mode & FileMode::Write) && !(mode & FileMode::Preserve))
|
||||||
|
qmode |= QIODevice::OpenModeFlag::Truncate;
|
||||||
|
|
||||||
|
if (mode & FileMode::NoCreate)
|
||||||
|
qmode |= QIODevice::OpenModeFlag::ExistingOnly;
|
||||||
|
|
||||||
|
if (mode & FileMode::Text)
|
||||||
|
qmode |= QIODevice::OpenModeFlag::Text;
|
||||||
|
|
||||||
|
return qmode;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr char AccessMode(FileMode mode, bool file_exists)
|
constexpr char AccessMode(FileMode mode, bool file_exists)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (mode & FileMode::Append)
|
if (mode & FileMode::Append)
|
||||||
return 'a';
|
return 'a';
|
||||||
|
|
||||||
@ -266,10 +287,15 @@ FileHandle* OpenFile(const std::string& path, FileMode mode)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool file_exists = QFile::exists(QString::fromStdString(path));
|
QString qpath{QString::fromStdString(path)};
|
||||||
std::string modeString = GetModeString(mode, file_exists);
|
|
||||||
|
std::string modeString = GetModeString(mode, QFile::exists(qpath));
|
||||||
|
QIODevice::OpenMode qmode = GetQMode(mode);
|
||||||
|
QFile qfile{qpath};
|
||||||
|
qfile.open(qmode);
|
||||||
|
FILE* file = fdopen(dup(qfile.handle()), modeString.c_str());
|
||||||
|
qfile.close();
|
||||||
|
|
||||||
FILE* file = fopen(path.c_str(), modeString.c_str());
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "Opened \"%s\" with FileMode 0x%x (effective mode \"%s\")\n", path.c_str(), mode, modeString.c_str());
|
Log(LogLevel::Debug, "Opened \"%s\" with FileMode 0x%x (effective mode \"%s\")\n", path.c_str(), mode, modeString.c_str());
|
||||||
|
@ -512,59 +512,59 @@ void LoadCheats(NDS& nds)
|
|||||||
nds.AREngine.SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
nds.AREngine.SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::array<u8, ARM9BIOSSize>> LoadARM9BIOS() noexcept
|
std::unique_ptr<ARM9BIOSImage> LoadARM9BIOS() noexcept
|
||||||
{
|
{
|
||||||
if (!Config::ExternalBIOSEnable)
|
if (!Config::ExternalBIOSEnable)
|
||||||
{
|
{
|
||||||
return Config::ConsoleType == 0 ? std::make_optional(bios_arm9_bin) : std::nullopt;
|
return Config::ConsoleType == 0 ? std::make_unique<ARM9BIOSImage>(bios_arm9_bin) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileHandle* f = OpenLocalFile(Config::BIOS9Path, Read))
|
if (FileHandle* f = OpenLocalFile(Config::BIOS9Path, Read))
|
||||||
{
|
{
|
||||||
std::array<u8, ARM9BIOSSize> bios {};
|
std::unique_ptr<ARM9BIOSImage> bios = std::make_unique<ARM9BIOSImage>();
|
||||||
FileRewind(f);
|
FileRewind(f);
|
||||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
FileRead(bios->data(), bios->size(), 1, f);
|
||||||
CloseFile(f);
|
CloseFile(f);
|
||||||
Log(Info, "ARM9 BIOS loaded from %s\n", Config::BIOS9Path.c_str());
|
Log(Info, "ARM9 BIOS loaded from %s\n", Config::BIOS9Path.c_str());
|
||||||
return bios;
|
return bios;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Warn, "ARM9 BIOS not found\n");
|
Log(Warn, "ARM9 BIOS not found\n");
|
||||||
return std::nullopt;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::array<u8, ARM7BIOSSize>> LoadARM7BIOS() noexcept
|
std::unique_ptr<ARM7BIOSImage> LoadARM7BIOS() noexcept
|
||||||
{
|
{
|
||||||
if (!Config::ExternalBIOSEnable)
|
if (!Config::ExternalBIOSEnable)
|
||||||
{
|
{
|
||||||
return Config::ConsoleType == 0 ? std::make_optional(bios_arm7_bin) : std::nullopt;
|
return Config::ConsoleType == 0 ? std::make_unique<ARM7BIOSImage>(bios_arm7_bin) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileHandle* f = OpenLocalFile(Config::BIOS7Path, Read))
|
if (FileHandle* f = OpenLocalFile(Config::BIOS7Path, Read))
|
||||||
{
|
{
|
||||||
std::array<u8, ARM7BIOSSize> bios {};
|
std::unique_ptr<ARM7BIOSImage> bios = std::make_unique<ARM7BIOSImage>();
|
||||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
FileRead(bios->data(), bios->size(), 1, f);
|
||||||
CloseFile(f);
|
CloseFile(f);
|
||||||
Log(Info, "ARM7 BIOS loaded from %s\n", Config::BIOS7Path.c_str());
|
Log(Info, "ARM7 BIOS loaded from %s\n", Config::BIOS7Path.c_str());
|
||||||
return bios;
|
return bios;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Warn, "ARM7 BIOS not found\n");
|
Log(Warn, "ARM7 BIOS not found\n");
|
||||||
return std::nullopt;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM9BIOS() noexcept
|
std::unique_ptr<DSiBIOSImage> LoadDSiARM9BIOS() noexcept
|
||||||
{
|
{
|
||||||
if (FileHandle* f = OpenLocalFile(Config::DSiBIOS9Path, Read))
|
if (FileHandle* f = OpenLocalFile(Config::DSiBIOS9Path, Read))
|
||||||
{
|
{
|
||||||
std::array<u8, DSiBIOSSize> bios {};
|
std::unique_ptr<DSiBIOSImage> bios = std::make_unique<DSiBIOSImage>();
|
||||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
FileRead(bios->data(), bios->size(), 1, f);
|
||||||
CloseFile(f);
|
CloseFile(f);
|
||||||
|
|
||||||
if (!Config::DSiFullBIOSBoot)
|
if (!Config::DSiFullBIOSBoot)
|
||||||
{
|
{
|
||||||
// herp
|
// herp
|
||||||
*(u32*)&bios[0] = 0xEAFFFFFE; // overwrites the reset vector
|
*(u32*)bios->data() = 0xEAFFFFFE; // overwrites the reset vector
|
||||||
|
|
||||||
// TODO!!!!
|
// TODO!!!!
|
||||||
// hax the upper 32K out of the goddamn DSi
|
// hax the upper 32K out of the goddamn DSi
|
||||||
@ -575,21 +575,21 @@ std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM9BIOS() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log(Warn, "ARM9i BIOS not found\n");
|
Log(Warn, "ARM9i BIOS not found\n");
|
||||||
return std::nullopt;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM7BIOS() noexcept
|
std::unique_ptr<DSiBIOSImage> LoadDSiARM7BIOS() noexcept
|
||||||
{
|
{
|
||||||
if (FileHandle* f = OpenLocalFile(Config::DSiBIOS7Path, Read))
|
if (FileHandle* f = OpenLocalFile(Config::DSiBIOS7Path, Read))
|
||||||
{
|
{
|
||||||
std::array<u8, DSiBIOSSize> bios {};
|
std::unique_ptr<DSiBIOSImage> bios = std::make_unique<DSiBIOSImage>();
|
||||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
FileRead(bios->data(), bios->size(), 1, f);
|
||||||
CloseFile(f);
|
CloseFile(f);
|
||||||
|
|
||||||
if (!Config::DSiFullBIOSBoot)
|
if (!Config::DSiFullBIOSBoot)
|
||||||
{
|
{
|
||||||
// herp
|
// herp
|
||||||
*(u32*)&bios[0] = 0xEAFFFFFE; // overwrites the reset vector
|
*(u32*)bios->data() = 0xEAFFFFFE; // overwrites the reset vector
|
||||||
|
|
||||||
// TODO!!!!
|
// TODO!!!!
|
||||||
// hax the upper 32K out of the goddamn DSi
|
// hax the upper 32K out of the goddamn DSi
|
||||||
@ -600,7 +600,7 @@ std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM7BIOS() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log(Warn, "ARM7i BIOS not found\n");
|
Log(Warn, "ARM7i BIOS not found\n");
|
||||||
return std::nullopt;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Firmware GenerateFirmware(int type) noexcept
|
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,
|
// If we don't have Wi-fi settings to load,
|
||||||
// then the defaults will have already been populated by the constructor.
|
// then the defaults will have already been populated by the constructor.
|
||||||
@ -681,10 +681,7 @@ std::optional<Firmware> LoadFirmware(int type) noexcept
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config::FirmwareOverrideSettings)
|
CustomizeFirmware(firmware, Config::FirmwareOverrideSettings);
|
||||||
{
|
|
||||||
CustomizeFirmware(firmware);
|
|
||||||
}
|
|
||||||
|
|
||||||
return firmware;
|
return firmware;
|
||||||
}
|
}
|
||||||
@ -916,6 +913,8 @@ void Reset(EmuThread* thread)
|
|||||||
thread->NDS->SetupDirectBoot(BaseROMName);
|
thread->NDS->SetupDirectBoot(BaseROMName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread->NDS->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1118,7 +1117,9 @@ bool ParseMacAddress(void* data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomizeFirmware(Firmware& firmware) noexcept
|
void CustomizeFirmware(Firmware& firmware, bool overridesettings) noexcept
|
||||||
|
{
|
||||||
|
if (overridesettings)
|
||||||
{
|
{
|
||||||
auto ¤tData = firmware.GetEffectiveUserData();
|
auto ¤tData = firmware.GetEffectiveUserData();
|
||||||
|
|
||||||
@ -1126,7 +1127,8 @@ void CustomizeFirmware(Firmware& firmware) noexcept
|
|||||||
std::string orig_username = Config::FirmwareUsername;
|
std::string orig_username = Config::FirmwareUsername;
|
||||||
if (!orig_username.empty())
|
if (!orig_username.empty())
|
||||||
{ // If the frontend defines a username, take it. If not, leave the existing one.
|
{ // If the frontend defines a username, take it. If not, leave the existing one.
|
||||||
std::u16string username = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(orig_username);
|
std::u16string username = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(
|
||||||
|
orig_username);
|
||||||
size_t usernameLength = std::min(username.length(), (size_t) 10);
|
size_t usernameLength = std::min(username.length(), (size_t) 10);
|
||||||
currentData.NameLength = usernameLength;
|
currentData.NameLength = usernameLength;
|
||||||
memcpy(currentData.Nickname, username.data(), usernameLength * sizeof(char16_t));
|
memcpy(currentData.Nickname, username.data(), usernameLength * sizeof(char16_t));
|
||||||
@ -1162,11 +1164,13 @@ void CustomizeFirmware(Firmware& firmware) noexcept
|
|||||||
std::string orig_message = Config::FirmwareMessage;
|
std::string orig_message = Config::FirmwareMessage;
|
||||||
if (!orig_message.empty())
|
if (!orig_message.empty())
|
||||||
{
|
{
|
||||||
std::u16string message = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(orig_message);
|
std::u16string message = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(
|
||||||
|
orig_message);
|
||||||
size_t messageLength = std::min(message.length(), (size_t) 26);
|
size_t messageLength = std::min(message.length(), (size_t) 26);
|
||||||
currentData.MessageLength = messageLength;
|
currentData.MessageLength = messageLength;
|
||||||
memcpy(currentData.Message, message.data(), messageLength * sizeof(char16_t));
|
memcpy(currentData.Message, message.data(), messageLength * sizeof(char16_t));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MacAddress mac;
|
MacAddress mac;
|
||||||
bool rep = false;
|
bool rep = false;
|
||||||
@ -1174,7 +1178,8 @@ void CustomizeFirmware(Firmware& firmware) noexcept
|
|||||||
|
|
||||||
memcpy(&mac, header.MacAddr.data(), sizeof(MacAddress));
|
memcpy(&mac, header.MacAddr.data(), sizeof(MacAddress));
|
||||||
|
|
||||||
|
if (overridesettings)
|
||||||
|
{
|
||||||
MacAddress configuredMac;
|
MacAddress configuredMac;
|
||||||
rep = ParseMacAddress(&configuredMac);
|
rep = ParseMacAddress(&configuredMac);
|
||||||
rep &= (configuredMac != MacAddress());
|
rep &= (configuredMac != MacAddress());
|
||||||
@ -1183,6 +1188,7 @@ void CustomizeFirmware(Firmware& firmware) noexcept
|
|||||||
{
|
{
|
||||||
mac = configuredMac;
|
mac = configuredMac;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int inst = Platform::InstanceID();
|
int inst = Platform::InstanceID();
|
||||||
if (inst > 0)
|
if (inst > 0)
|
||||||
@ -1566,23 +1572,28 @@ QString GBACartLabel()
|
|||||||
|
|
||||||
void ROMIcon(const u8 (&data)[512], const u16 (&palette)[16], u32 (&iconRef)[32*32])
|
void ROMIcon(const u8 (&data)[512], const u16 (&palette)[16], u32 (&iconRef)[32*32])
|
||||||
{
|
{
|
||||||
int index = 0;
|
u32 paletteRGBA[16];
|
||||||
for (int i = 0; i < 4; i++)
|
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 k = 0; k < 8; k++)
|
for (int xtile = 0; xtile < 4; xtile++)
|
||||||
{
|
{
|
||||||
for (int l = 0; l < 8; l++)
|
for (int ypixel = 0; ypixel < 8; ypixel++)
|
||||||
{
|
{
|
||||||
u8 pal_index = index % 2 ? data[index/2] >> 4 : data[index/2] & 0x0F;
|
for (int xpixel = 0; xpixel < 8; xpixel++)
|
||||||
u8 r = ((palette[pal_index] >> 0) & 0x1F) * 255 / 31;
|
{
|
||||||
u8 g = ((palette[pal_index] >> 5) & 0x1F) * 255 / 31;
|
u8 pal_index = count % 2 ? data[count/2] >> 4 : data[count/2] & 0x0F;
|
||||||
u8 b = ((palette[pal_index] >> 10) & 0x1F) * 255 / 31;
|
iconRef[ytile*256 + ypixel*32 + xtile*8 + xpixel] = paletteRGBA[pal_index];
|
||||||
u8 a = pal_index ? 255: 0;
|
count++;
|
||||||
u32* row = &iconRef[256 * i + 32 * k + 8 * j];
|
|
||||||
row[l] = r | (g << 8) | (b << 16) | (a << 24);
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
#include "MemConstants.h"
|
#include "MemConstants.h"
|
||||||
|
|
||||||
|
#include <Args.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -56,16 +58,16 @@ void ClearBackupState();
|
|||||||
|
|
||||||
/// Returns the configured ARM9 BIOS loaded from disk,
|
/// Returns the configured ARM9 BIOS loaded from disk,
|
||||||
/// the FreeBIOS if external BIOS is disabled and we're in NDS mode,
|
/// the FreeBIOS if external BIOS is disabled and we're in NDS mode,
|
||||||
/// or nullopt if loading failed.
|
/// or nullptr if loading failed.
|
||||||
std::optional<std::array<u8, ARM9BIOSSize>> LoadARM9BIOS() noexcept;
|
std::unique_ptr<ARM9BIOSImage> LoadARM9BIOS() noexcept;
|
||||||
std::optional<std::array<u8, ARM7BIOSSize>> LoadARM7BIOS() noexcept;
|
std::unique_ptr<ARM7BIOSImage> LoadARM7BIOS() noexcept;
|
||||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM9BIOS() noexcept;
|
std::unique_ptr<DSiBIOSImage> LoadDSiARM9BIOS() noexcept;
|
||||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM7BIOS() noexcept;
|
std::unique_ptr<DSiBIOSImage> LoadDSiARM7BIOS() noexcept;
|
||||||
std::optional<FATStorageArgs> GetDSiSDCardArgs() noexcept;
|
std::optional<FATStorageArgs> GetDSiSDCardArgs() noexcept;
|
||||||
std::optional<FATStorage> LoadDSiSDCard() noexcept;
|
std::optional<FATStorage> LoadDSiSDCard() noexcept;
|
||||||
std::optional<FATStorageArgs> GetDLDISDCardArgs() noexcept;
|
std::optional<FATStorageArgs> GetDLDISDCardArgs() noexcept;
|
||||||
std::optional<FATStorage> LoadDLDISDCard() noexcept;
|
std::optional<FATStorage> LoadDLDISDCard() noexcept;
|
||||||
void CustomizeFirmware(Firmware& firmware) noexcept;
|
void CustomizeFirmware(Firmware& firmware, bool overridesettings) noexcept;
|
||||||
Firmware GenerateFirmware(int type) noexcept;
|
Firmware GenerateFirmware(int type) noexcept;
|
||||||
/// Loads and customizes a firmware image based on the values in Config
|
/// Loads and customizes a firmware image based on the values in Config
|
||||||
std::optional<Firmware> LoadFirmware(int type) noexcept;
|
std::optional<Firmware> LoadFirmware(int type) noexcept;
|
||||||
|
@ -214,7 +214,7 @@ void ScreenPanel::mouseMoveEvent(QMouseEvent* event)
|
|||||||
|
|
||||||
showCursor();
|
showCursor();
|
||||||
|
|
||||||
if (!(event->buttons() & Qt::LeftButton)) return;
|
//if (!(event->buttons() & Qt::LeftButton)) return;
|
||||||
if (!touching) return;
|
if (!touching) return;
|
||||||
|
|
||||||
int x = event->pos().x();
|
int x = event->pos().x();
|
||||||
|
@ -805,7 +805,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
|
|||||||
if (event->isAutoRepeat()) return;
|
if (event->isAutoRepeat()) return;
|
||||||
|
|
||||||
// TODO!! REMOVE ME IN RELEASE BUILDS!!
|
// 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);
|
Input::KeyPress(event);
|
||||||
}
|
}
|
||||||
@ -916,6 +916,7 @@ void MainWindow::onAppStateChanged(Qt::ApplicationState state)
|
|||||||
{
|
{
|
||||||
if (state == Qt::ApplicationInactive)
|
if (state == Qt::ApplicationInactive)
|
||||||
{
|
{
|
||||||
|
Input::KeyReleaseAll();
|
||||||
if (Config::PauseLostFocus && emuThread->emuIsRunning())
|
if (Config::PauseLostFocus && emuThread->emuIsRunning())
|
||||||
emuThread->emuPause();
|
emuThread->emuPause();
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ int main(int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
SANITIZE(Config::ScreenVSyncInterval, 1, 20);
|
SANITIZE(Config::ScreenVSyncInterval, 1, 20);
|
||||||
SANITIZE(Config::GL_ScaleFactor, 1, 16);
|
SANITIZE(Config::GL_ScaleFactor, 1, 16);
|
||||||
SANITIZE(Config::AudioInterp, 0, 3);
|
SANITIZE(Config::AudioInterp, 0, 4);
|
||||||
SANITIZE(Config::AudioVolume, 0, 256);
|
SANITIZE(Config::AudioVolume, 0, 256);
|
||||||
SANITIZE(Config::MicInputType, 0, (int)micInputType_MAX);
|
SANITIZE(Config::MicInputType, 0, (int)micInputType_MAX);
|
||||||
SANITIZE(Config::ScreenRotation, 0, (int)Frontend::screenRot_MAX);
|
SANITIZE(Config::ScreenRotation, 0, (int)Frontend::screenRot_MAX);
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"sdl2",
|
"sdl2",
|
||||||
"libarchive",
|
{
|
||||||
|
"name": "libarchive",
|
||||||
|
"default-features": false,
|
||||||
|
"features": ["bzip2", "crypto", "lz4", "zstd"]
|
||||||
|
},
|
||||||
"libslirp",
|
"libslirp",
|
||||||
"zstd",
|
"zstd",
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user