mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-05-20 05:10:27 -04:00
Compare commits
17 commits
d1a80e126b
...
8641abcf86
Author | SHA1 | Date | |
---|---|---|---|
8641abcf86 | |||
10798c3464 | |||
ee2c6cc7c2 | |||
474bf6e784 | |||
35cea5e1d7 | |||
6112aa120a | |||
ba8d547dfa | |||
84474105e2 | |||
5a852cb00d | |||
95adc87f6d | |||
8feeee6103 | |||
d99c571f94 | |||
111dc7a563 | |||
0b87dd5fa6 | |||
968bd26d85 | |||
6e26559cd2 | |||
4754596870 |
2
.github/workflows/build-macos.yml
vendored
2
.github/workflows/build-macos.yml
vendored
|
@ -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
|
||||
|
|
|
@ -8,6 +8,7 @@ endif()
|
|||
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_SOURCE_DIR}/cmake/DefaultBuildFlags.cmake")
|
||||
|
||||
option(USE_VCPKG "Use vcpkg for dependency packages" OFF)
|
||||
if (USE_VCPKG)
|
||||
|
@ -78,14 +79,6 @@ if (ENABLE_LTO)
|
|||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Og")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og")
|
||||
endif()
|
||||
|
||||
string(REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
if (NOT APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s")
|
||||
endif()
|
||||
|
|
|
@ -6,10 +6,9 @@
|
|||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-%23ff554d.svg"></a>
|
||||
<a href="https://kiwiirc.com/client/irc.badnik.net/?nick=IRC-Source_?#melonds" alt="IRC channel: #melonds"><img src="https://img.shields.io/badge/IRC%20chat-%23melonds-%23dd2e44.svg"></a>
|
||||
<br>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions?query=workflow%3A%22CMake+Build+%28Windows+x86-64%29%22+event%3Apush"><img src="https://img.shields.io/github/actions/workflow/status/melonDS-emu/melonDS/build-windows.yml?label=Windows%20x86-64&logo=GitHub&branch=master"></img></a>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions?query=workflow%3A%22CMake+Build+%28Ubuntu+x86-64%29%22+event%3Apush"><img src="https://img.shields.io/github/actions/workflow/status/melonDS-emu/melonDS/build-ubuntu.yml?label=Linux%20x86-64&logo=GitHub"></img></a>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions?query=workflow%3A%22CMake+Build+%28Ubuntu+aarch64%29%22+event%3Apush"><img src="https://img.shields.io/github/actions/workflow/status/melonDS-emu/melonDS/build-ubuntu-aarch64.yml?label=Linux%20ARM64&logo=GitHub"></img></a>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions/workflows/build-macos-universal.yml?query=event%3Apush"><img src="https://img.shields.io/github/actions/workflow/status/melonDS-emu/melonDS/build-macos.yml?label=macOS%20Universal&logo=GitHub"></img></a>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions/workflows/build-windows.yml?query=event%3Apush"><img src="https://github.com/melonDS-emu/melonDS/actions/workflows/build-windows.yml/badge.svg" /></a>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions/workflows/build-ubuntu.yml?query=event%3Apush"><img src="https://github.com/melonDS-emu/melonDS/actions/workflows/build-ubuntu.yml/badge.svg" /></a>
|
||||
<a href="https://github.com/melonDS-emu/melonDS/actions/workflows/build-macos.yml?query=event%3Apush"><img src="https://github.com/melonDS-emu/melonDS/actions/workflows/build-macos.yml/badge.svg" /></a>
|
||||
</p>
|
||||
DS emulator, sorta
|
||||
|
||||
|
|
9
cmake/DefaultBuildFlags.cmake
Normal file
9
cmake/DefaultBuildFlags.cmake
Normal file
|
@ -0,0 +1,9 @@
|
|||
if (CMAKE_C_COMPILER_ID STREQUAL GNU)
|
||||
set(CMAKE_C_FLAGS_DEBUG_INIT "-g -Og")
|
||||
endif()
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-g -Og")
|
||||
endif()
|
||||
|
||||
string(REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT}")
|
||||
string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_CXX_FLAGS_RELEASE_INIT}")
|
|
@ -19,6 +19,13 @@ function(fix_interface_includes)
|
|||
if (PARENT_DIR MATCHES "include$")
|
||||
list(APPEND NEW_DIRS "${PARENT_DIR}")
|
||||
endif()
|
||||
|
||||
# HACK
|
||||
# The libarchive pkg-config file in MSYS2 seems to include a UNIX-style path for its
|
||||
# include directory and CMake doesn't like that.
|
||||
if (WIN32 AND MINGW AND target STREQUAL PkgConfig::LibArchive)
|
||||
list(FILTER DIRS EXCLUDE REGEX "^/[^.]+64/.*")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(APPEND DIRS ${NEW_DIRS})
|
||||
|
|
|
@ -865,8 +865,9 @@ void Compiler::Reset()
|
|||
|
||||
const u32 brk_0 = 0xD4200000;
|
||||
|
||||
for (int i = 0; i < (JitMemMainSize + JitMemSecondarySize) / 4; i++)
|
||||
*(((u32*)GetRWPtr()) + i) = brk_0;
|
||||
u8* const rw_ptr = GetWriteableRWPtr();
|
||||
for (u32 i = 0; i < (JitMemMainSize + JitMemSecondarySize); i += sizeof(u32))
|
||||
std::memcpy(rw_ptr + i, &brk_0, sizeof(u32));
|
||||
}
|
||||
|
||||
void Compiler::Comp_AddCycles_C(bool forceNonConstant)
|
||||
|
|
18
src/CP15.cpp
18
src/CP15.cpp
|
@ -186,10 +186,14 @@ void ARMv5::UpdatePURegion(u32 n)
|
|||
return;
|
||||
}
|
||||
|
||||
u32 start = rgn >> 12;
|
||||
u32 sz = 2 << ((rgn >> 1) & 0x1F);
|
||||
u32 end = start + (sz >> 12);
|
||||
// TODO: check alignment of start
|
||||
// notes:
|
||||
// * min size of a pu region is 4KiB (12 bits)
|
||||
// * size is calculated as size + 1, but the 12 lsb of address space are ignored, therefore we need it as size + 1 - 12, or size - 11
|
||||
// * pu regions are aligned based on their size
|
||||
u32 size = std::max((int)((rgn>>1) & 0x1F) - 11, 0); // obtain the size, subtract 11 and clamp to a min of 0.
|
||||
u32 start = ((rgn >> 12) >> size) << size; // determine the start offset, and use shifts to force alignment with a multiple of the size.
|
||||
u32 end = start + (1<<size); // add 1 left shifted by size to start to determine end point
|
||||
// dont need to bounds check the end point because the force alignment inherently prevents it from breaking
|
||||
|
||||
u8 usermask = 0;
|
||||
u8 privmask = 0;
|
||||
|
@ -239,7 +243,7 @@ void ARMv5::UpdatePURegion(u32 n)
|
|||
"PU region %d: %08X-%08X, user=%02X priv=%02X, %08X/%08X\n",
|
||||
n,
|
||||
start << 12,
|
||||
end << 12,
|
||||
(end << 12) - 1,
|
||||
usermask,
|
||||
privmask,
|
||||
PU_DataRW,
|
||||
|
@ -579,12 +583,12 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
|||
|
||||
std::snprintf(log_output,
|
||||
sizeof(log_output),
|
||||
"PU: region %d = %08X : %s, %08X-%08X\n",
|
||||
"PU: region %d = %08X : %s, start: %08X size: %02X\n",
|
||||
(id >> 4) & 0xF,
|
||||
val,
|
||||
val & 1 ? "enabled" : "disabled",
|
||||
val & 0xFFFFF000,
|
||||
(val & 0xFFFFF000) + (2 << ((val & 0x3E) >> 1))
|
||||
(val & 0x3E) >> 1
|
||||
);
|
||||
Log(LogLevel::Debug, "%s", log_output);
|
||||
// Some implementations of Log imply a newline, so we build up the line before printing it
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
460
src/Wifi.cpp
460
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<<irq);
|
||||
u32 newflags = IOPORT(W_IF) & IOPORT(W_IE);
|
||||
u16 newflags = IOPORT(W_IF) & IOPORT(W_IE);
|
||||
|
||||
if ((oldflags == 0) && (newflags != 0))
|
||||
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()
|
||||
{
|
||||
SetIRQ(13);
|
||||
|
||||
if (!(IOPORT(W_PowerTX) & 0x0002))
|
||||
if ((IOPORT(W_ModeWEP) & 0x7) != 3)
|
||||
{
|
||||
IOPORT(0x034) = 0x0002;
|
||||
//PowerDown();
|
||||
// FIXME!!
|
||||
IOPORT(W_RFPins) = 0x0046;
|
||||
IOPORT(W_RFStatus) = 9;
|
||||
if (!(IOPORT(W_PowerTX) & (1<<1)))
|
||||
{
|
||||
UpdatePowerStatus(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wifi::SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced
|
||||
{
|
||||
// CHECKME: is this also done for USCOMPARE IRQ?
|
||||
if (source != 2)
|
||||
IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval);
|
||||
|
||||
|
@ -409,10 +450,10 @@ void Wifi::SetIRQ15()
|
|||
{
|
||||
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;
|
||||
IOPORT(W_RFStatus) = 1;
|
||||
UpdatePowerStatus(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,16 +467,110 @@ void Wifi::SetStatus(u32 status)
|
|||
}
|
||||
|
||||
|
||||
void Wifi::PowerDown()
|
||||
void Wifi::UpdatePowerStatus(int power) // 1=on 0=no change -1=off
|
||||
{
|
||||
IOPORT(W_TXReqRead) &= ~0x000F;
|
||||
IOPORT(W_PowerState) |= 0x0200;
|
||||
// TRANSCEIVER POWER MANAGEMENT
|
||||
//
|
||||
// * 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
|
||||
|
||||
// if the RF hardware is powered down while still sending or receiving,
|
||||
// the current frame is completed before going idle
|
||||
if (!ComStatus)
|
||||
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))
|
||||
{
|
||||
SetStatus(9);
|
||||
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 (!ComStatus)
|
||||
{
|
||||
IOPORT(W_TRXPower) = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,6 +656,9 @@ void Wifi::TXSendFrame(const TXSlot* slot, int num)
|
|||
if (noseqno == 2)
|
||||
*(u16*)&TXBuffer[0xC] |= (1<<11);
|
||||
|
||||
if (CurChannel == 0) return;
|
||||
TXBuffer[9] = CurChannel;
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
|
@ -600,6 +738,9 @@ void Wifi::StartTX_Cmd()
|
|||
slot->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:
|
||||
|
|
14
src/Wifi.h
14
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();
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
|
||||
static const char* APName;
|
||||
static const u8 APMac[6];
|
||||
static const u8 APChannel;
|
||||
|
||||
void MSTimer();
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#define GDBSTUB_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -209,16 +209,22 @@ void Process()
|
|||
}
|
||||
|
||||
JoyInputMask = 0xFFF;
|
||||
for (int i = 0; i < 12; i++)
|
||||
if (JoystickButtonDown(Config::JoyMapping[i]))
|
||||
JoyInputMask &= ~(1<<i);
|
||||
if (Joystick)
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
if (JoystickButtonDown(Config::JoyMapping[i]))
|
||||
JoyInputMask &= ~(1 << i);
|
||||
}
|
||||
|
||||
InputMask = KeyInputMask & JoyInputMask;
|
||||
|
||||
JoyHotkeyMask = 0;
|
||||
for (int i = 0; i < HK_MAX; i++)
|
||||
if (JoystickButtonDown(Config::HKJoyMapping[i]))
|
||||
JoyHotkeyMask |= (1<<i);
|
||||
if (Joystick)
|
||||
{
|
||||
for (int i = 0; i < HK_MAX; i++)
|
||||
if (JoystickButtonDown(Config::HKJoyMapping[i]))
|
||||
JoyHotkeyMask |= (1 << i);
|
||||
}
|
||||
|
||||
HotkeyMask = KeyHotkeyMask | JoyHotkeyMask;
|
||||
HotkeyPress = HotkeyMask & ~LastHotkeyMask;
|
||||
|
|
|
@ -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<Firmware> LoadFirmware(int type) noexcept
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (Config::FirmwareOverrideSettings)
|
||||
{
|
||||
CustomizeFirmware(firmware);
|
||||
}
|
||||
CustomizeFirmware(firmware, Config::FirmwareOverrideSettings);
|
||||
|
||||
return firmware;
|
||||
}
|
||||
|
@ -951,8 +948,8 @@ u32 DecompressROM(const u8* inContent, const u32 inSize, unique_ptr<u8[]>& outCo
|
|||
|
||||
if (realSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
{
|
||||
outContent = make_unique<u8[]>(realSize);
|
||||
u64 decompressed = ZSTD_decompress(outContent.get(), realSize, inContent, inSize);
|
||||
auto newOutContent = make_unique<u8[]>(realSize);
|
||||
u64 decompressed = ZSTD_decompress(newOutContent.get(), realSize, inContent, inSize);
|
||||
|
||||
if (ZSTD_isError(decompressed))
|
||||
{
|
||||
|
@ -960,6 +957,7 @@ u32 DecompressROM(const u8* inContent, const u32 inSize, unique_ptr<u8[]>& outCo
|
|||
return 0;
|
||||
}
|
||||
|
||||
outContent = std::move(newOutContent);
|
||||
return realSize;
|
||||
}
|
||||
else
|
||||
|
@ -1014,7 +1012,6 @@ u32 DecompressROM(const u8* inContent, const u32 inSize, unique_ptr<u8[]>& outCo
|
|||
}
|
||||
} while (inBuf.pos < inBuf.size);
|
||||
|
||||
ZSTD_freeDStream(dStream);
|
||||
outContent = make_unique<u8[]>(outBuf.pos);
|
||||
memcpy(outContent.get(), outBuf.dst, outBuf.pos);
|
||||
|
||||
|
@ -1120,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<std::codecvt_utf8_utf16<char16_t>, 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<Firmware::Language>(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<std::codecvt_utf8_utf16<char16_t>, 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<Firmware::Language>(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<std::codecvt_utf8_utf16<char16_t>, 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<std::codecvt_utf8_utf16<char16_t>, 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;
|
||||
|
@ -1176,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();
|
||||
|
@ -1568,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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ std::optional<FATStorageArgs> GetDSiSDCardArgs() noexcept;
|
|||
std::optional<FATStorage> LoadDSiSDCard() noexcept;
|
||||
std::optional<FATStorageArgs> GetDLDISDCardArgs() noexcept;
|
||||
std::optional<FATStorage> 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<Firmware> LoadFirmware(int type) noexcept;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"dependencies": [
|
||||
"sdl2",
|
||||
"libarchive",
|
||||
{
|
||||
"name": "libarchive",
|
||||
"default-features": false,
|
||||
"features": ["bzip2", "crypto", "lz4", "zstd"]
|
||||
},
|
||||
"libslirp",
|
||||
"zstd",
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue