From 7340b1d6e3c9de607608a786b839001500a3348b Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Tue, 19 Nov 2019 21:37:47 +0000 Subject: [PATCH 01/71] Fix hanging UI when `null` addr --- src/libui_sdl/LAN_PCap.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index c228f5e4..55b08914 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -257,12 +257,11 @@ bool Init(bool open_adapter) struct ifaddrs* curaddr = addrs; while (curaddr) { - if (strcmp(curaddr->ifa_name, adata->DeviceName)) + if (strcmp(curaddr->ifa_name, adata->DeviceName) || !curaddr->ifa_addr) { curaddr = curaddr->ifa_next; continue; } - if (!curaddr->ifa_addr) continue; u16 af = curaddr->ifa_addr->sa_family; if (af == AF_INET) From 7e07250652260657b0a78d66c556d6edc1175b27 Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Tue, 19 Nov 2019 22:19:30 +0000 Subject: [PATCH 02/71] Maybe better to log --- src/libui_sdl/LAN_PCap.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index 55b08914..0682e61e 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -257,12 +257,18 @@ bool Init(bool open_adapter) struct ifaddrs* curaddr = addrs; while (curaddr) { - if (strcmp(curaddr->ifa_name, adata->DeviceName) || !curaddr->ifa_addr) + if (strcmp(curaddr->ifa_name, adata->DeviceName) { curaddr = curaddr->ifa_next; continue; } + if (!curaddr->ifa_addr){ + printf("Device does not have an address :/"); + curaddr = curaddr->ifa_next; + continue; + } + u16 af = curaddr->ifa_addr->sa_family; if (af == AF_INET) { From cdd60bb29822736bc7e0a0a3469e1aed33052e00 Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Tue, 19 Nov 2019 22:20:39 +0000 Subject: [PATCH 03/71] fix build --- src/libui_sdl/LAN_PCap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index 0682e61e..e4078664 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -257,7 +257,7 @@ bool Init(bool open_adapter) struct ifaddrs* curaddr = addrs; while (curaddr) { - if (strcmp(curaddr->ifa_name, adata->DeviceName) + if (strcmp(curaddr->ifa_name, adata->DeviceName)) { curaddr = curaddr->ifa_next; continue; From c2a55bc2174daea687f865089af4e7a3fdc192f3 Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Tue, 19 Nov 2019 22:22:47 +0000 Subject: [PATCH 04/71] clean log --- src/libui_sdl/LAN_PCap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index e4078664..dd5a7002 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -264,7 +264,7 @@ bool Init(bool open_adapter) } if (!curaddr->ifa_addr){ - printf("Device does not have an address :/"); + printf("Device does not have an address :/\n"); curaddr = curaddr->ifa_next; continue; } From 477be1d1551fdd4925c95404b5af025ed9f30081 Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Tue, 19 Nov 2019 22:34:02 +0000 Subject: [PATCH 05/71] add device name --- src/libui_sdl/LAN_PCap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index dd5a7002..75a2e3cc 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -264,7 +264,7 @@ bool Init(bool open_adapter) } if (!curaddr->ifa_addr){ - printf("Device does not have an address :/\n"); + printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); curaddr = curaddr->ifa_next; continue; } From 7730e6c1e2086db4c73ecebaa140ca45c1383a9f Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Wed, 20 Nov 2019 23:24:16 +0000 Subject: [PATCH 06/71] Coding style + weird spacing --- src/libui_sdl/LAN_PCap.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index 75a2e3cc..312af0ea 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -263,10 +263,11 @@ bool Init(bool open_adapter) continue; } - if (!curaddr->ifa_addr){ + if (!curaddr->ifa_addr) + { printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); curaddr = curaddr->ifa_next; - continue; + continue; } u16 af = curaddr->ifa_addr->sa_family; From 7af658f0897c6d6ad1f67b9d7a9bc60955c029a0 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Wed, 4 Dec 2019 22:46:33 +0100 Subject: [PATCH 07/71] Add a UNIX_PORTABLE build option, turning it off makes a build of melonDS suitable for systemwide installation. --- melonDS.desktop | 11 +++++++ src/NDSCart.cpp | 2 +- src/Platform.h | 8 ++++- src/libui_sdl/CMakeLists.txt | 8 +++++ src/libui_sdl/Platform.cpp | 64 ++++++++++++++++++++++++++++++++++++ src/libui_sdl/main.cpp | 32 ++++++++++++++---- 6 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 melonDS.desktop diff --git a/melonDS.desktop b/melonDS.desktop new file mode 100644 index 00000000..3dd921ce --- /dev/null +++ b/melonDS.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=melonDS +GenericName=Nintendo DS Emulator +Comment=A fast and accurate Nintendo DS emulator. +Exec=melonDS +Type=Application +Categories=Game;Emulator; +Terminal=false +Icon=melon_256x256 +MimeType=application/x-nintendo-ds-rom; +Keywords=emulator;Nintendo;DS;NDS;Nintendo DS; diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 0ecd304a..5654a7d3 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -815,7 +815,7 @@ bool ReadROMParams(u32 gamecode, u32* params) // [gamecode] [ROM size] [save type] [reserved] // list must be sorted by gamecode - FILE* f = Platform::OpenLocalFile("romlist.bin", "rb"); + FILE* f = Platform::OpenDataFile("romlist.bin"); if (!f) return false; fseek(f, 0, SEEK_END); diff --git a/src/Platform.h b/src/Platform.h index ca6971ee..dfe83d06 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -32,15 +32,21 @@ void StopEmu(); // can be optionally restricted to only opening a file that already exists. // * OpenLocalFile(): // opens files local to the emulator (melonDS.ini, BIOS, firmware, ...) -// checks, by order of priority: +// For Windows builds, or portable UNIX builds it checks, by order of priority: // * current working directory // * emulator directory (essentially where the melonDS executable is) if supported // * any platform-specific application data directories // in create mode, if the file doesn't exist, it will be created in the emulator // directory if supported, or in the current directory otherwise +// For regular UNIX builds, the user's configuration directory is always used. +// * OpenDataFile(): +// Opens a file that was installed alongside melonDS on UNIX systems in /usr/share, etc. +// Looks in the user's data directory first, then the system's. +// If on Windows or a portable UNIX build, this simply calls OpenLocalFile(). FILE* OpenFile(const char* path, const char* mode, bool mustexist=false); FILE* OpenLocalFile(const char* path, const char* mode); +FILE* OpenDataFile(const char* path); inline bool FileExists(const char* name) { diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 64206bf2..afd38e40 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -31,6 +31,11 @@ target_link_libraries(melonDS core ${SDL2_LIBRARIES} libui) if (UNIX) + option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" ON) + if (UNIX_PORTABLE) + add_definitions(-DUNIX_PORTABLE) + endif() + find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk+-3.0) pkg_check_modules(SDL2 REQUIRED sdl2) @@ -61,4 +66,7 @@ elseif (WIN32) target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi) endif () +install(FILES ../../melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) +install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps) +install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonds) install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp index 94b3791f..5cbf344c 100644 --- a/src/libui_sdl/Platform.cpp +++ b/src/libui_sdl/Platform.cpp @@ -135,6 +135,63 @@ FILE* OpenFile(const char* path, const char* mode, bool mustexist) return ret; } +#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) + +FILE* OpenLocalFile(const char* path, const char* mode) +{ + std::string fullpath; + if (path[0] == '/') + { + // If it's an absolute path, just open that. + fullpath = std::string(path); + } + else + { + // Check user configuration directory + std::string confpath = std::string(g_get_user_config_dir()) + "/melonds/"; + g_mkdir_with_parents(confpath.c_str(), 0755); + fullpath = confpath + path; + } + + return OpenFile(fullpath.c_str(), mode, mode[0] != 'w'); +} + +FILE* OpenDataFile(const char* path) +{ + const char* melondir = "melonds"; + const char* const* sys_dirs = g_get_system_data_dirs(); + const char* user_dir = g_get_user_data_dir(); + + // First check the user's data directory + char* fullpath = g_build_path("/", user_dir, melondir, path, NULL); + if (access(fullpath, R_OK) == 0) + { + FILE* f = fopen(fullpath, "r"); + g_free(fullpath); + return f; + } + free(fullpath); + + // Then check the system data directories + for (size_t i = 0; sys_dirs[i] != NULL; i++) + { + const char* dir = sys_dirs[i]; + char* fullpath = g_build_path("/", dir, melondir, path, NULL); + + if (access(fullpath, R_OK) == 0) + { + FILE* f = fopen(fullpath, "r"); + g_free(fullpath); + return f; + } + free(fullpath); + } + + return NULL; +} + +#else + FILE* OpenLocalFile(const char* path, const char* mode) { bool relpath = false; @@ -257,6 +314,13 @@ FILE* OpenLocalFile(const char* path, const char* mode) return NULL; } +FILE* OpenDataFile(const char* path) +{ + return OpenLocalFile(path, "r"); +} + +#endif + void* Thread_Create(void (*func)()) { diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index d6aa4600..40b70790 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -21,6 +21,10 @@ #include #include +#ifndef __WIN32__ +#include +#endif + #include #include "libui/ui.h" @@ -2589,6 +2593,7 @@ int main(int argc, char** argv) printf("melonDS " MELONDS_VERSION "\n"); printf(MELONDS_URL "\n"); +#if defined(__WIN32__) || defined(UNIX_PORTABLE) if (argc > 0 && strlen(argv[0]) > 0) { int len = strlen(argv[0]); @@ -2615,6 +2620,13 @@ int main(int argc, char** argv) EmuDirectory = new char[2]; strcpy(EmuDirectory, "."); } +#else + const char* confdir = g_get_user_config_dir(); + const char* confname = "/melonds"; + EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1]; + strcat(EmuDirectory, confdir); + strcat(EmuDirectory, confname); +#endif // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); @@ -2650,15 +2662,23 @@ int main(int argc, char** argv) !Platform::LocalFileExists("bios9.bin") || !Platform::LocalFileExists("firmware.bin")) { - uiMsgBoxError( - NULL, - "BIOS/Firmware not found", +#if defined(__WIN32__) || defined(UNIX_PORTABLE) + const char* locationName = "the directory you run melonDS from"; +#else + char* locationName = EmuDirectory; +#endif + char msgboxtext[512]; + sprintf(msgboxtext, "One or more of the following required files don't exist or couldn't be accessed:\n\n" "bios7.bin -- ARM7 BIOS\n" "bios9.bin -- ARM9 BIOS\n" "firmware.bin -- firmware image\n\n" - "Dump the files from your DS and place them in the directory you run melonDS from.\n" - "Make sure that the files can be accessed."); + "Dump the files from your DS and place them in %s.\n" + "Make sure that the files can be accessed.", + locationName + ); + + uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext); uiUninit(); SDL_Quit(); @@ -2704,7 +2724,7 @@ int main(int argc, char** argv) } } { - FILE* f = Platform::OpenLocalFile("romlist.bin", "rb"); + FILE* f = Platform::OpenDataFile("romlist.bin"); if (f) { u32 data; From 959c37ead74968ef3bf8b66f852307f6e9fb10e3 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Wed, 4 Dec 2019 22:54:30 +0100 Subject: [PATCH 08/71] Open with rb instead of r in OpenDataFile to avoid potential problems with Windows. --- src/libui_sdl/Platform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp index 5cbf344c..89429270 100644 --- a/src/libui_sdl/Platform.cpp +++ b/src/libui_sdl/Platform.cpp @@ -316,7 +316,7 @@ FILE* OpenLocalFile(const char* path, const char* mode) FILE* OpenDataFile(const char* path) { - return OpenLocalFile(path, "r"); + return OpenLocalFile(path, "rb"); } #endif From 4f87707cda26f9c6a7a70ad46232eefebc5a4d82 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Thu, 5 Dec 2019 00:11:52 +0100 Subject: [PATCH 09/71] If all else fails, look for data files (romlist.bin) in the current working direcoty. --- src/libui_sdl/Platform.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp index 89429270..8b83a014 100644 --- a/src/libui_sdl/Platform.cpp +++ b/src/libui_sdl/Platform.cpp @@ -186,6 +186,9 @@ FILE* OpenDataFile(const char* path) } free(fullpath); } + + FILE* f = fopen(path, "rb"); + if (f) return f; return NULL; } From 03f33fa5c3a47f17c3783ce045fc2f761ed11290 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Thu, 5 Dec 2019 00:12:40 +0100 Subject: [PATCH 10/71] Make UNIX builds non-portable by default. --- src/libui_sdl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index afd38e40..ae270e42 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -31,7 +31,7 @@ target_link_libraries(melonDS core ${SDL2_LIBRARIES} libui) if (UNIX) - option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" ON) + option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) if (UNIX_PORTABLE) add_definitions(-DUNIX_PORTABLE) endif() From 23bca8c17a3a630721e61079daf729ee1e5ed65f Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Thu, 5 Dec 2019 00:40:59 +0100 Subject: [PATCH 11/71] Tell the user where to place romlist.bin if it can't be found for UNIX non-portable builds. --- src/libui_sdl/main.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 40b70790..c7a44019 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -2724,6 +2724,17 @@ int main(int argc, char** argv) } } { + const char* romlist_missing = "Save memory type detection will not work correctly.\n\n" + "You should use the latest version of romlist.bin (provided in melonDS release packages)."; +#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) + std::string missingstr = std::string(romlist_missing) + + "\n\nThe ROM list should be placed in " + g_get_user_data_dir() + "/melonds/, otherwise " + "melonDS will search for it in the current working directory."; + const char* romlist_missing_text = missingstr.c_str(); +#else + const char* romlist_missing_text = romlist_missing; +#endif + FILE* f = Platform::OpenDataFile("romlist.bin"); if (f) { @@ -2733,18 +2744,12 @@ int main(int argc, char** argv) if ((data >> 24) == 0) // old CRC-based list { - uiMsgBoxError(NULL, - "Your version of romlist.bin is outdated.", - "Save memory type detection will not work correctly.\n\n" - "You should use the latest version of romlist.bin (provided in melonDS release packages)."); + uiMsgBoxError(NULL, "Your version of romlist.bin is outdated.", romlist_missing_text); } } else { - uiMsgBoxError(NULL, - "romlist.bin not found.", - "Save memory type detection will not work correctly.\n\n" - "You should use the latest version of romlist.bin (provided in melonDS release packages)."); + uiMsgBoxError(NULL, "romlist.bin not found.", romlist_missing_text); } } From f21347c918934441a90a2b18a928535e0dc854a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 12:32:59 -0500 Subject: [PATCH 12/71] Fix GBA memory values on deselected CPU Previously, the GBA memory was 0xFF-filled on both CPUs. However, GBATEK reports that the deselected CPU is 0x00-filled, and that some titles depend on this behavior to function properly. --- src/NDS.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index ceeeb793..0957ea35 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1610,16 +1610,16 @@ u8 ARM9Read8(u32 addr) case 0x08000000: case 0x09000000: - if (ExMemCnt[0] & (1<<7)) return 0xFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus case 0x0A000000: - if (ExMemCnt[0] & (1<<7)) return 0xFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus } printf("unknown arm9 read8 %08X\n", addr); @@ -1671,16 +1671,16 @@ u16 ARM9Read16(u32 addr) case 0x08000000: case 0x09000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus case 0x0A000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus } //printf("unknown arm9 read16 %08X %08X\n", addr, ARM9->R[15]); @@ -1732,16 +1732,16 @@ u32 ARM9Read32(u32 addr) case 0x08000000: case 0x09000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFFFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: - if (ExMemCnt[0] & (1<<7)) return 0xFFFFFFFF; // TODO: proper open bus + if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus } printf("unknown arm9 read32 %08X | %08X %08X\n", addr, ARM9->R[15], ARM9->R[12]); @@ -1935,16 +1935,16 @@ u8 ARM7Read8(u32 addr) case 0x08000000: case 0x09000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus case 0x0A000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled // TODO!!! - return 0xFF; + return 0xFF; // TODO: proper open bus } printf("unknown arm7 read8 %08X %08X %08X/%08X\n", addr, ARM7->R[15], ARM7->R[0], ARM7->R[1]); @@ -1998,16 +1998,16 @@ u16 ARM7Read16(u32 addr) case 0x08000000: case 0x09000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus case 0x0A000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFF; + return 0xFFFF; // TODO: proper open bus } printf("unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]); @@ -2061,16 +2061,16 @@ u32 ARM7Read32(u32 addr) case 0x08000000: case 0x09000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFFFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; //printf("GBA read8 %08X\n", addr); // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: - if (!(ExMemCnt[0] & (1<<7))) return 0xFFFFFFFF; // TODO: proper open bus + if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled // TODO!!! - return 0xFFFFFFFF; + return 0xFFFFFFFF; // TODO: proper open bus } printf("unknown arm7 read32 %08X | %08X\n", addr, ARM7->R[15]); From d86ee1d5bfb76d4efd89f4056beece374926500a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 13:46:51 -0500 Subject: [PATCH 13/71] Add GBA cart model and allow reading from it --- src/CMakeLists.txt | 1 + src/GBACart.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++++ src/GBACart.h | 52 ++++++++++++ src/NDS.cpp | 73 +++++++++++------ 4 files changed, 299 insertions(+), 24 deletions(-) create mode 100644 src/GBACart.cpp create mode 100644 src/GBACart.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1110f1f..03a4bfe0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(core STATIC CP15.cpp CRC32.cpp DMA.cpp + GBACart.cpp GPU.cpp GPU2D.cpp GPU3D.cpp diff --git a/src/GBACart.cpp b/src/GBACart.cpp new file mode 100644 index 00000000..7c2faad0 --- /dev/null +++ b/src/GBACart.cpp @@ -0,0 +1,197 @@ +/* + Copyright 2019 Arisotura, Raphaël Zumer + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "GBACart.h" +#include "CRC32.h" +#include "Platform.h" + + +namespace GBACart_SRAM +{ + +u8* SRAM; +u32 SRAMLength; + +char SRAMPath[1024]; + + +bool Init() +{ + SRAM = NULL; + return true; +} + +void DeInit() +{ + if (SRAM) delete[] SRAM; +} + +void Reset() +{ + if (SRAM) delete[] SRAM; + SRAM = NULL; +} + +void DoSavestate(Savestate* file) +{ + // TODO? +} + +void LoadSave(const char* path) +{ + if (SRAM) delete[] SRAM; + + strncpy(SRAMPath, path, 1023); + SRAMPath[1023] = '\0'; + + FILE* f = Platform::OpenFile(path, "rb"); + if (f) + { + fseek(f, 0, SEEK_END); + SRAMLength = (u32)ftell(f); + SRAM = new u8[SRAMLength]; + + fseek(f, 0, SEEK_SET); + fread(SRAM, SRAMLength, 1, f); + + fclose(f); + } + else + { + int SRAMLength = 65536; // max GBA SRAM size + + SRAM = new u8[SRAMLength]; + memset(SRAM, 0xFF, SRAMLength); + } +} + +void RelocateSave(const char* path, bool write) +{ + if (!write) + { + LoadSave(path); // lazy + return; + } + + strncpy(SRAMPath, path, 1023); + SRAMPath[1023] = '\0'; + + FILE* f = Platform::OpenFile(path, "wb"); + if (!f) + { + printf("GBACart_SRAM::RelocateSave: failed to create new file. fuck\n"); + return; + } + + fwrite(SRAM, SRAMLength, 1, f); + fclose(f); +} + +} + + +namespace GBACart +{ + +bool CartInserted; +u8* CartROM; +u32 CartROMSize; +u32 CartCRC; +u32 CartID; + + +bool Init() +{ + if (!GBACart_SRAM::Init()) return false; + + CartROM = NULL; + + return true; +} + +void DeInit() +{ + if (CartROM) delete[] CartROM; + + GBACart_SRAM::DeInit(); +} + +void Reset() +{ + CartInserted = false; + if (CartROM) delete[] CartROM; + CartROM = NULL; + CartROMSize = 0; + + GBACart_SRAM::Reset(); +} + +void DoSavestate(Savestate* file) +{ + // TODO? +} + +bool LoadROM(const char* path, const char* sram) +{ + FILE* f = Platform::OpenFile(path, "rb"); + if (!f) + { + return false; + } + + fseek(f, 0, SEEK_END); + u32 len = (u32)ftell(f); + + CartROMSize = 0x200; + while (CartROMSize < len) + CartROMSize <<= 1; + + u32 gamecode; + fseek(f, 0xAC, SEEK_SET); + fread(&gamecode, 4, 1, f); + printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24); + + CartROM = new u8[CartROMSize]; + memset(CartROM, 0, CartROMSize); + fseek(f, 0, SEEK_SET); + fread(CartROM, 1, len, f); + + fclose(f); + //CartROM = f; + + CartCRC = CRC32(CartROM, CartROMSize); + printf("ROM CRC32: %08X\n", CartCRC); + + CartInserted = true; + + // save + printf("Save file: %s\n", sram); + GBACart_SRAM::LoadSave(sram); + + return true; +} + +void RelocateSave(const char* path, bool write) +{ + // derp herp + GBACart_SRAM::RelocateSave(path, write); +} + +} diff --git a/src/GBACart.h b/src/GBACart.h new file mode 100644 index 00000000..94da0b27 --- /dev/null +++ b/src/GBACart.h @@ -0,0 +1,52 @@ +/* + Copyright 2019 Arisotura, Raphaël Zumer + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef GBACART_H +#define GBACART_H + +#include "types.h" +#include "Savestate.h" + + +namespace GBACart_SRAM +{ + +extern u8* SRAM; +extern u32 SRAMLength; + +} + + +namespace GBACart +{ + +extern bool CartInserted; +extern u8* CartROM; +extern u32 CartROMSize; + +bool Init(); +void DeInit(); +void Reset(); + +void DoSavestate(Savestate* file); +bool LoadROM(const char* path, const char* sram); +void RelocateSave(const char* path, bool write); + +} + +#endif // GBACART_H diff --git a/src/NDS.cpp b/src/NDS.cpp index 0957ea35..a16eb1c0 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -22,6 +22,7 @@ #include "NDS.h" #include "ARM.h" #include "NDSCart.h" +#include "GBACart.h" #include "DMA.h" #include "FIFO.h" #include "GPU.h" @@ -1611,14 +1612,18 @@ u8 ARM9Read8(u32 addr) case 0x08000000: case 0x09000000: if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFF; // TODO: proper open bus case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFF; // TODO: proper open bus } @@ -1672,14 +1677,18 @@ u16 ARM9Read16(u32 addr) case 0x08000000: case 0x09000000: if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFF; // TODO: proper open bus case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFF; // TODO: proper open bus } @@ -1733,14 +1742,18 @@ u32 ARM9Read32(u32 addr) case 0x08000000: case 0x09000000: if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus } @@ -1936,14 +1949,18 @@ u8 ARM7Read8(u32 addr) case 0x08000000: case 0x09000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFF; // TODO: proper open bus case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFF; // TODO: proper open bus } @@ -1999,14 +2016,18 @@ u16 ARM7Read16(u32 addr) case 0x08000000: case 0x09000000: if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFF; // TODO: proper open bus case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFF; // TODO: proper open bus } @@ -2062,14 +2083,18 @@ u32 ARM7Read32(u32 addr) case 0x08000000: case 0x09000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled - //return *(u8*)&NDSCart::CartROM[addr & (NDSCart::CartROMSize-1)]; - //printf("GBA read8 %08X\n", addr); - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart::CartROM[addr & (GBACart::CartROMSize-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled - // TODO!!! + if (GBACart::CartInserted) + { + return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + } return 0xFFFFFFFF; // TODO: proper open bus } From 968768042eae94f6965ecda5beedba8b8cf172e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 15:30:56 -0500 Subject: [PATCH 14/71] Properly init/deinit the GBA slot --- src/NDS.cpp | 17 +++++++++++++++++ src/NDS.h | 1 + 2 files changed, 18 insertions(+) diff --git a/src/NDS.cpp b/src/NDS.cpp index a16eb1c0..da36bdc6 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -170,6 +170,7 @@ bool Init() IPCFIFO7 = new FIFO(16); if (!NDSCart::Init()) return false; + if (!GBACart::Init()) return false; if (!GPU::Init()) return false; if (!SPU::Init()) return false; if (!SPI::Init()) return false; @@ -191,6 +192,7 @@ void DeInit() delete IPCFIFO7; NDSCart::DeInit(); + GBACart::DeInit(); GPU::DeInit(); SPU::DeInit(); SPI::DeInit(); @@ -492,6 +494,7 @@ void Reset() RCnt = 0; NDSCart::Reset(); + GBACart::Reset(); GPU::Reset(); SPU::Reset(); SPI::Reset(); @@ -693,6 +696,7 @@ bool DoSavestate(Savestate* file) ARM7->DoSavestate(file); NDSCart::DoSavestate(file); + GBACart::DoSavestate(file); GPU::DoSavestate(file); SPU::DoSavestate(file); SPI::DoSavestate(file); @@ -721,6 +725,19 @@ bool LoadROM(const char* path, const char* sram, bool direct) } } +bool LoadGBAROM(const char* path, const char* sram) +{ + if (GBACart::LoadROM(path, sram)) + { + return true; + } + else + { + printf("Failed to load ROM %s\n", path); + return false; + } +} + void LoadBIOS() { Reset(); diff --git a/src/NDS.h b/src/NDS.h index 32433374..16c42efd 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -135,6 +135,7 @@ void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq); bool LoadROM(const char* path, const char* sram, bool direct); +bool LoadGBAROM(const char* path, const char* sram); void LoadBIOS(); void SetupDirectBoot(); void RelocateSave(const char* path, bool write); From 1da9b3806c67282f7fc2c48b5b0b4614e553c34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 15:31:18 -0500 Subject: [PATCH 15/71] Hook up the GBA slot to the UI A GBA cartridge may be loaded in the same way as a DS cartridge. If the extension of the selected file is "gba", it will be treated as a GBA file. The system boot logic is still centered around the DS cartridge, so loading a GBA file will not start or reset it. --- src/libui_sdl/main.cpp | 145 +++++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 49 deletions(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index d6aa4600..68bc6b89 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -105,9 +105,9 @@ int EmuRunning; volatile int EmuStatus; bool RunningSomething; -char ROMPath[1024]; -char SRAMPath[1024]; -char PrevSRAMPath[1024]; // for savestate 'undo load' +char ROMPath[2][1024]; +char SRAMPath[2][1024]; +char PrevSRAMPath[2][1024]; // for savestate 'undo load' bool SavestateLoaded; @@ -184,7 +184,7 @@ void SetupScreenRects(int width, int height); void TogglePause(void* blarg); void Reset(void* blarg); -void SetupSRAMPath(); +void SetupSRAMPath(int slot); void SaveState(int slot); void LoadState(int slot); @@ -1648,12 +1648,18 @@ void Reset(void* blarg) SavestateLoaded = false; uiMenuItemDisable(MenuItem_UndoStateLoad); - if (ROMPath[0] == '\0') + if (ROMPath[0][0] == '\0') NDS::LoadBIOS(); else { - SetupSRAMPath(); - NDS::LoadROM(ROMPath, SRAMPath, Config::DirectBoot); + SetupSRAMPath(0); + NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot); + } + + if (ROMPath[1][0] != '\0') + { + SetupSRAMPath(1); + NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); } Run(); @@ -1688,41 +1694,53 @@ void Stop(bool internal) OSD::AddMessage(0xFFC040, "Shutdown"); } -void SetupSRAMPath() +void SetupSRAMPath(int slot) { - strncpy(SRAMPath, ROMPath, 1023); - SRAMPath[1023] = '\0'; - strncpy(SRAMPath + strlen(ROMPath) - 3, "sav", 3); + strncpy(SRAMPath[slot], ROMPath[slot], 1023); + SRAMPath[slot][1023] = '\0'; + strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); } -void TryLoadROM(char* file, int prevstatus) +void TryLoadROM(char* file, int slot, int prevstatus) { char oldpath[1024]; char oldsram[1024]; - strncpy(oldpath, ROMPath, 1024); - strncpy(oldsram, SRAMPath, 1024); + strncpy(oldpath, ROMPath[slot], 1024); + strncpy(oldsram, SRAMPath[slot], 1024); - strncpy(ROMPath, file, 1023); - ROMPath[1023] = '\0'; + strncpy(ROMPath[slot], file, 1023); + ROMPath[slot][1023] = '\0'; - SetupSRAMPath(); + SetupSRAMPath(0); + SetupSRAMPath(1); - if (NDS::LoadROM(ROMPath, SRAMPath, Config::DirectBoot)) + if (slot == 0 && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot)) { SavestateLoaded = false; uiMenuItemDisable(MenuItem_UndoStateLoad); - strncpy(PrevSRAMPath, SRAMPath, 1024); // safety + // Reload the inserted GBA cartridge (if any) + if (ROMPath[1][0] != '\0') NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); + + strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety Run(); } + else if (slot == 1 && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) + { + SavestateLoaded = false; + uiMenuItemDisable(MenuItem_UndoStateLoad); + + strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety + if (RunningSomething) Run(); // do not start just from a GBA cart + } else { uiMsgBoxError(MainWindow, "Failed to load the ROM", "Make sure the file can be accessed and isn't opened in another application."); - strncpy(ROMPath, oldpath, 1024); - strncpy(SRAMPath, oldsram, 1024); + strncpy(ROMPath[slot], oldpath, 1024); + strncpy(SRAMPath[slot], oldsram, 1024); EmuRunning = prevstatus; } } @@ -1735,22 +1753,22 @@ void GetSavestateName(int slot, char* filename, int len) { int pos; - if (ROMPath[0] == '\0') // running firmware, no ROM + if (ROMPath[0][0] == '\0') // running firmware, no ROM { strcpy(filename, "firmware"); pos = 8; } else { - int l = strlen(ROMPath); + int l = strlen(ROMPath[0]); pos = l; - while (ROMPath[pos] != '.' && pos > 0) pos--; + while (ROMPath[0][pos] != '.' && pos > 0) pos--; if (pos == 0) pos = l; // avoid buffer overflow. shoddy if (pos > len-5) pos = len-5; - strncpy(&filename[0], ROMPath, pos); + strncpy(&filename[0], ROMPath[0], pos); } strcpy(&filename[pos], ".ml"); filename[pos+3] = '0'+slot; @@ -1818,16 +1836,16 @@ void LoadState(int slot) if (!failed) { - if (Config::SavestateRelocSRAM && ROMPath[0]!='\0') + if (Config::SavestateRelocSRAM && ROMPath[0][0]!='\0') { - strncpy(PrevSRAMPath, SRAMPath, 1024); + strncpy(PrevSRAMPath[0], SRAMPath[0], 1024); - strncpy(SRAMPath, filename, 1019); - int len = strlen(SRAMPath); - strcpy(&SRAMPath[len], ".sav"); - SRAMPath[len+4] = '\0'; + strncpy(SRAMPath[0], filename, 1019); + int len = strlen(SRAMPath[0]); + strcpy(&SRAMPath[0][len], ".sav"); + SRAMPath[0][len+4] = '\0'; - NDS::RelocateSave(SRAMPath, false); + NDS::RelocateSave(SRAMPath[0], false); } char msg[64]; @@ -1883,14 +1901,14 @@ void SaveState(int slot) if (slot > 0) uiMenuItemEnable(MenuItem_LoadStateSlot[slot-1]); - if (Config::SavestateRelocSRAM && ROMPath[0]!='\0') + if (Config::SavestateRelocSRAM && ROMPath[0][0]!='\0') { - strncpy(SRAMPath, filename, 1019); - int len = strlen(SRAMPath); - strcpy(&SRAMPath[len], ".sav"); - SRAMPath[len+4] = '\0'; + strncpy(SRAMPath[0], filename, 1019); + int len = strlen(SRAMPath[0]); + strcpy(&SRAMPath[0][len], ".sav"); + SRAMPath[0][len+4] = '\0'; - NDS::RelocateSave(SRAMPath, true); + NDS::RelocateSave(SRAMPath[0], true); } } @@ -1917,10 +1935,10 @@ void UndoStateLoad() NDS::DoSavestate(backup); delete backup; - if (ROMPath[0]!='\0') + if (ROMPath[0][0]!='\0') { - strncpy(SRAMPath, PrevSRAMPath, 1024); - NDS::RelocateSave(SRAMPath, false); + strncpy(SRAMPath[0], PrevSRAMPath[0], 1024); + NDS::RelocateSave(SRAMPath[0], false); } OSD::AddMessage(0, "State load undone"); @@ -1964,7 +1982,11 @@ void OnDropFile(uiWindow* window, char* file, void* blarg) while (EmuStatus != 2); } - TryLoadROM(file, prevstatus); + TryLoadROM(file, 0, prevstatus); + } + else if (!strcasecmp(ext, "gba")) + { + TryLoadROM(file, 1, prevstatus); } } @@ -1995,7 +2017,7 @@ void OnOpenFile(uiMenuItem* item, uiWindow* window, void* blarg) EmuRunning = 2; while (EmuStatus != 2); - char* file = uiOpenFile(window, "DS ROM (*.nds)|*.nds;*.srl|Any file|*.*", Config::LastROMFolder); + char* file = uiOpenFile(window, "DS ROM (*.nds)|*.nds;*.srl|GBA ROM (*.gba)|*.gba|Any file|*.*", Config::LastROMFolder); if (!file) { EmuRunning = prevstatus; @@ -2006,8 +2028,17 @@ void OnOpenFile(uiMenuItem* item, uiWindow* window, void* blarg) while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--; strncpy(Config::LastROMFolder, file, pos); Config::LastROMFolder[pos] = '\0'; + char* ext = &file[strlen(file)-3]; + + if (!strcasecmp(ext, "gba")) + { + TryLoadROM(file, 1, prevstatus); + } + else + { + TryLoadROM(file, 0, prevstatus); + } - TryLoadROM(file, prevstatus); uiFreeText(file); } @@ -2032,7 +2063,7 @@ void OnRun(uiMenuItem* item, uiWindow* window, void* blarg) { if (!RunningSomething) { - ROMPath[0] = '\0'; + ROMPath[0][0] = '\0'; NDS::LoadBIOS(); } @@ -2852,14 +2883,30 @@ int main(int argc, char** argv) if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl")) { - strncpy(ROMPath, file, 1023); - ROMPath[1023] = '\0'; + strncpy(ROMPath[0], file, 1023); + ROMPath[0][1023] = '\0'; - SetupSRAMPath(); + SetupSRAMPath(0); - if (NDS::LoadROM(ROMPath, SRAMPath, Config::DirectBoot)) + if (NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot)) Run(); } + + if (argc > 2) + { + file = argv[2]; + ext = &file[strlen(file)-3]; + + if (!strcasecmp(ext, "gba")) + { + strncpy(ROMPath[1], file, 1023); + ROMPath[1][1023] = '\0'; + + SetupSRAMPath(1); + + NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); + } + } } uiMain(); From 91bf62a1d45fd8e81c6c77cb7072898f184c3a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 15:55:06 -0500 Subject: [PATCH 16/71] Keep GBA carts loaded when booting to firmware --- src/libui_sdl/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 68bc6b89..1e6069e2 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -2065,6 +2065,12 @@ void OnRun(uiMenuItem* item, uiWindow* window, void* blarg) { ROMPath[0][0] = '\0'; NDS::LoadBIOS(); + + if (ROMPath[1][0] != '\0') + { + SetupSRAMPath(1); + NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); + } } Run(); From 48a8a25548a9aa0ed73e4d0cb2d30471326481af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 17:13:56 -0500 Subject: [PATCH 17/71] Reset GBA cartridge state when loading a new ROM --- src/GBACart.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 7c2faad0..8ce76ab0 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -156,6 +156,11 @@ bool LoadROM(const char* path, const char* sram) return false; } + if (CartInserted) + { + Reset(); + } + fseek(f, 0, SEEK_END); u32 len = (u32)ftell(f); From 62b9f51e2329507d5e47b4239259067b5fb66240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 8 Dec 2019 17:56:22 -0500 Subject: [PATCH 18/71] Handle GBA cartridge SRAM writes --- src/GBACart.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ src/GBACart.h | 4 ++++ src/NDS.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 8ce76ab0..10f51066 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -104,6 +104,60 @@ void RelocateSave(const char* path, bool write) fclose(f); } +void Write8(u32 addr, u8 val) +{ + u8 prev = *(u8*)&SRAM[addr]; + + if (prev != val) + { + *(u8*)&SRAM[addr] = val;/* + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 1, 1, f); + fclose(f); + }*/ + } +} + +void Write16(u32 addr, u16 val) +{ + u16 prev = *(u16*)&SRAM[addr]; + + if (prev != val) + { + *(u16*)&SRAM[addr] = val;/* + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 2, 1, f); + fclose(f); + }*/ + } +} + +void Write32(u32 addr, u32 val) +{ + u32 prev = *(u32*)&SRAM[addr]; + + if (prev != val) + { + *(u32*)&SRAM[addr] = val;/* + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 3, 1, f); + fclose(f); + }*/ + } +} + } diff --git a/src/GBACart.h b/src/GBACart.h index 94da0b27..e86ea43d 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -29,6 +29,10 @@ namespace GBACart_SRAM extern u8* SRAM; extern u32 SRAMLength; +void Write8(u32 addr, u8 val); +void Write16(u32 addr, u16 val); +void Write32(u32 addr, u32 val); + } diff --git a/src/NDS.cpp b/src/NDS.cpp index da36bdc6..fe66814f 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1802,6 +1802,14 @@ void ARM9Write8(u32 addr, u8 val) case 0x07000000: // checkme return; + + case 0x0A000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write8(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } printf("unknown arm9 write8 %08X %02X\n", addr, val); @@ -1845,6 +1853,14 @@ void ARM9Write16(u32 addr, u16 val) if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u16*)&GPU::OAM[addr & 0x7FF] = val; return; + + case 0x0A000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write16(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } //printf("unknown arm9 write16 %08X %04X\n", addr, val); @@ -1888,6 +1904,14 @@ void ARM9Write32(u32 addr, u32 val) if (!(PowerControl9 & ((addr & 0x400) ? (1<<9) : (1<<1)))) return; *(u32*)&GPU::OAM[addr & 0x7FF] = val; return; + + case 0x0A000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write32(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]); @@ -2152,6 +2176,14 @@ void ARM7Write8(u32 addr, u8 val) case 0x06800000: GPU::WriteVRAM_ARM7(addr, val); return; + + case 0x0A000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write8(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } printf("unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]); @@ -2198,6 +2230,14 @@ void ARM7Write16(u32 addr, u16 val) case 0x06800000: GPU::WriteVRAM_ARM7(addr, val); return; + + case 0x0A000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write16(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } //printf("unknown arm7 write16 %08X %04X @ %08X\n", addr, val, ARM7->R[15]); @@ -2245,6 +2285,14 @@ void ARM7Write32(u32 addr, u32 val) case 0x06800000: GPU::WriteVRAM_ARM7(addr, val); return; + + case 0x0A000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + GBACart_SRAM::Write32(addr & (GBACart_SRAM::SRAMLength-1), val); + } + return; } //printf("unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]); From 86b746dd1c61b3577c6cf6eed56f09bfbdefab6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Mon, 9 Dec 2019 04:51:59 -0500 Subject: [PATCH 19/71] Remove unused Write function in NDSCart --- src/NDSCart.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 0ecd304a..4d240000 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -48,7 +48,6 @@ void Write_Null(u8 val, bool islast); void Write_EEPROMTiny(u8 val, bool islast); void Write_EEPROM(u8 val, bool islast); void Write_Flash(u8 val, bool islast); -void Write_Discover(u8 val, bool islast); bool Init() From 5ad85f15c1858108665329fada39d67edc408b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Mon, 9 Dec 2019 04:53:45 -0500 Subject: [PATCH 20/71] Add a framework to support non-SRAM GBA saves The support is not yet there, but at least we should not read or write bogus data. --- src/GBACart.cpp | 193 ++++++++++++++++++++++++++++++++++++++++-------- src/GBACart.h | 4 + src/NDS.cpp | 12 +-- 3 files changed, 171 insertions(+), 38 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 10f51066..937958cf 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -26,11 +26,40 @@ namespace GBACart_SRAM { + +enum SaveType { + S_NULL, + S_EEPROM4K, + S_EEPROM64K, + S_SRAM256K, + S_FLASH512K, + S_FLASH1M +}; + +struct FlashProperties +{ + u8 state; + u8 cmd; + u8 device; + u8 manufacturer; + u8 bank; +}; + u8* SRAM; u32 SRAMLength; +SaveType SRAMType; +FlashProperties SRAMFlash; char SRAMPath[1024]; +void (*WriteFunc)(u32 addr, u8 val); + + +void Write_Null(u32 addr, u8 val); +void Write_EEPROM(u32 addr, u8 val); +void Write_SRAM(u32 addr, u8 val); +void Write_Flash(u32 addr, u8 val); + bool Init() { @@ -47,6 +76,9 @@ void Reset() { if (SRAM) delete[] SRAM; SRAM = NULL; + SRAMLength = 0; + SRAMType = S_NULL; + SRAMFlash = {}; } void DoSavestate(Savestate* file) @@ -60,6 +92,7 @@ void LoadSave(const char* path) strncpy(SRAMPath, path, 1023); SRAMPath[1023] = '\0'; + SRAMLength = 0; FILE* f = Platform::OpenFile(path, "rb"); if (f) @@ -73,12 +106,48 @@ void LoadSave(const char* path) fclose(f); } - else - { - int SRAMLength = 65536; // max GBA SRAM size - SRAM = new u8[SRAMLength]; - memset(SRAM, 0xFF, SRAMLength); + switch (SRAMLength) + { + case 512: + SRAMType = S_EEPROM4K; + WriteFunc = Write_EEPROM; + break; + case 8192: + SRAMType = S_EEPROM64K; + WriteFunc = Write_EEPROM; + break; + case 32768: + SRAMType = S_SRAM256K; + WriteFunc = Write_SRAM; + break; + case 65536: + SRAMType = S_FLASH512K; + WriteFunc = Write_Flash; + break; + case 128*1024: + SRAMType = S_FLASH1M; + WriteFunc = Write_Flash; + break; + default: + printf("!! BAD SAVE LENGTH %d\n", SRAMLength); + case 0: + SRAMType = S_NULL; + WriteFunc = Write_Null; + break; + } + + if (SRAMType == S_FLASH512K) + { + // Panasonic 64K chip + SRAMFlash.device = 0x1B; + SRAMFlash.manufacturer = 0x32; + } + else if (SRAMType == S_FLASH1M) + { + // Macronix 128K chip + SRAMFlash.device = 0x09; + SRAMFlash.manufacturer = 0xC2; } } @@ -104,21 +173,93 @@ void RelocateSave(const char* path, bool write) fclose(f); } +u8 Read_Flash(u32 addr) +{ + // TODO: pokemen + return 0xFF; +} + +void Write_Null(u32 addr, u8 val) {} + +void Write_EEPROM(u32 addr, u8 val) +{ + // TODO: could be used in homebrew? +} + +void Write_Flash(u32 addr, u8 val) +{ + // TODO: pokemen +} + +void Write_SRAM(u32 addr, u8 val) +{ + *(u8*)&SRAM[addr] = val; + + // bit wasteful to do this for every written byte + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 1, 1, f); + fclose(f); + } +} + +u8 Read8(u32 addr) +{ + if (SRAMType == S_NULL) + { + return 0xFF; + } + + if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) + { + return Read_Flash(addr); + } + + return *(u8*)&SRAM[addr]; +} + +u16 Read16(u32 addr) +{ + if (SRAMType == S_NULL) + { + return 0xFFFF; + } + + if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) + { + return Read_Flash(addr) & (Read_Flash(addr + 1) << 8); + } + + return *(u16*)&SRAM[addr]; +} + +u32 Read32(u32 addr) +{ + if (SRAMType == S_NULL) + { + return 0xFFFFFFFF; + } + + if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) + { + return Read_Flash(addr) & + (Read_Flash(addr + 1) << 8) & + (Read_Flash(addr + 2) << 16) & + (Read_Flash(addr + 3) << 24); + } + + return *(u32*)&SRAM[addr]; +} + void Write8(u32 addr, u8 val) { u8 prev = *(u8*)&SRAM[addr]; if (prev != val) { - *(u8*)&SRAM[addr] = val;/* - - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) - { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 1, 1, f); - fclose(f); - }*/ + WriteFunc(addr, val); } } @@ -128,15 +269,8 @@ void Write16(u32 addr, u16 val) if (prev != val) { - *(u16*)&SRAM[addr] = val;/* - - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) - { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 2, 1, f); - fclose(f); - }*/ + WriteFunc(addr, val & 0xFF); + WriteFunc(addr + 1, val >> 8 & 0xFF); } } @@ -146,15 +280,10 @@ void Write32(u32 addr, u32 val) if (prev != val) { - *(u32*)&SRAM[addr] = val;/* - - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) - { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 3, 1, f); - fclose(f); - }*/ + WriteFunc(addr, val & 0xFF); + WriteFunc(addr + 1, val >> 8 & 0xFF); + WriteFunc(addr + 2, val >> 16 & 0xFF); + WriteFunc(addr + 3, val >> 24 & 0xFF); } } diff --git a/src/GBACart.h b/src/GBACart.h index e86ea43d..81fb2227 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -29,6 +29,10 @@ namespace GBACart_SRAM extern u8* SRAM; extern u32 SRAMLength; +u8 Read8(u32 addr); +u16 Read16(u32 addr); +u32 Read32(u32 addr); + void Write8(u32 addr, u8 val); void Write16(u32 addr, u16 val); void Write32(u32 addr, u32 val); diff --git a/src/NDS.cpp b/src/NDS.cpp index fe66814f..a906fbb0 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1639,7 +1639,7 @@ u8 ARM9Read8(u32 addr) if (ExMemCnt[0] & (1<<7)) return 0x00; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read8(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFF; // TODO: proper open bus } @@ -1704,7 +1704,7 @@ u16 ARM9Read16(u32 addr) if (ExMemCnt[0] & (1<<7)) return 0x0000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read16(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFF; // TODO: proper open bus } @@ -1769,7 +1769,7 @@ u32 ARM9Read32(u32 addr) if (ExMemCnt[0] & (1<<7)) return 0x00000000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read32(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFFFFFF; // TODO: proper open bus } @@ -2000,7 +2000,7 @@ u8 ARM7Read8(u32 addr) if (!(ExMemCnt[0] & (1<<7))) return 0x00; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u8*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read8(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFF; // TODO: proper open bus } @@ -2067,7 +2067,7 @@ u16 ARM7Read16(u32 addr) if (!(ExMemCnt[0] & (1<<7))) return 0x0000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u16*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read16(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFF; // TODO: proper open bus } @@ -2134,7 +2134,7 @@ u32 ARM7Read32(u32 addr) if (!(ExMemCnt[0] & (1<<7))) return 0x00000000; // deselected CPU is 00h-filled if (GBACart::CartInserted) { - return *(u32*)&GBACart_SRAM::SRAM[addr & (GBACart_SRAM::SRAMLength-1)]; + return GBACart_SRAM::Read32(addr & (GBACart_SRAM::SRAMLength-1)); } return 0xFFFFFFFF; // TODO: proper open bus } From 4e8b0c8ce451bc11de8b11b4da14a24242c8c34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Mon, 9 Dec 2019 06:09:30 -0500 Subject: [PATCH 21/71] Eject GBA cartridges on stop from the UI --- src/GBACart.cpp | 31 +++++++++++++++++++++++++++---- src/libui_sdl/main.cpp | 3 +++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 937958cf..a0483b1a 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -145,9 +145,9 @@ void LoadSave(const char* path) } else if (SRAMType == S_FLASH1M) { - // Macronix 128K chip - SRAMFlash.device = 0x09; - SRAMFlash.manufacturer = 0xC2; + // Sanyo 128K chip + SRAMFlash.device = 0x13; + SRAMFlash.manufacturer = 0x62; } } @@ -175,7 +175,30 @@ void RelocateSave(const char* path, bool write) u8 Read_Flash(u32 addr) { - // TODO: pokemen + if (SRAMFlash.cmd == 0) // no cmd + { + return *(u8*)&SRAM[addr + 0x10000 * SRAMFlash.bank]; + } + + // TODO properly keep track of command sequences, + // and deny unauthorized writes + switch (SRAMFlash.cmd) + { + case 0x90: // chip ID + if (addr == 0x0A000000) return SRAMFlash.manufacturer; + if (addr == 0x0A000001) return SRAMFlash.device; + break; + case 0xF0: // terminate command (TODO: break if non-Macronix chip and not at the end of an ID call?) + SRAMFlash.state = 0; + SRAMFlash.cmd = 0; + break; + case 0xB0: // bank switching (128K only) + break; // we don't track the request for now + default: + printf("GBACart_SRAM::Read_Flash: unknown command 0x%02X @ 0x%08X\n", SRAMFlash.cmd, addr); + break; + } + return 0xFF; } diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 1e6069e2..31b04889 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1674,6 +1674,9 @@ void Stop(bool internal) while (EmuStatus != 2); RunningSomething = false; + // eject any inserted GBA cartridge + ROMPath[1][0] = '\0'; + uiWindowSetTitle(MainWindow, "melonDS " MELONDS_VERSION); for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); From 5a7600dc79454869c6d6dfe56bf74afea2162d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Mon, 9 Dec 2019 06:09:52 -0500 Subject: [PATCH 22/71] =?UTF-8?q?Fix=20"=C3=A9"=20character=20encoding=20i?= =?UTF-8?q?n=20NDS.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/NDSCart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 4d240000..014ae5ae 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -398,7 +398,7 @@ void Write(u8 val, u32 hold) switch (CurCmd) { case 0x00: - // Pokémon carts have an IR transceiver thing, and send this + // Pokémon carts have an IR transceiver thing, and send this // to bypass it and access SRAM. // TODO: design better CurCmd = val; From 8fc9a33a9f22ecfb8974e57e009deb2670886946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Mon, 9 Dec 2019 06:10:26 -0500 Subject: [PATCH 23/71] Implement GBA cartridge Flash reading and writing --- src/GBACart.cpp | 141 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 7 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index a0483b1a..473d9942 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -180,22 +180,20 @@ u8 Read_Flash(u32 addr) return *(u8*)&SRAM[addr + 0x10000 * SRAMFlash.bank]; } - // TODO properly keep track of command sequences, - // and deny unauthorized writes switch (SRAMFlash.cmd) { case 0x90: // chip ID - if (addr == 0x0A000000) return SRAMFlash.manufacturer; - if (addr == 0x0A000001) return SRAMFlash.device; + if (addr == 0x0000) return SRAMFlash.manufacturer; + if (addr == 0x0001) return SRAMFlash.device; break; case 0xF0: // terminate command (TODO: break if non-Macronix chip and not at the end of an ID call?) SRAMFlash.state = 0; SRAMFlash.cmd = 0; break; case 0xB0: // bank switching (128K only) - break; // we don't track the request for now + break; // ignore here, handled during writes default: - printf("GBACart_SRAM::Read_Flash: unknown command 0x%02X @ 0x%08X\n", SRAMFlash.cmd, addr); + printf("GBACart_SRAM::Read_Flash: unknown command 0x%02X @ 0x%04X\n", SRAMFlash.cmd, addr); break; } @@ -211,7 +209,136 @@ void Write_EEPROM(u32 addr, u8 val) void Write_Flash(u32 addr, u8 val) { - // TODO: pokemen + switch (SRAMFlash.state) + { + case 0x00: + if (addr == 0x5555) + { + if (val == 0xF0) + { + // reset + SRAMFlash.state = 0; + SRAMFlash.cmd = 0; + return; + } + else if (val == 0xAA) + { + SRAMFlash.state = 1; + return; + } + } + if (addr == 0x0000) + { + if (SRAMFlash.cmd == 0xB0) + { + // bank switching + SRAMFlash.bank = val; + SRAMFlash.cmd = 0; + return; + } + } + break; + case 0x01: + if (addr == 0x2AAA && val == 0x55) + { + SRAMFlash.state = 2; + return; + } + SRAMFlash.state = 0; + break; + case 0x02: + if (addr == 0x5555) + { + // send command + switch (val) + { + case 0x80: // erase + SRAMFlash.state = 0x80; + break; + case 0x90: // chip ID + SRAMFlash.state = 0x90; + break; + case 0xA0: // write + SRAMFlash.state = 0; + break; + default: + SRAMFlash.state = 0; + break; + } + + SRAMFlash.cmd = val; + return; + } + break; + // erase + case 0x80: + if (addr == 0x5555 && val == 0xAA) + { + SRAMFlash.state = 0x81; + return; + } + SRAMFlash.state = 0; + break; + case 0x81: + if (addr == 0x2AAA && val == 0x55) + { + SRAMFlash.state = 0x82; + return; + } + SRAMFlash.state = 0; + break; + case 0x82: + if (val == 0x30) + { + u32 start_addr = addr + 0x10000 * SRAMFlash.bank; + memset((u8*)&SRAM[start_addr], 0xFF, 0x1000); + + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); + if (f) + { + fseek(f, start_addr, SEEK_SET); + fwrite((u8*)&SRAM[start_addr], 1, 0x1000, f); + fclose(f); + } + } + SRAMFlash.state = 0; + SRAMFlash.cmd = 0; + return; + // chip ID + case 0x90: + if (addr == 0x5555 && val == 0xAA) + { + SRAMFlash.state = 0x91; + return; + } + SRAMFlash.state = 0; + break; + case 0x91: + if (addr == 0x2AAA && val == 0x55) + { + SRAMFlash.state = 0x92; + return; + } + SRAMFlash.state = 0; + break; + case 0x92: + SRAMFlash.state = 0; + SRAMFlash.cmd = 0; + return; + default: + break; + } + + if (SRAMFlash.cmd == 0xA0) // write + { + Write_SRAM(addr + 0x10000 * SRAMFlash.bank, val); + SRAMFlash.state = 0; + SRAMFlash.cmd = 0; + return; + } + + printf("GBACart_SRAM::Write_Flash: unknown write 0x%02X @ 0x%04X (state: 0x%02X)\n", + val, addr, SRAMFlash.state); } void Write_SRAM(u32 addr, u8 val) From 68d3474458b0f3623d69efb54cdbe101e5adadcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Mon, 9 Dec 2019 07:06:39 -0500 Subject: [PATCH 24/71] Fix GBA Flash read/writes and clean up --- src/GBACart.cpp | 79 +++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 473d9942..2260e06c 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -46,6 +46,7 @@ struct FlashProperties }; u8* SRAM; +FILE* SRAMFile; u32 SRAMLength; SaveType SRAMType; FlashProperties SRAMFlash; @@ -64,18 +65,23 @@ void Write_Flash(u32 addr, u8 val); bool Init() { SRAM = NULL; + SRAMFile = NULL; return true; } void DeInit() { + if (SRAMFile) fclose(SRAMFile); if (SRAM) delete[] SRAM; } void Reset() { + if (SRAMFile) fclose(SRAMFile); if (SRAM) delete[] SRAM; + SRAM = NULL; + SRAMFile = NULL; SRAMLength = 0; SRAMType = S_NULL; SRAMFlash = {}; @@ -94,7 +100,7 @@ void LoadSave(const char* path) SRAMPath[1023] = '\0'; SRAMLength = 0; - FILE* f = Platform::OpenFile(path, "rb"); + FILE* f = Platform::OpenFile(SRAMPath, "r+b"); if (f) { fseek(f, 0, SEEK_END); @@ -104,7 +110,7 @@ void LoadSave(const char* path) fseek(f, 0, SEEK_SET); fread(SRAM, SRAMLength, 1, f); - fclose(f); + SRAMFile = f; } switch (SRAMLength) @@ -162,15 +168,15 @@ void RelocateSave(const char* path, bool write) strncpy(SRAMPath, path, 1023); SRAMPath[1023] = '\0'; - FILE* f = Platform::OpenFile(path, "wb"); + FILE *f = Platform::OpenFile(path, "r+b"); if (!f) { printf("GBACart_SRAM::RelocateSave: failed to create new file. fuck\n"); return; } - fwrite(SRAM, SRAMLength, 1, f); - fclose(f); + SRAMFile = f; + fwrite(SRAM, SRAMLength, 1, SRAMFile); } u8 Read_Flash(u32 addr) @@ -190,6 +196,8 @@ u8 Read_Flash(u32 addr) SRAMFlash.state = 0; SRAMFlash.cmd = 0; break; + case 0xA0: // erase command + break; // ignore here, handled during writes case 0xB0: // bank switching (128K only) break; // ignore here, handled during writes default: @@ -269,6 +277,7 @@ void Write_Flash(u32 addr, u8 val) SRAMFlash.cmd = val; return; } + SRAMFlash.state = 0; break; // erase case 0x80: @@ -293,12 +302,10 @@ void Write_Flash(u32 addr, u8 val) u32 start_addr = addr + 0x10000 * SRAMFlash.bank; memset((u8*)&SRAM[start_addr], 0xFF, 0x1000); - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) + if (SRAMFile) { - fseek(f, start_addr, SEEK_SET); - fwrite((u8*)&SRAM[start_addr], 1, 0x1000, f); - fclose(f); + fseek(SRAMFile, start_addr, SEEK_SET); + fwrite((u8*)&SRAM[start_addr], 1, 0x1000, SRAMFile); } } SRAMFlash.state = 0; @@ -343,15 +350,18 @@ void Write_Flash(u32 addr, u8 val) void Write_SRAM(u32 addr, u8 val) { - *(u8*)&SRAM[addr] = val; + u8 prev = *(u8*)&SRAM[addr]; - // bit wasteful to do this for every written byte - FILE* f = Platform::OpenFile(SRAMPath, "r+b"); - if (f) + // TODO: try not to do this for every byte + if (prev != val) { - fseek(f, addr, SEEK_SET); - fwrite((u8*)&SRAM[addr], 1, 1, f); - fclose(f); + *(u8*)&SRAM[addr] = val; + + if (SRAMFile) + { + fseek(SRAMFile, addr, SEEK_SET); + fwrite((u8*)&SRAM[addr], 1, 1, SRAMFile); + } } } @@ -379,7 +389,9 @@ u16 Read16(u32 addr) if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) { - return Read_Flash(addr) & (Read_Flash(addr + 1) << 8); + u16 val = Read_Flash(addr + 0) | + (Read_Flash(addr + 1) << 8); + return val; } return *(u16*)&SRAM[addr]; @@ -394,10 +406,11 @@ u32 Read32(u32 addr) if (SRAMType == S_FLASH512K || SRAMType == S_FLASH1M) { - return Read_Flash(addr) & - (Read_Flash(addr + 1) << 8) & - (Read_Flash(addr + 2) << 16) & + u32 val = Read_Flash(addr + 0) | + (Read_Flash(addr + 1) << 8) | + (Read_Flash(addr + 2) << 16) | (Read_Flash(addr + 3) << 24); + return val; } return *(u32*)&SRAM[addr]; @@ -407,34 +420,25 @@ void Write8(u32 addr, u8 val) { u8 prev = *(u8*)&SRAM[addr]; - if (prev != val) - { - WriteFunc(addr, val); - } + WriteFunc(addr, val); } void Write16(u32 addr, u16 val) { u16 prev = *(u16*)&SRAM[addr]; - if (prev != val) - { - WriteFunc(addr, val & 0xFF); - WriteFunc(addr + 1, val >> 8 & 0xFF); - } + WriteFunc(addr + 0, val & 0xFF); + WriteFunc(addr + 1, val >> 8 & 0xFF); } void Write32(u32 addr, u32 val) { u32 prev = *(u32*)&SRAM[addr]; - if (prev != val) - { - WriteFunc(addr, val & 0xFF); - WriteFunc(addr + 1, val >> 8 & 0xFF); - WriteFunc(addr + 2, val >> 16 & 0xFF); - WriteFunc(addr + 3, val >> 24 & 0xFF); - } + WriteFunc(addr + 0, val & 0xFF); + WriteFunc(addr + 1, val >> 8 & 0xFF); + WriteFunc(addr + 2, val >> 16 & 0xFF); + WriteFunc(addr + 3, val >> 24 & 0xFF); } } @@ -512,7 +516,6 @@ bool LoadROM(const char* path, const char* sram) fread(CartROM, 1, len, f); fclose(f); - //CartROM = f; CartCRC = CRC32(CartROM, CartROMSize); printf("ROM CRC32: %08X\n", CartCRC); From 4d1f3d419ee2859a243bc8fb1db37afaffee8a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 09:57:10 -0500 Subject: [PATCH 25/71] Clarify comments and credit DeSmuME for Flash I/O --- src/GBACart.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 2260e06c..1011971c 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -36,6 +36,7 @@ enum SaveType { S_FLASH1M }; +// from DeSmuME struct FlashProperties { u8 state; @@ -179,6 +180,7 @@ void RelocateSave(const char* path, bool write) fwrite(SRAM, SRAMLength, 1, SRAMFile); } +// mostly ported from DeSmuME u8 Read_Flash(u32 addr) { if (SRAMFlash.cmd == 0) // no cmd @@ -196,10 +198,10 @@ u8 Read_Flash(u32 addr) SRAMFlash.state = 0; SRAMFlash.cmd = 0; break; - case 0xA0: // erase command - break; // ignore here, handled during writes + case 0xA0: // write command + break; // ignore here, handled in Write_Flash() case 0xB0: // bank switching (128K only) - break; // ignore here, handled during writes + break; // ignore here, handled in Write_Flash() default: printf("GBACart_SRAM::Read_Flash: unknown command 0x%02X @ 0x%04X\n", SRAMFlash.cmd, addr); break; @@ -215,6 +217,7 @@ void Write_EEPROM(u32 addr, u8 val) // TODO: could be used in homebrew? } +// mostly ported from DeSmuME void Write_Flash(u32 addr, u8 val) { switch (SRAMFlash.state) @@ -352,7 +355,6 @@ void Write_SRAM(u32 addr, u8 val) { u8 prev = *(u8*)&SRAM[addr]; - // TODO: try not to do this for every byte if (prev != val) { *(u8*)&SRAM[addr] = val; From 00929371481ce0fa29adfe5a58e364f27713099a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 16:36:00 -0500 Subject: [PATCH 26/71] Rename SRAMFlash to SRAMFlashState --- src/GBACart.cpp | 95 ++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 1011971c..b5445197 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -26,7 +26,6 @@ namespace GBACart_SRAM { - enum SaveType { S_NULL, S_EEPROM4K, @@ -50,7 +49,7 @@ u8* SRAM; FILE* SRAMFile; u32 SRAMLength; SaveType SRAMType; -FlashProperties SRAMFlash; +FlashProperties SRAMFlashState; char SRAMPath[1024]; @@ -85,7 +84,7 @@ void Reset() SRAMFile = NULL; SRAMLength = 0; SRAMType = S_NULL; - SRAMFlash = {}; + SRAMFlashState = {}; } void DoSavestate(Savestate* file) @@ -147,14 +146,14 @@ void LoadSave(const char* path) if (SRAMType == S_FLASH512K) { // Panasonic 64K chip - SRAMFlash.device = 0x1B; - SRAMFlash.manufacturer = 0x32; + SRAMFlashState.device = 0x1B; + SRAMFlashState.manufacturer = 0x32; } else if (SRAMType == S_FLASH1M) { // Sanyo 128K chip - SRAMFlash.device = 0x13; - SRAMFlash.manufacturer = 0x62; + SRAMFlashState.device = 0x13; + SRAMFlashState.manufacturer = 0x62; } } @@ -183,27 +182,27 @@ void RelocateSave(const char* path, bool write) // mostly ported from DeSmuME u8 Read_Flash(u32 addr) { - if (SRAMFlash.cmd == 0) // no cmd + if (SRAMFlashState.cmd == 0) // no cmd { - return *(u8*)&SRAM[addr + 0x10000 * SRAMFlash.bank]; + return *(u8*)&SRAM[addr + 0x10000 * SRAMFlashState.bank]; } - switch (SRAMFlash.cmd) + switch (SRAMFlashState.cmd) { case 0x90: // chip ID - if (addr == 0x0000) return SRAMFlash.manufacturer; - if (addr == 0x0001) return SRAMFlash.device; + if (addr == 0x0000) return SRAMFlashState.manufacturer; + if (addr == 0x0001) return SRAMFlashState.device; break; case 0xF0: // terminate command (TODO: break if non-Macronix chip and not at the end of an ID call?) - SRAMFlash.state = 0; - SRAMFlash.cmd = 0; + SRAMFlashState.state = 0; + SRAMFlashState.cmd = 0; break; case 0xA0: // write command break; // ignore here, handled in Write_Flash() case 0xB0: // bank switching (128K only) break; // ignore here, handled in Write_Flash() default: - printf("GBACart_SRAM::Read_Flash: unknown command 0x%02X @ 0x%04X\n", SRAMFlash.cmd, addr); + printf("GBACart_SRAM::Read_Flash: unknown command 0x%02X @ 0x%04X\n", SRAMFlashState.cmd, addr); break; } @@ -220,7 +219,7 @@ void Write_EEPROM(u32 addr, u8 val) // mostly ported from DeSmuME void Write_Flash(u32 addr, u8 val) { - switch (SRAMFlash.state) + switch (SRAMFlashState.state) { case 0x00: if (addr == 0x5555) @@ -228,23 +227,23 @@ void Write_Flash(u32 addr, u8 val) if (val == 0xF0) { // reset - SRAMFlash.state = 0; - SRAMFlash.cmd = 0; + SRAMFlashState.state = 0; + SRAMFlashState.cmd = 0; return; } else if (val == 0xAA) { - SRAMFlash.state = 1; + SRAMFlashState.state = 1; return; } } if (addr == 0x0000) { - if (SRAMFlash.cmd == 0xB0) + if (SRAMFlashState.cmd == 0xB0) { // bank switching - SRAMFlash.bank = val; - SRAMFlash.cmd = 0; + SRAMFlashState.bank = val; + SRAMFlashState.cmd = 0; return; } } @@ -252,10 +251,10 @@ void Write_Flash(u32 addr, u8 val) case 0x01: if (addr == 0x2AAA && val == 0x55) { - SRAMFlash.state = 2; + SRAMFlashState.state = 2; return; } - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; case 0x02: if (addr == 0x5555) @@ -264,45 +263,45 @@ void Write_Flash(u32 addr, u8 val) switch (val) { case 0x80: // erase - SRAMFlash.state = 0x80; + SRAMFlashState.state = 0x80; break; case 0x90: // chip ID - SRAMFlash.state = 0x90; + SRAMFlashState.state = 0x90; break; case 0xA0: // write - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; default: - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; } - SRAMFlash.cmd = val; + SRAMFlashState.cmd = val; return; } - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; // erase case 0x80: if (addr == 0x5555 && val == 0xAA) { - SRAMFlash.state = 0x81; + SRAMFlashState.state = 0x81; return; } - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; case 0x81: if (addr == 0x2AAA && val == 0x55) { - SRAMFlash.state = 0x82; + SRAMFlashState.state = 0x82; return; } - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; case 0x82: if (val == 0x30) { - u32 start_addr = addr + 0x10000 * SRAMFlash.bank; + u32 start_addr = addr + 0x10000 * SRAMFlashState.bank; memset((u8*)&SRAM[start_addr], 0xFF, 0x1000); if (SRAMFile) @@ -311,44 +310,44 @@ void Write_Flash(u32 addr, u8 val) fwrite((u8*)&SRAM[start_addr], 1, 0x1000, SRAMFile); } } - SRAMFlash.state = 0; - SRAMFlash.cmd = 0; + SRAMFlashState.state = 0; + SRAMFlashState.cmd = 0; return; // chip ID case 0x90: if (addr == 0x5555 && val == 0xAA) { - SRAMFlash.state = 0x91; + SRAMFlashState.state = 0x91; return; } - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; case 0x91: if (addr == 0x2AAA && val == 0x55) { - SRAMFlash.state = 0x92; + SRAMFlashState.state = 0x92; return; } - SRAMFlash.state = 0; + SRAMFlashState.state = 0; break; case 0x92: - SRAMFlash.state = 0; - SRAMFlash.cmd = 0; + SRAMFlashState.state = 0; + SRAMFlashState.cmd = 0; return; default: break; } - if (SRAMFlash.cmd == 0xA0) // write + if (SRAMFlashState.cmd == 0xA0) // write { - Write_SRAM(addr + 0x10000 * SRAMFlash.bank, val); - SRAMFlash.state = 0; - SRAMFlash.cmd = 0; + Write_SRAM(addr + 0x10000 * SRAMFlashState.bank, val); + SRAMFlashState.state = 0; + SRAMFlashState.cmd = 0; return; } printf("GBACart_SRAM::Write_Flash: unknown write 0x%02X @ 0x%04X (state: 0x%02X)\n", - val, addr, SRAMFlash.state); + val, addr, SRAMFlashState.state); } void Write_SRAM(u32 addr, u8 val) From 9128517b9086b9508dac375fb2764dcdc9ea3947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 16:36:38 -0500 Subject: [PATCH 27/71] Add basic GBA GPIO support, solar sensor detection --- src/GBACart.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- src/GBACart.h | 2 ++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index b5445197..75bc1dc3 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -448,11 +448,34 @@ void Write32(u32 addr, u32 val) namespace GBACart { +const char SOLAR_SENSOR_GAMECODES[10][5] = +{ + "U3IJ", // Bokura no Taiyou - Taiyou Action RPG (Japan) + "U3IE", // Boktai - The Sun Is in Your Hand (USA) + "U3IP", // Boktai - The Sun Is in Your Hand (Europe) + "U32J", // Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan) + "U32E", // Boktai 2 - Solar Boy Django (USA) + "U32P", // Boktai 2 - Solar Boy Django (Europe) + "U33J", // Shin Bokura no Taiyou - Gyakushuu no Sabata (Japan) + "A3IJ" // Boktai - The Sun Is in Your Hand (USA) (Sample) +}; + + +struct GPIO +{ + bool has_solar_sensor; + u16 data; + u16 direction; + u16 control; +}; + + bool CartInserted; u8* CartROM; u32 CartROMSize; u32 CartCRC; u32 CartID; +GPIO CartGPIO; // overridden GPIO parameters bool Init() @@ -477,6 +500,7 @@ void Reset() if (CartROM) delete[] CartROM; CartROM = NULL; CartROMSize = 0; + CartGPIO = {}; GBACart_SRAM::Reset(); } @@ -506,10 +530,20 @@ bool LoadROM(const char* path, const char* sram) while (CartROMSize < len) CartROMSize <<= 1; - u32 gamecode; + char gamecode[5] = { '\0' }; fseek(f, 0xAC, SEEK_SET); - fread(&gamecode, 4, 1, f); - printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24); + fread(&gamecode, 1, 4, f); + printf("Game code: %s\n", gamecode); + + for (int i = 0; i < sizeof(SOLAR_SENSOR_GAMECODES)/sizeof(SOLAR_SENSOR_GAMECODES[0]); i++) + { + if (strcmp(gamecode, SOLAR_SENSOR_GAMECODES[i]) == 0) CartGPIO.has_solar_sensor = true; + } + + if (CartGPIO.has_solar_sensor) + { + printf("GBA solar sensor support detected!\n"); + } CartROM = new u8[CartROMSize]; memset(CartROM, 0, CartROMSize); @@ -536,4 +570,41 @@ void RelocateSave(const char* path, bool write) GBACart_SRAM::RelocateSave(path, write); } +// referenced from mGBA +void WriteGPIO(u32 addr, u16 val) +{ + switch (addr) + { + case 0xC4: + CartGPIO.data &= ~CartGPIO.direction; + CartGPIO.data |= val & CartGPIO.direction; + // TODO: process pins + break; + case 0xC6: + CartGPIO.direction = val; + break; + case 0xC8: + CartGPIO.control = val; + break; + default: + printf("Unknown GBA GPIO write 0x%02X @ 0x%04X\n", val, addr); + } + + // write the GPIO values in the ROM (if writable) + if (CartGPIO.control & 1) + { + *(u16*)&CartROM[addr] = CartGPIO.data; + *(u16*)&CartROM[addr + 2] = CartGPIO.direction; + *(u16*)&CartROM[addr + 4] = CartGPIO.control; + } + else + { + // GBATEK: "in write-only mode, reads return 00h (or [possibly] other data (...))" + // ambiguous, but mGBA sets ROM to 00h when switching to write-only, so do the same + *(u16*)&CartROM[addr] = 0; + *(u16*)&CartROM[addr + 2] = 0; + *(u16*)&CartROM[addr + 4] = 0; + } +} + } diff --git a/src/GBACart.h b/src/GBACart.h index 81fb2227..22a3a603 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -55,6 +55,8 @@ void DoSavestate(Savestate* file); bool LoadROM(const char* path, const char* sram); void RelocateSave(const char* path, bool write); +void WriteGPIO(u32 addr, u16 val); + } #endif // GBACART_H From f6cd66e5b1eb02f1664a4de083085fb81e6816b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 17:43:25 -0500 Subject: [PATCH 28/71] Implement solar sensor processing --- src/GBACart.cpp | 67 +++++++++++++++++++++++++++++++++++++------------ src/GBACart.h | 19 ++++++++++++++ 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 75bc1dc3..5b819001 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -461,15 +461,6 @@ const char SOLAR_SENSOR_GAMECODES[10][5] = }; -struct GPIO -{ - bool has_solar_sensor; - u16 data; - u16 direction; - u16 control; -}; - - bool CartInserted; u8* CartROM; u32 CartROMSize; @@ -503,6 +494,7 @@ void Reset() CartGPIO = {}; GBACart_SRAM::Reset(); + GBACart_SolarSensor::Reset(); } void DoSavestate(Savestate* file) @@ -578,7 +570,7 @@ void WriteGPIO(u32 addr, u16 val) case 0xC4: CartGPIO.data &= ~CartGPIO.direction; CartGPIO.data |= val & CartGPIO.direction; - // TODO: process pins + if (CartGPIO.has_solar_sensor) GBACart_SolarSensor::Process(&CartGPIO); break; case 0xC6: CartGPIO.direction = val; @@ -593,17 +585,60 @@ void WriteGPIO(u32 addr, u16 val) // write the GPIO values in the ROM (if writable) if (CartGPIO.control & 1) { - *(u16*)&CartROM[addr] = CartGPIO.data; - *(u16*)&CartROM[addr + 2] = CartGPIO.direction; - *(u16*)&CartROM[addr + 4] = CartGPIO.control; + *(u16*)&CartROM[0xC4] = CartGPIO.data; + *(u16*)&CartROM[0xC6] = CartGPIO.direction; + *(u16*)&CartROM[0xC8] = CartGPIO.control; } else { // GBATEK: "in write-only mode, reads return 00h (or [possibly] other data (...))" // ambiguous, but mGBA sets ROM to 00h when switching to write-only, so do the same - *(u16*)&CartROM[addr] = 0; - *(u16*)&CartROM[addr + 2] = 0; - *(u16*)&CartROM[addr + 4] = 0; + *(u16*)&CartROM[0xC4] = 0; + *(u16*)&CartROM[0xC6] = 0; + *(u16*)&CartROM[0xC8] = 0; + } +} + +} + + +namespace GBACart_SolarSensor +{ + +bool LightEdge; +u8 LightCounter; +u8 LightSample; +u8 LightLevel; // 0-10 range + +// levels from mGBA +const int GBA_LUX_LEVELS[11] = { 0, 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 }; +#define LIGHT_VALUE (0xFF - (0x16 + GBA_LUX_LEVELS[LightLevel])) + + +void Reset() +{ + LightEdge = false; + LightCounter = 0; + LightSample = 0xFF; + LightLevel = 0; +} + +void Process(GBACart::GPIO* gpio) +{ + if (gpio->data & 4) return; // Boktai chip select + if (gpio->data & 2) // Reset + { + LightCounter = 0; + LightSample = LIGHT_VALUE; + } + if (gpio->data & 1 && LightEdge) LightCounter++; + + LightEdge = !(gpio->data & 1); + + bool sendBit = LightCounter >= LightSample; + if (gpio->control & 1) + { + gpio->data = (gpio->data & gpio->direction) | ((sendBit << 3) & ~gpio->direction & 0xF); } } diff --git a/src/GBACart.h b/src/GBACart.h index 22a3a603..32a2171e 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -43,6 +43,14 @@ void Write32(u32 addr, u32 val); namespace GBACart { +struct GPIO +{ + bool has_solar_sensor; + u16 data; + u16 direction; + u16 control; +}; + extern bool CartInserted; extern u8* CartROM; extern u32 CartROMSize; @@ -59,4 +67,15 @@ void WriteGPIO(u32 addr, u16 val); } + +namespace GBACart_SolarSensor +{ + +extern u8 LightLevel; + +void Reset(); +void Process(GBACart::GPIO* gpio); + +} + #endif // GBACART_H From ca9f183d24c028cbbbecbe07aefb37bdcd04a581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 17:54:34 -0500 Subject: [PATCH 29/71] Hook up solar sensor control to the UI It uses hardcoded keypad left and right arrows. --- src/GBACart.cpp | 8 +++++--- src/GBACart.h | 2 +- src/libui_sdl/main.cpp | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 5b819001..a7ddf9b6 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -462,6 +462,7 @@ const char SOLAR_SENSOR_GAMECODES[10][5] = bool CartInserted; +bool HasSolarSensor; u8* CartROM; u32 CartROMSize; u32 CartCRC; @@ -488,6 +489,7 @@ void DeInit() void Reset() { CartInserted = false; + HasSolarSensor = false; if (CartROM) delete[] CartROM; CartROM = NULL; CartROMSize = 0; @@ -529,10 +531,10 @@ bool LoadROM(const char* path, const char* sram) for (int i = 0; i < sizeof(SOLAR_SENSOR_GAMECODES)/sizeof(SOLAR_SENSOR_GAMECODES[0]); i++) { - if (strcmp(gamecode, SOLAR_SENSOR_GAMECODES[i]) == 0) CartGPIO.has_solar_sensor = true; + if (strcmp(gamecode, SOLAR_SENSOR_GAMECODES[i]) == 0) HasSolarSensor = true; } - if (CartGPIO.has_solar_sensor) + if (HasSolarSensor) { printf("GBA solar sensor support detected!\n"); } @@ -570,7 +572,7 @@ void WriteGPIO(u32 addr, u16 val) case 0xC4: CartGPIO.data &= ~CartGPIO.direction; CartGPIO.data |= val & CartGPIO.direction; - if (CartGPIO.has_solar_sensor) GBACart_SolarSensor::Process(&CartGPIO); + if (HasSolarSensor) GBACart_SolarSensor::Process(&CartGPIO); break; case 0xC6: CartGPIO.direction = val; diff --git a/src/GBACart.h b/src/GBACart.h index 32a2171e..032c4fc1 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -45,13 +45,13 @@ namespace GBACart struct GPIO { - bool has_solar_sensor; u16 data; u16 direction; u16 control; }; extern bool CartInserted; +extern bool HasSolarSensor; extern u8* CartROM; extern u32 CartROMSize; diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 31b04889..1b7cfe6a 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -38,6 +38,7 @@ #include "DlgWifiSettings.h" #include "../NDS.h" +#include "../GBACart.h" #include "../GPU.h" #include "../SPU.h" #include "../Wifi.h" @@ -1291,6 +1292,20 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) { if (evt->Modifiers == 0x0) UndoStateLoad(); } + else if (evt->Scancode == 0x4B) // Keypad left + { + if (GBACart::CartInserted && GBACart::HasSolarSensor) + { + if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; + } + } + else if (evt->Scancode == 0x4D) // Keypad right + { + if (GBACart::CartInserted && GBACart::HasSolarSensor) + { + if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; + } + } for (int i = 0; i < 12; i++) if (EventMatchesKey(evt, Config::KeyMapping[i], false)) From f257b007a250e33ecc7a86c7447ccf049964dd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 18:44:53 -0500 Subject: [PATCH 30/71] Properly pass through GBA GPIO writes --- src/GBACart.cpp | 2 + src/NDS.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++ src/libui_sdl/main.cpp | 2 + 3 files changed, 92 insertions(+) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index a7ddf9b6..7e5e3b58 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -630,8 +630,10 @@ void Process(GBACart::GPIO* gpio) if (gpio->data & 4) return; // Boktai chip select if (gpio->data & 2) // Reset { + u8 prev = LightSample; LightCounter = 0; LightSample = LIGHT_VALUE; + printf("Solar sensor reset (sample: 0x%02X -> 0x%02X)\n", prev, LightSample); } if (gpio->data & 1 && LightEdge) LightCounter++; diff --git a/src/NDS.cpp b/src/NDS.cpp index a906fbb0..47f96c90 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1803,6 +1803,19 @@ void ARM9Write8(u32 addr, u8 val) // checkme return; + case 0x08000000: + case 0x09000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + if ((addr & 0x00FFFFFF) >= 0xC4 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -1854,6 +1867,21 @@ void ARM9Write16(u32 addr, u16 val) *(u16*)&GPU::OAM[addr & 0x7FF] = val; return; + case 0x08000000: + case 0x09000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC3 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -1905,6 +1933,22 @@ void ARM9Write32(u32 addr, u32 val) *(u32*)&GPU::OAM[addr & 0x7FF] = val; return; + case 0x08000000: + case 0x09000000: + if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC1 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val & 0xFF); + GBACart::WriteGPIO((addr + 2) & (GBACart::CartROMSize-1), (val >> 16) & 0xFF); + return; + } + } + break; + case 0x0A000000: if (ExMemCnt[0] & (1<<7)) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -2177,6 +2221,19 @@ void ARM7Write8(u32 addr, u8 val) GPU::WriteVRAM_ARM7(addr, val); return; + case 0x08000000: + case 0x09000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + if ((addr & 0x00FFFFFF) >= 0xC4 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -2231,6 +2288,21 @@ void ARM7Write16(u32 addr, u16 val) GPU::WriteVRAM_ARM7(addr, val); return; + case 0x08000000: + case 0x09000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC3 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val); + return; + } + } + break; + case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write if (GBACart::CartInserted) @@ -2286,6 +2358,22 @@ void ARM7Write32(u32 addr, u32 val) GPU::WriteVRAM_ARM7(addr, val); return; + case 0x08000000: + case 0x09000000: + if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write + if (GBACart::CartInserted) + { + // Note: the lower bound is adjusted such that a write starting + // there will hit the first byte of the GPIO region. + if ((addr & 0x00FFFFFF) >= 0xC1 && (addr & 0x00FFFFFF) <= 0xC9) + { + GBACart::WriteGPIO(addr & (GBACart::CartROMSize-1), val & 0xFF); + GBACart::WriteGPIO((addr + 2) & (GBACart::CartROMSize-1), (val >> 16) & 0xFF); + return; + } + } + break; + case 0x0A000000: if (!(ExMemCnt[0] & (1<<7))) return; // deselected CPU, skip the write if (GBACart::CartInserted) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 1b7cfe6a..d2a38f25 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1297,6 +1297,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (GBACart::CartInserted && GBACart::HasSolarSensor) { if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; + printf("Solar sensor level set to %d\n", GBACart_SolarSensor::LightLevel); } } else if (evt->Scancode == 0x4D) // Keypad right @@ -1304,6 +1305,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (GBACart::CartInserted && GBACart::HasSolarSensor) { if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; + printf("Solar sensor level set to %d\n", GBACart_SolarSensor::LightLevel); } } From f8e43ac486aa7bbc9ebfdbd23b959f0fa163c51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 19:24:28 -0500 Subject: [PATCH 31/71] Display solar sensor level changes on OSD --- src/libui_sdl/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index d2a38f25..a96b77a4 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1297,7 +1297,9 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (GBACart::CartInserted && GBACart::HasSolarSensor) { if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; - printf("Solar sensor level set to %d\n", GBACart_SolarSensor::LightLevel); + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); } } else if (evt->Scancode == 0x4D) // Keypad right @@ -1305,7 +1307,9 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (GBACart::CartInserted && GBACart::HasSolarSensor) { if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; - printf("Solar sensor level set to %d\n", GBACart_SolarSensor::LightLevel); + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); } } From 7027813cb268c8b168a2c6ac7e871761f02a4435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Wed, 11 Dec 2019 10:29:51 -0500 Subject: [PATCH 32/71] Add C/C++ with CMake GitHub workflow This enables continuous integration with GitHub Actions. --- .github/workflows/ccppcmake.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/ccppcmake.yml diff --git a/.github/workflows/ccppcmake.yml b/.github/workflows/ccppcmake.yml new file mode 100644 index 00000000..7cf43395 --- /dev/null +++ b/.github/workflows/ccppcmake.yml @@ -0,0 +1,32 @@ +name: C/C++ CI with CMake + +on: [push] + +env: + BUILD_TYPE: Release + CMAKE_VERSION: 3.15.2 + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Install dependencies + shell: bash + working-directory: ${{runner.workspace}} + run: | # Fetch a new version of CMake, because the default is too old. + wget -nv https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ + && tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ + && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev + - name: Create build environment + run: mkdir ${{runner.workspace}}/build + - name: Configure + shell: bash + working-directory: ${{runner.workspace}}/build + run: ${{runner.workspace}}/cmake-$CMAKE_VERSION-Linux-x86_64/bin/cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - name: Make + shell: bash + working-directory: ${{runner.workspace}}/build + run: make -j$(nproc --all) From 295404a5a696c158df2ddf9b9548c0a4b8c368c6 Mon Sep 17 00:00:00 2001 From: i404788 <50617709+i404788@users.noreply.github.com> Date: Thu, 12 Dec 2019 09:03:01 +0000 Subject: [PATCH 33/71] Fix weird spacing --- src/libui_sdl/LAN_PCap.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index 312af0ea..44af0a36 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -263,12 +263,12 @@ bool Init(bool open_adapter) continue; } - if (!curaddr->ifa_addr) - { - printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); - curaddr = curaddr->ifa_next; - continue; - } + if (!curaddr->ifa_addr) + { + printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); + curaddr = curaddr->ifa_next; + continue; + } u16 af = curaddr->ifa_addr->sa_family; if (af == AF_INET) From d2e75197634de2e2252fe49b70b3461b506bd15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Thu, 12 Dec 2019 15:23:57 -0500 Subject: [PATCH 34/71] Enable GitHub CI on pull request Also rename the build to be more specific. --- .github/workflows/{ccppcmake.yml => build-ubuntu.yml} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename .github/workflows/{ccppcmake.yml => build-ubuntu.yml} (94%) diff --git a/.github/workflows/ccppcmake.yml b/.github/workflows/build-ubuntu.yml similarity index 94% rename from .github/workflows/ccppcmake.yml rename to .github/workflows/build-ubuntu.yml index 7cf43395..fc5bd90c 100644 --- a/.github/workflows/ccppcmake.yml +++ b/.github/workflows/build-ubuntu.yml @@ -1,6 +1,6 @@ -name: C/C++ CI with CMake +name: CMake Build (Ubuntu x86-64) -on: [push] +on: [push, pull_request] env: BUILD_TYPE: Release @@ -8,9 +8,9 @@ env: jobs: build: - + runs-on: ubuntu-latest - + steps: - uses: actions/checkout@v1 - name: Install dependencies From 469ff2d932f21efbf2f4693625e130f2c62a7421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Thu, 12 Dec 2019 15:44:11 -0500 Subject: [PATCH 35/71] Update packages on CI before installing --- .github/workflows/build-ubuntu.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index fc5bd90c..8223e04f 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -19,6 +19,7 @@ jobs: run: | # Fetch a new version of CMake, because the default is too old. wget -nv https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ && tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ + && sudo apt-get update \ && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev - name: Create build environment run: mkdir ${{runner.workspace}}/build From 546e7ded96f88d92b6c7654b1bf73eee7e272d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Thu, 12 Dec 2019 15:44:34 -0500 Subject: [PATCH 36/71] Add Windows CI configuration --- .github/workflows/build-windows.yml | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/build-windows.yml diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 00000000..1b91df3f --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,34 @@ +name: CMake Build (Windows x86-64) + +on: [push, pull_request] + +env: + BUILD_TYPE: Release + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: Install MSYS2 + working-directory: ${{runner.workspace}} + run: | # Fetch MSYS2 build from XQEmu. Official distribution causes a CI failure due to permission errors. + Invoke-WebRequest -Uri "https://github.com/xqemu/ci-environment-msys2/releases/latest/download/msys64.7z" -OutFile "msys64.7z" + 7z x -y msys64.7z "-oC:\tools\" + C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Syuq --noconfirm" + - name: Install dependencies + run: C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Sq --noconfirm git make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain}" + - name: Create build environment + run: | + New-Item -ItemType directory -Path ${{runner.workspace}}\melonDS\build + Copy-Item -Path ${{runner.workspace}}\melonDS -Destination C:\tools\msys64\home\runneradmin -Recurse + - name: Configure + run: | + C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \ + && cd melonDS/build && cmake .. -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}" + - name: Make + run: | + C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \ + && cd melonDS/build && make -j$(nproc --all)" From 331c3c3b86fb32d781e0f9fdeb8dd8ebc7c53660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Thu, 12 Dec 2019 22:06:57 -0500 Subject: [PATCH 37/71] Upload CI build artifacts --- .github/workflows/build-ubuntu.yml | 4 ++++ .github/workflows/build-windows.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index 8223e04f..e8309856 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -31,3 +31,7 @@ jobs: shell: bash working-directory: ${{runner.workspace}}/build run: make -j$(nproc --all) + - uses: actions/upload-artifact@v1 + with: + name: melonDS + path: ${{runner.workspace}}/build/melonDS diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 1b91df3f..0c66a5a0 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -32,3 +32,7 @@ jobs: run: | C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \ && cd melonDS/build && make -j$(nproc --all)" + - uses: actions/upload-artifact@v1 + with: + name: melonDS.exe + path: C:\tools\msys64\home\runneradmin\melonDS\build\melonDS.exe From 86ae2e02d0251b3bb8784dc5f0b8974e93b2f4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Fri, 13 Dec 2019 09:18:36 -0500 Subject: [PATCH 38/71] Fix Ubuntu CI when Microsoft breaks repositories --- .github/workflows/build-ubuntu.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index e8309856..a93d707f 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -19,6 +19,7 @@ jobs: run: | # Fetch a new version of CMake, because the default is too old. wget -nv https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ && tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ + && sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \ && sudo apt-get update \ && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev - name: Create build environment From 55db337c8d8e03108ab642a1c0d8772e06e4c6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Fri, 13 Dec 2019 11:34:28 -0500 Subject: [PATCH 39/71] Package shared resources with Windows CI artifacts --- .github/workflows/build-windows.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 0c66a5a0..c7d05d03 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -31,8 +31,9 @@ jobs: - name: Make run: | C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \ - && cd melonDS/build && make -j$(nproc --all)" + && cd melonDS/build && make -j$(nproc --all) \ + && ../msys-dist.sh" - uses: actions/upload-artifact@v1 with: - name: melonDS.exe - path: C:\tools\msys64\home\runneradmin\melonDS\build\melonDS.exe + name: melonDS + path: C:\tools\msys64\home\runneradmin\melonDS\build\dist From 67903b7974dc6d44cda10c1c74eadebd1b4bbd2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Fri, 13 Dec 2019 12:42:39 -0500 Subject: [PATCH 40/71] Include romlist.bin with Linux CI artifacts --- .github/workflows/build-ubuntu.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index a93d707f..fed0f3e2 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -17,11 +17,11 @@ jobs: shell: bash working-directory: ${{runner.workspace}} run: | # Fetch a new version of CMake, because the default is too old. - wget -nv https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ - && tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ - && sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \ - && sudo apt-get update \ - && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev + wget -nv https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ + && tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ + && sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \ + && sudo apt-get update \ + && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev - name: Create build environment run: mkdir ${{runner.workspace}}/build - name: Configure @@ -31,8 +31,11 @@ jobs: - name: Make shell: bash working-directory: ${{runner.workspace}}/build - run: make -j$(nproc --all) + run: | + make -j$(nproc --all) \ + && mkdir dist \ + && cp {melonDS,romlist.bin} dist - uses: actions/upload-artifact@v1 with: name: melonDS - path: ${{runner.workspace}}/build/melonDS + path: ${{runner.workspace}}/build/dist From 43535c873ac1b4ce80212b052b0455a1eaaa0208 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Thu, 19 Dec 2019 02:48:11 +0100 Subject: [PATCH 41/71] Remove redundant desktop file and change desktop/icon file name to net.kuribo64.melonDS, also change melonds to melonDS. --- ...kuribo64.melonds.yml => net.kuribo64.melonDS.yml} | 12 +++++------- flatpak/net.kuribo64.melonds.desktop | 8 -------- melonDS.desktop => net.kuribo64.melonDS.desktop | 2 +- src/libui_sdl/CMakeLists.txt | 4 ++-- 4 files changed, 8 insertions(+), 18 deletions(-) rename flatpak/{net.kuribo64.melonds.yml => net.kuribo64.melonDS.yml} (71%) delete mode 100644 flatpak/net.kuribo64.melonds.desktop rename melonDS.desktop => net.kuribo64.melonDS.desktop (91%) diff --git a/flatpak/net.kuribo64.melonds.yml b/flatpak/net.kuribo64.melonDS.yml similarity index 71% rename from flatpak/net.kuribo64.melonds.yml rename to flatpak/net.kuribo64.melonDS.yml index dcc97b5b..e3369909 100644 --- a/flatpak/net.kuribo64.melonds.yml +++ b/flatpak/net.kuribo64.melonDS.yml @@ -1,5 +1,5 @@ --- -app-id: net.kuribo64.melonds +app-id: net.kuribo64.melonDS runtime: org.freedesktop.Platform runtime-version: '18.08' sdk: org.freedesktop.Sdk @@ -22,10 +22,8 @@ modules: buildsystem: cmake-ninja sources: - type: git - url: https://github.com/StapleButter/melonDS.git - commit: d4d4965b2fffc69958685a25a9d9fc0c78b54567 - - type: file - path: net.kuribo64.melonds.desktop + url: https://github.com/Arisotura/melonDS.git + branch: master post-install: - - "desktop-file-install --dir=/app/share/applications net.kuribo64.melonds.desktop" - - "install -D icon/melon_256x256.png /app/share/icons/hicolor/256x256/apps/net.kuribo64.melonds.png" + - "desktop-file-install --dir=/app/share/applications net.kuribo64.melonDS.desktop" + - "install -D icon/melon_256x256.png /app/share/icons/hicolor/256x256/apps/net.kuribo64.melonDS.png" diff --git a/flatpak/net.kuribo64.melonds.desktop b/flatpak/net.kuribo64.melonds.desktop deleted file mode 100644 index e91f10d7..00000000 --- a/flatpak/net.kuribo64.melonds.desktop +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=melonDS -Comment=Nintendo DS emulator -Exec=melonDS -Type=Application -Categories=Game; -Terminal=false -Icon=net.kuribo64.melonds diff --git a/melonDS.desktop b/net.kuribo64.melonDS.desktop similarity index 91% rename from melonDS.desktop rename to net.kuribo64.melonDS.desktop index 3dd921ce..c0dafe28 100644 --- a/melonDS.desktop +++ b/net.kuribo64.melonDS.desktop @@ -6,6 +6,6 @@ Exec=melonDS Type=Application Categories=Game;Emulator; Terminal=false -Icon=melon_256x256 +Icon=net.kuribo64.melonDS MimeType=application/x-nintendo-ds-rom; Keywords=emulator;Nintendo;DS;NDS;Nintendo DS; diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index ae270e42..8c3d042f 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -66,7 +66,7 @@ elseif (WIN32) target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi) endif () -install(FILES ../../melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) -install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps) +install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) +install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME net.kuribo64.melonDS.png) install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonds) install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) From c5623c4dcd122278e45a363b655be67d845ecf63 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Thu, 19 Dec 2019 02:52:34 +0100 Subject: [PATCH 42/71] Change the config/data dirs from "melonds" to "melonDS" for consistency. --- src/libui_sdl/CMakeLists.txt | 2 +- src/libui_sdl/Platform.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 8c3d042f..2d384e41 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -68,5 +68,5 @@ endif () install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME net.kuribo64.melonDS.png) -install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonds) +install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp index 8b83a014..cc1b7345 100644 --- a/src/libui_sdl/Platform.cpp +++ b/src/libui_sdl/Platform.cpp @@ -148,7 +148,7 @@ FILE* OpenLocalFile(const char* path, const char* mode) else { // Check user configuration directory - std::string confpath = std::string(g_get_user_config_dir()) + "/melonds/"; + std::string confpath = std::string(g_get_user_config_dir()) + "/melonDS/"; g_mkdir_with_parents(confpath.c_str(), 0755); fullpath = confpath + path; } @@ -158,7 +158,7 @@ FILE* OpenLocalFile(const char* path, const char* mode) FILE* OpenDataFile(const char* path) { - const char* melondir = "melonds"; + const char* melondir = "melonDS"; const char* const* sys_dirs = g_get_system_data_dirs(); const char* user_dir = g_get_user_data_dir(); @@ -238,7 +238,7 @@ FILE* OpenLocalFile(const char* path, const char* mode) emudirpath[pathlen] = '\0'; } - // Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonds on Linux + // Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonDS on Linux FILE* f; @@ -300,7 +300,7 @@ FILE* OpenLocalFile(const char* path, const char* mode) { // Now check XDG_CONFIG_HOME // TODO: check for memory leak there - std::string fullpath = std::string(g_get_user_config_dir()) + "/melonds/" + path; + std::string fullpath = std::string(g_get_user_config_dir()) + "/melonDS/" + path; f = OpenFile(fullpath.c_str(), mode, true); if (f) { delete[] emudirpath; return f; } } From 8172cbc1706874651d227ce72d213fb636e506d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Tue, 10 Dec 2019 20:28:40 -0500 Subject: [PATCH 43/71] Add DoSavestate() function to GBACart_SolarSensor Still empty, but should be implemented along with the rest. --- src/GBACart.cpp | 7 +++++++ src/GBACart.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 7e5e3b58..1cca8120 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -502,6 +502,8 @@ void Reset() void DoSavestate(Savestate* file) { // TODO? + GBACart_SRAM::DoSavestate(file); + GBACart_SolarSensor::DoSavestate(file); } bool LoadROM(const char* path, const char* sram) @@ -625,6 +627,11 @@ void Reset() LightLevel = 0; } +void DoSavestate(Savestate* file) +{ + // TODO? +} + void Process(GBACart::GPIO* gpio) { if (gpio->data & 4) return; // Boktai chip select diff --git a/src/GBACart.h b/src/GBACart.h index 032c4fc1..fd26326c 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -29,6 +29,9 @@ namespace GBACart_SRAM extern u8* SRAM; extern u32 SRAMLength; +void Reset(); +void DoSavestate(Savestate* file); + u8 Read8(u32 addr); u16 Read16(u32 addr); u32 Read32(u32 addr); @@ -74,6 +77,7 @@ namespace GBACart_SolarSensor extern u8 LightLevel; void Reset(); +void DoSavestate(Savestate* file); void Process(GBACart::GPIO* gpio); } From be19e0e8d49485d91c4106bad79daa766f7cb131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Wed, 11 Dec 2019 19:21:59 -0500 Subject: [PATCH 44/71] Make solar sensor hotkeys configurable --- src/libui_sdl/DlgInputConfig.cpp | 6 +++-- src/libui_sdl/PlatformConfig.cpp | 30 ++++++++++++++----------- src/libui_sdl/PlatformConfig.h | 2 ++ src/libui_sdl/main.cpp | 38 +++++++++++++++----------------- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp index a80e2ec7..21394b13 100644 --- a/src/libui_sdl/DlgInputConfig.cpp +++ b/src/libui_sdl/DlgInputConfig.cpp @@ -71,7 +71,9 @@ char hotkeylabels[HK_MAX][32] = "Pause/resume:", "Reset:", "Fast forward:", - "Fast forward (toggle):" + "Fast forward (toggle):", + "Decrease sunlight (Boktai):", + "Increase sunlight (Boktai):" }; int openedmask; @@ -514,7 +516,7 @@ void Open(int type) memcpy(dlg->keymap, Config::HKKeyMapping, sizeof(int)*HK_MAX); memcpy(dlg->joymap, Config::HKJoyMapping, sizeof(int)*HK_MAX); - dlg->win = uiNewWindow("Hotkey config - melonDS", 600, 100, 0, 0, 0); + dlg->win = uiNewWindow("Hotkey config - melonDS", 700, 100, 0, 0, 0); } uiControl(dlg->win)->UserData = dlg; diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp index c8ec19fb..a2eaab94 100644 --- a/src/libui_sdl/PlatformConfig.cpp +++ b/src/libui_sdl/PlatformConfig.cpp @@ -93,25 +93,29 @@ ConfigEntry PlatformConfigFile[] = {"Joy_X", 0, &JoyMapping[10], -1, NULL, 0}, {"Joy_Y", 0, &JoyMapping[11], -1, NULL, 0}, - {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0}, - {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0}, - {"HKKey_Pause", 0, &HKKeyMapping[HK_Pause], -1, NULL, 0}, - {"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0}, - {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0}, - {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0}, + {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0}, + {"HKKey_Pause", 0, &HKKeyMapping[HK_Pause], -1, NULL, 0}, + {"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0}, + {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0}, + {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], 0x4B, NULL, 0}, + {"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], 0x4D, NULL, 0}, - {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0}, - {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0}, - {"HKJoy_Pause", 0, &HKJoyMapping[HK_Pause], -1, NULL, 0}, - {"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0}, - {"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -1, NULL, 0}, - {"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0}, + {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0}, + {"HKJoy_Pause", 0, &HKJoyMapping[HK_Pause], -1, NULL, 0}, + {"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0}, + {"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -1, NULL, 0}, + {"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, NULL, 0}, + {"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, NULL, 0}, {"JoystickID", 0, &JoystickID, 0, NULL, 0}, {"WindowWidth", 0, &WindowWidth, 256, NULL, 0}, {"WindowHeight", 0, &WindowHeight, 384, NULL, 0}, - {"WindowMax", 0, &WindowMaximized, 0, NULL, 0}, + {"WindowMax", 0, &WindowMaximized, 0, NULL, 0}, {"ScreenRotation", 0, &ScreenRotation, 0, NULL, 0}, {"ScreenGap", 0, &ScreenGap, 0, NULL, 0}, diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h index 842e72ae..682b9bc1 100644 --- a/src/libui_sdl/PlatformConfig.h +++ b/src/libui_sdl/PlatformConfig.h @@ -29,6 +29,8 @@ enum HK_Reset, HK_FastForward, HK_FastForwardToggle, + HK_SolarSensorDecrease, + HK_SolarSensorIncrease, HK_MAX }; diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index a96b77a4..38804f69 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -949,6 +949,24 @@ int EmuThreadFunc(void* burp) if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); + if (GBACart::CartInserted && GBACart::HasSolarSensor) + { + if (HotkeyPressed(HK_SolarSensorDecrease)) + { + if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); + } + if (HotkeyPressed(HK_SolarSensorIncrease)) + { + if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); + } + } + if (EmuRunning == 1) { EmuStatus = 1; @@ -1292,26 +1310,6 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) { if (evt->Modifiers == 0x0) UndoStateLoad(); } - else if (evt->Scancode == 0x4B) // Keypad left - { - if (GBACart::CartInserted && GBACart::HasSolarSensor) - { - if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; - char msg[64]; - sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - OSD::AddMessage(0, msg); - } - } - else if (evt->Scancode == 0x4D) // Keypad right - { - if (GBACart::CartInserted && GBACart::HasSolarSensor) - { - if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; - char msg[64]; - sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - OSD::AddMessage(0, msg); - } - } for (int i = 0; i < 12; i++) if (EventMatchesKey(evt, Config::KeyMapping[i], false)) From 2abdcc54dd159a89a2545e8c6c34e1f0687a64f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Thu, 19 Dec 2019 00:12:36 -0500 Subject: [PATCH 45/71] Implement DoSavestate() for GBACart classes Admittedly untested. --- src/GBACart.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 1cca8120..1829ca7c 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -89,7 +89,34 @@ void Reset() void DoSavestate(Savestate* file) { - // TODO? + file->Section("GBCS"); // Game Boy [Advance] Cart Save + + // logic mostly copied from NDSCart_SRAM + + u32 oldlen = SRAMLength; + + file->Var32(&SRAMLength); + if (SRAMLength != oldlen) + { + printf("savestate (GBA): VERY BAD!!!! SRAM LENGTH DIFFERENT. %d -> %d\n", oldlen, SRAMLength); + printf("oh well. loading it anyway. iojkjkojo\n"); + + if (oldlen) delete[] SRAM; + if (SRAMLength) SRAM = new u8[SRAMLength]; + } + if (SRAMLength) + { + file->VarArray(SRAM, SRAMLength); + } + + // persist some extra state info + file->Var8(&SRAMFlashState.bank); + file->Var8(&SRAMFlashState.cmd); + file->Var8(&SRAMFlashState.device); + file->Var8(&SRAMFlashState.manufacturer); + file->Var8(&SRAMFlashState.state); + + file->Var8((u8*)&SRAMType); } void LoadSave(const char* path) @@ -501,9 +528,43 @@ void Reset() void DoSavestate(Savestate* file) { - // TODO? + file->Section("GBAC"); // Game Boy Advance Cartridge + + // logic mostly copied from NDSCart + + // first we need to reload the cart itself, + // since unlike with DS, it's not loaded in advance + + u32 oldlen = CartROMSize; + + file->Var32(&CartROMSize); + if (!CartROMSize) return; // no GBA cartridge state? nothing to do here. + + if (CartROMSize != oldlen) // loading a differently-sized cartridge + { + if (oldlen) delete[] CartROM; + CartROM = new u8[CartROMSize]; + } + + // why yes, let's save the whole GBA cart in the state + // TODO: let's maybe not? + + file->VarArray(CartROM, CartROMSize); + + CartInserted = true; // known, because CartROMSize > 0 + file->Var32(&CartCRC); + file->Var32(&CartID); + + file->Var8((u8*)&HasSolarSensor); + + file->Var16(&CartGPIO.control); + file->Var16(&CartGPIO.data); + file->Var16(&CartGPIO.direction); + + // now do the rest + GBACart_SRAM::DoSavestate(file); - GBACart_SolarSensor::DoSavestate(file); + if (HasSolarSensor) GBACart_SolarSensor::DoSavestate(file); } bool LoadROM(const char* path, const char* sram) @@ -629,7 +690,10 @@ void Reset() void DoSavestate(Savestate* file) { - // TODO? + file->Var8((u8*)&LightEdge); + file->Var8(&LightCounter); + file->Var8(&LightSample); + file->Var8(&LightLevel); } void Process(GBACart::GPIO* gpio) From a57ba1368e151484908052d696aa90f28928cfe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 22 Dec 2019 11:45:11 -0500 Subject: [PATCH 46/71] Skip saving/loading GBA flash state if SRAM is null --- src/GBACart.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 1829ca7c..f6bed861 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -96,18 +96,24 @@ void DoSavestate(Savestate* file) u32 oldlen = SRAMLength; file->Var32(&SRAMLength); + if (SRAMLength != oldlen) { - printf("savestate (GBA): VERY BAD!!!! SRAM LENGTH DIFFERENT. %d -> %d\n", oldlen, SRAMLength); - printf("oh well. loading it anyway. iojkjkojo\n"); - + // reallocate save memory if (oldlen) delete[] SRAM; if (SRAMLength) SRAM = new u8[SRAMLength]; } if (SRAMLength) { + // fill save memory if data is present file->VarArray(SRAM, SRAMLength); } + else + { + // no save data, nothing left to do + SRAMType = SaveType::S_NULL; + return; + } // persist some extra state info file->Var8(&SRAMFlashState.bank); From f380767fab219df087488a4e4e8a5eab47efb94c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 22 Dec 2019 13:58:27 -0500 Subject: [PATCH 47/71] Only store the GBA ROM header in save states Also fix some potential crashes due to SRAM state not being cleared correctly on state load. --- src/GBACart.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index f6bed861..7753482c 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -110,8 +110,11 @@ void DoSavestate(Savestate* file) } else { - // no save data, nothing left to do + // no save data, clear the current state SRAMType = SaveType::S_NULL; + if (SRAMFile) fclose(SRAMFile); + SRAM = NULL; + SRAMFile = NULL; return; } @@ -541,21 +544,40 @@ void DoSavestate(Savestate* file) // first we need to reload the cart itself, // since unlike with DS, it's not loaded in advance - u32 oldlen = CartROMSize; - file->Var32(&CartROMSize); if (!CartROMSize) return; // no GBA cartridge state? nothing to do here. - if (CartROMSize != oldlen) // loading a differently-sized cartridge + u32 oldCRC = CartCRC; + file->Var32(&CartCRC); + if (CartCRC != oldCRC) { - if (oldlen) delete[] CartROM; + // delete and reallocate ROM so that it is zero-padded to its full length + if (CartROM) delete[] CartROM; CartROM = new u8[CartROMSize]; + + // clear the SRAM file handle; writes will not be committed + if (GBACart_SRAM::SRAMFile) + { + fclose(GBACart_SRAM::SRAMFile); + GBACart_SRAM::SRAMFile = NULL; + } } - // why yes, let's save the whole GBA cart in the state - // TODO: let's maybe not? - - file->VarArray(CartROM, CartROMSize); + // only save/load the cartridge header + // + // GBA connectivity on DS mainly involves identifying the title currently + // inserted, reading save data, and issuing commands intercepted here + // (e.g. solar sensor signals). we don't know of any case where GBA ROM is + // read directly from DS software. therefore, it is more practical, both + // from the development and user experience perspectives, to avoid dealing + // with file dependencies, and store a small portion of ROM data that should + // satisfy the needs of all known software that reads from the GBA slot. + // + // note: in case of a state load, only the cartridge header is restored, but + // the rest of the ROM data is only cleared (zero-initialized) if the CRC + // differs. Therefore, loading the GBA cartridge associated with the save state + // in advance will maintain access to the full ROM contents. + file->VarArray(CartROM, 192); CartInserted = true; // known, because CartROMSize > 0 file->Var32(&CartCRC); From 22d11209b0466e3c852da543ddfc512b66735bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 22 Dec 2019 15:49:23 -0500 Subject: [PATCH 48/71] Split GBA Reset and Eject logic into two sets This allows solving some crashes and provides more flexibility in how GBA cartridges change state between soft and hard resets. Since save states including GBA data do not carry over the original save file path, and the GBA cartridge is being reset along with the other parts of the system, this is needed to avoid losing the GBA state on reset following a state load, while preserving the behavior where cartridges are ejected when calling Stop(). --- src/GBACart.cpp | 41 +++++++++++++++++++++++++++++++++-------- src/GBACart.h | 2 ++ src/libui_sdl/main.cpp | 22 ++++++++++++++++++++-- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/GBACart.cpp b/src/GBACart.cpp index 7753482c..4d44d3a1 100644 --- a/src/GBACart.cpp +++ b/src/GBACart.cpp @@ -76,10 +76,14 @@ void DeInit() } void Reset() +{ + // do nothing, we don't want to clear GBA SRAM on reset +} + +void Eject() { if (SRAMFile) fclose(SRAMFile); if (SRAM) delete[] SRAM; - SRAM = NULL; SRAMFile = NULL; SRAMLength = 0; @@ -524,17 +528,32 @@ void DeInit() void Reset() { - CartInserted = false; - HasSolarSensor = false; - if (CartROM) delete[] CartROM; - CartROM = NULL; - CartROMSize = 0; - CartGPIO = {}; + // Do not reset cartridge ROM. + // Prefer keeping the inserted cartridge on reset. + // This allows resetting a DS game without losing GBA state, + // and resetting to firmware without the slot being emptied. + // The Stop function will clear the cartridge state via Eject(). GBACart_SRAM::Reset(); GBACart_SolarSensor::Reset(); } +void Eject() +{ + if (CartROM) delete[] CartROM; + + CartInserted = false; + HasSolarSensor = false; + CartROM = NULL; + CartROMSize = 0; + CartCRC = NULL; + CartID = NULL; + CartGPIO = {}; + + GBACart_SRAM::Eject(); + Reset(); +} + void DoSavestate(Savestate* file) { file->Section("GBAC"); // Game Boy Advance Cartridge @@ -545,10 +564,16 @@ void DoSavestate(Savestate* file) // since unlike with DS, it's not loaded in advance file->Var32(&CartROMSize); - if (!CartROMSize) return; // no GBA cartridge state? nothing to do here. + if (!CartROMSize) // no GBA cartridge state? nothing to do here + { + // do eject the cartridge if something is inserted + Eject(); + return; + } u32 oldCRC = CartCRC; file->Var32(&CartCRC); + if (CartCRC != oldCRC) { // delete and reallocate ROM so that it is zero-padded to its full length diff --git a/src/GBACart.h b/src/GBACart.h index fd26326c..96a05b8b 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -57,10 +57,12 @@ extern bool CartInserted; extern bool HasSolarSensor; extern u8* CartROM; extern u32 CartROMSize; +extern u32 CartCRC; bool Init(); void DeInit(); void Reset(); +void Eject(); void DoSavestate(Savestate* file); bool LoadROM(const char* path, const char* sram); diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 38804f69..af69f8e3 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1694,6 +1694,7 @@ void Stop(bool internal) RunningSomething = false; // eject any inserted GBA cartridge + GBACart::Eject(); ROMPath[1][0] = '\0'; uiWindowSetTitle(MainWindow, "melonDS " MELONDS_VERSION); @@ -1834,6 +1835,8 @@ void LoadState(int slot) return; } + u32 oldGBACartCRC = GBACart::CartCRC; + // backup Savestate* backup = new Savestate("timewarp.mln", true); NDS::DoSavestate(backup); @@ -1870,9 +1873,24 @@ void LoadState(int slot) NDS::RelocateSave(SRAMPath[0], false); } + bool loadedPartialGBAROM = false; + + // in case we have a GBA cart inserted, and the GBA ROM changes + // due to having loaded a save state, we do not want to reload + // the previous cartridge on reset, or commit writes to any + // loaded save file. therefore, their paths are "nulled". + if (GBACart::CartInserted && GBACart::CartCRC != oldGBACartCRC) + { + ROMPath[1][0] = '\0'; + SRAMPath[1][0] = '\0'; + loadedPartialGBAROM = true; + } + char msg[64]; - if (slot > 0) sprintf(msg, "State loaded from slot %d", slot); - else sprintf(msg, "State loaded from file"); + if (slot > 0) sprintf(msg, "State loaded from slot %d%s", + slot, loadedPartialGBAROM ? " (GBA ROM header only)" : ""); + else sprintf(msg, "State loaded from file%s", + loadedPartialGBAROM ? " (GBA ROM header only)" : ""); OSD::AddMessage(0, msg); SavestateLoaded = true; From da0afbde8823f37af92a0f1cd0ad2ad7a5fa7d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20=E2=9B=85?= <3259076+KAMiKAZOW@users.noreply.github.com> Date: Thu, 30 Jan 2020 17:25:08 +0100 Subject: [PATCH 49/71] Use different icon location "pixmaps" is the deprecated, legacy-only location. "hicolor" is the current, proper location that supports multiple resolutions which we now use --- src/libui_sdl/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 2d384e41..8c8467bd 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -67,6 +67,11 @@ elseif (WIN32) endif () install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) -install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_32x32.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/32x32/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png) install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) From eaaac6aa3b8f7bfb42e09727a7d7cf4a5aec78f4 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 2 Feb 2020 10:49:09 -0600 Subject: [PATCH 50/71] Fix CodeBlocks build --- melonDS.cbp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/melonDS.cbp b/melonDS.cbp index fb42cb47..7834a0e1 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -119,6 +119,8 @@ + + @@ -277,10 +279,6 @@ - - - - - + From 106b9a6f24958d33a0f909b3ceb1abf50570b82d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 14 Feb 2020 19:26:52 +0100 Subject: [PATCH 51/71] lay base for AR cheatzorz. baahahhhh --- melonDS.cbp | 8 ++++++- src/AREngine.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++ src/AREngine.h | 33 ++++++++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/GPU.cpp | 5 ++++- src/NDS.cpp | 7 ++++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 src/AREngine.cpp create mode 100644 src/AREngine.h diff --git a/melonDS.cbp b/melonDS.cbp index 7834a0e1..58f86a63 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -100,6 +100,8 @@ + + @@ -279,6 +281,10 @@ - + + + + + diff --git a/src/AREngine.cpp b/src/AREngine.cpp new file mode 100644 index 00000000..9a87d5d7 --- /dev/null +++ b/src/AREngine.cpp @@ -0,0 +1,55 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "NDS.h" +#include "AREngine.h" + + +namespace AREngine +{ + +// TODO: more sensible size for this? allocate on demand? +u32 CheatCodes[2 * 1024]; + + +bool Init() +{ + return true; +} + +void DeInit() +{ + // +} + +void Reset() +{ + memset(CheatCodes, 0, sizeof(u32)*2*1024); + + // TODO: acquire codes from a sensible source! +} + + +void RunCheats() +{ + // bahahah +} + +} diff --git a/src/AREngine.h b/src/AREngine.h new file mode 100644 index 00000000..afaf5986 --- /dev/null +++ b/src/AREngine.h @@ -0,0 +1,33 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef ARENGINE_H +#define ARENGINE_H + +namespace AREngine +{ + +bool Init(); +void DeInit(); +void Reset(); + +void RunCheats(); + +} + +#endif // ARENGINE_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03a4bfe0..3b760ba8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ project(core) add_library(core STATIC + AREngine.cpp ARM.cpp ARMInterpreter.cpp ARMInterpreter_ALU.cpp diff --git a/src/GPU.cpp b/src/GPU.cpp index 071d5f65..1ac9f50e 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -20,7 +20,7 @@ #include #include "NDS.h" #include "GPU.h" -u64 vbltime; +#include "AREngine.h" namespace GPU { @@ -986,6 +986,9 @@ void StartScanline(u32 line) GPU2D_A->VBlank(); GPU2D_B->VBlank(); GPU3D::VBlank(); + + // TODO: verify when AR cheats actually run! + AREngine::RunCheats(); } else if (VCount == 144) { diff --git a/src/NDS.cpp b/src/NDS.cpp index 47f96c90..0198ea3b 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -30,6 +30,7 @@ #include "SPI.h" #include "RTC.h" #include "Wifi.h" +#include "AREngine.h" #include "Platform.h" @@ -177,6 +178,8 @@ bool Init() if (!RTC::Init()) return false; if (!Wifi::Init()) return false; + if (!AREngine::Init()) return false; + return true; } @@ -198,6 +201,8 @@ void DeInit() SPI::DeInit(); RTC::DeInit(); Wifi::DeInit(); + + AREngine::DeInit(); } @@ -500,6 +505,8 @@ void Reset() SPI::Reset(); RTC::Reset(); Wifi::Reset(); + + AREngine::Reset(); } void Stop() From d0b27178f148a192207eceef8b38737d059b68ad Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 14 Feb 2020 20:13:06 +0100 Subject: [PATCH 52/71] miserable, feeble little attempt at executing AR codes. also, it's hardcoded. probably not a good thing. --- src/AREngine.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 9a87d5d7..3049ecbc 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -25,8 +25,16 @@ namespace AREngine { +typedef struct +{ + u32 Code[2 * 64]; // TODO: more sensible size for this? allocate on demand? + bool Enabled; + +} CheatEntry; + // TODO: more sensible size for this? allocate on demand? -u32 CheatCodes[2 * 1024]; +CheatEntry CheatCodes[64]; +u32 NumCheatCodes; bool Init() @@ -41,15 +49,98 @@ void DeInit() void Reset() { - memset(CheatCodes, 0, sizeof(u32)*2*1024); + memset(CheatCodes, 0, sizeof(CheatCodes)); + NumCheatCodes = 0; // TODO: acquire codes from a sensible source! + CheatEntry* entry = &CheatCodes[0]; + u32* ptr = &entry->Code[0]; +#define TEMP_PUTCODE(a, b) *ptr++ = a; *ptr++ = b; + // NSMBDS EUR - giant fucking Mario + TEMP_PUTCODE(0x1209DBD0, 0x0000027C); + TEMP_PUTCODE(0x2209DBC0, 0x00000003); + TEMP_PUTCODE(0x94000130, 0xFFFD0000); + TEMP_PUTCODE(0x1209DBD0, 0x00000000); + TEMP_PUTCODE(0x2209DBC0, 0x00000003); + entry->Enabled = true; + NumCheatCodes++; } +#define case16(x) \ + case ((x)+0x00): case ((x)+0x01): case ((x)+0x02): case ((x)+0x03): \ + case ((x)+0x04): case ((x)+0x05): case ((x)+0x06): case ((x)+0x07): \ + case ((x)+0x08): case ((x)+0x09): case ((x)+0x0A): case ((x)+0x0B): \ + case ((x)+0x0C): case ((x)+0x0D): case ((x)+0x0E): case ((x)+0x0F) + +void RunCheat(CheatEntry* entry) +{ + u32* code = &entry->Code[0]; + + u32 cond = 1; + u32 condstack = 0; + + for (;;) + { + u32 a = *code++; + u32 b = *code++; + if ((a|b) == 0) break; + + u8 op = a >> 24; + + if ((op < 0xD0 && op != 0xC5) || op > 0xD2) + { + if (!cond) + { + // TODO: skip parameters for opcode Ex + continue; + } + } + + switch (op) + { + case16(0x00): // 32-bit write + NDS::ARM7Write32(a & 0x0FFFFFFF, b); + break; + + case16(0x10): // 16-bit write + NDS::ARM7Write16(a & 0x0FFFFFFF, b & 0xFFFF); + break; + + case16(0x20): // 8-bit write + NDS::ARM7Write8(a & 0x0FFFFFFF, b & 0xFF); + break; + + case16(0x90): // IF b.l = ((~b.h) & u16[a]) + { + condstack <<= 1; + condstack |= cond; + + u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); + u16 chk = ~(b >> 16); + chk &= val; + + cond = ((b & 0xFFFF) == chk) ? 1:0; + } + break; + + default: + printf("!! bad AR opcode %08X %08X\n", a, b); + return; + } + } +} + void RunCheats() { - // bahahah + // TODO: make it disableable in general + + for (u32 i = 0; i < NumCheatCodes; i++) + { + CheatEntry* entry = &CheatCodes[i]; + if (entry->Enabled) + RunCheat(entry); + } } } From 83f8e11bc13f6dcacf72d9be49054da5b0a83566 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 14 Feb 2020 20:18:08 +0100 Subject: [PATCH 53/71] update copyright years --- melon.rc | 2 +- src/AREngine.cpp | 2 +- src/AREngine.h | 2 +- src/ARM.cpp | 2 +- src/ARM.h | 2 +- src/ARMInterpreter.cpp | 2 +- src/ARMInterpreter.h | 2 +- src/ARMInterpreter_ALU.cpp | 2 +- src/ARMInterpreter_ALU.h | 2 +- src/ARMInterpreter_Branch.cpp | 2 +- src/ARMInterpreter_Branch.h | 2 +- src/ARMInterpreter_LoadStore.cpp | 2 +- src/ARMInterpreter_LoadStore.h | 2 +- src/ARM_InstrTable.h | 2 +- src/CP15.cpp | 2 +- src/CRC32.cpp | 2 +- src/CRC32.h | 2 +- src/Config.cpp | 2 +- src/Config.h | 2 +- src/DMA.cpp | 2 +- src/DMA.h | 2 +- src/FIFO.h | 2 +- src/GPU.cpp | 2 +- src/GPU.h | 2 +- src/GPU2D.cpp | 2 +- src/GPU2D.h | 2 +- src/GPU3D.cpp | 2 +- src/GPU3D.h | 2 +- src/GPU3D_OpenGL.cpp | 2 +- src/GPU3D_OpenGL_shaders.h | 2 +- src/GPU3D_Soft.cpp | 2 +- src/NDS.cpp | 2 +- src/NDS.h | 2 +- src/NDSCart.h | 2 +- src/OpenGLSupport.cpp | 2 +- src/OpenGLSupport.h | 2 +- src/Platform.h | 2 +- src/RTC.cpp | 2 +- src/RTC.h | 2 +- src/SPI.cpp | 2 +- src/SPI.h | 2 +- src/SPU.cpp | 2 +- src/SPU.h | 2 +- src/Savestate.cpp | 2 +- src/Savestate.h | 2 +- src/Wifi.cpp | 2 +- src/Wifi.h | 2 +- src/WifiAP.cpp | 2 +- src/WifiAP.h | 2 +- src/libui_sdl/DlgAudioSettings.cpp | 2 +- src/libui_sdl/DlgAudioSettings.h | 2 +- src/libui_sdl/DlgEmuSettings.cpp | 2 +- src/libui_sdl/DlgEmuSettings.h | 2 +- src/libui_sdl/DlgInputConfig.cpp | 2 +- src/libui_sdl/DlgInputConfig.h | 2 +- src/libui_sdl/DlgVideoSettings.cpp | 2 +- src/libui_sdl/DlgVideoSettings.h | 2 +- src/libui_sdl/DlgWifiSettings.cpp | 2 +- src/libui_sdl/DlgWifiSettings.h | 2 +- src/libui_sdl/LAN_PCap.cpp | 22 +++++++++++----------- src/libui_sdl/LAN_PCap.h | 2 +- src/libui_sdl/LAN_Socket.cpp | 2 +- src/libui_sdl/LAN_Socket.h | 2 +- src/libui_sdl/MelonCap.cpp | 2 +- src/libui_sdl/MelonCap.h | 2 +- src/libui_sdl/OSD.cpp | 2 +- src/libui_sdl/OSD.h | 2 +- src/libui_sdl/Platform.cpp | 4 ++-- src/libui_sdl/PlatformConfig.cpp | 2 +- src/libui_sdl/PlatformConfig.h | 2 +- src/libui_sdl/font.h | 2 +- src/libui_sdl/main.cpp | 4 ++-- src/libui_sdl/main_shaders.h | 2 +- src/types.h | 2 +- src/version.h | 2 +- 75 files changed, 87 insertions(+), 87 deletions(-) diff --git a/melon.rc b/melon.rc index e2d8dc28..c6ee672e 100644 --- a/melon.rc +++ b/melon.rc @@ -18,7 +18,7 @@ FILETYPE VFT_APP VALUE "FileVersion", "0.8.3" VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon." VALUE "InternalName", "SDnolem" - VALUE "LegalCopyright", "2016-2019 Arisotura & co." + VALUE "LegalCopyright", "2016-2020 Arisotura & co." VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "zafkflzdasd.exe" VALUE "ProductName", "melonDS" diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 3049ecbc..45684738 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/AREngine.h b/src/AREngine.h index afaf5986..a78405f2 100644 --- a/src/AREngine.h +++ b/src/AREngine.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARM.cpp b/src/ARM.cpp index f50af259..43838ca0 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARM.h b/src/ARM.h index dcff4777..b9f5d892 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index d3f66d82..347fa1e9 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter.h b/src/ARMInterpreter.h index 1802bccd..72442381 100644 --- a/src/ARMInterpreter.h +++ b/src/ARMInterpreter.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter_ALU.cpp b/src/ARMInterpreter_ALU.cpp index d60d8f87..545667ad 100644 --- a/src/ARMInterpreter_ALU.cpp +++ b/src/ARMInterpreter_ALU.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter_ALU.h b/src/ARMInterpreter_ALU.h index 0f7fe9ba..7f889ded 100644 --- a/src/ARMInterpreter_ALU.h +++ b/src/ARMInterpreter_ALU.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter_Branch.cpp b/src/ARMInterpreter_Branch.cpp index 6d1cf174..91cf5bb6 100644 --- a/src/ARMInterpreter_Branch.cpp +++ b/src/ARMInterpreter_Branch.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter_Branch.h b/src/ARMInterpreter_Branch.h index 43347e30..757092f7 100644 --- a/src/ARMInterpreter_Branch.h +++ b/src/ARMInterpreter_Branch.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index 1d1fc6d2..5b053852 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARMInterpreter_LoadStore.h b/src/ARMInterpreter_LoadStore.h index ab69b158..09768a66 100644 --- a/src/ARMInterpreter_LoadStore.h +++ b/src/ARMInterpreter_LoadStore.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/ARM_InstrTable.h b/src/ARM_InstrTable.h index 2e4a7072..86d7d5a8 100644 --- a/src/ARM_InstrTable.h +++ b/src/ARM_InstrTable.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/CP15.cpp b/src/CP15.cpp index cf0ece9d..c1f46bcd 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/CRC32.cpp b/src/CRC32.cpp index 5cb47e2e..97af7212 100644 --- a/src/CRC32.cpp +++ b/src/CRC32.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/CRC32.h b/src/CRC32.h index 449457ac..a74fa8d5 100644 --- a/src/CRC32.h +++ b/src/CRC32.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Config.cpp b/src/Config.cpp index 58aef58b..f558ef64 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Config.h b/src/Config.h index 363df703..84fd57bc 100644 --- a/src/Config.h +++ b/src/Config.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DMA.cpp b/src/DMA.cpp index 51ce8255..ae3fdd7f 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DMA.h b/src/DMA.h index 3146ef19..2e7678cb 100644 --- a/src/DMA.h +++ b/src/DMA.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/FIFO.h b/src/FIFO.h index a9e9ed80..e2ea644b 100644 --- a/src/FIFO.h +++ b/src/FIFO.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU.cpp b/src/GPU.cpp index 1ac9f50e..633cbd71 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU.h b/src/GPU.h index 7e7a9d12..661a7d91 100644 --- a/src/GPU.h +++ b/src/GPU.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 30a6d45f..1c6cf0cf 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU2D.h b/src/GPU2D.h index 6675ce7d..c4bd2f92 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 1c3fbee0..52bc10f9 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU3D.h b/src/GPU3D.h index fd524887..1fd3383e 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index 6abb1abc..b1bcaa11 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU3D_OpenGL_shaders.h b/src/GPU3D_OpenGL_shaders.h index 2545ee0d..5722ca5f 100644 --- a/src/GPU3D_OpenGL_shaders.h +++ b/src/GPU3D_OpenGL_shaders.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 193d1983..8397898d 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/NDS.cpp b/src/NDS.cpp index 0198ea3b..713e8ac4 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/NDS.h b/src/NDS.h index 16c42efd..4e41520e 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/NDSCart.h b/src/NDSCart.h index 0dc42204..4167aa64 100644 --- a/src/NDSCart.h +++ b/src/NDSCart.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp index 59424b43..f91af9bf 100644 --- a/src/OpenGLSupport.cpp +++ b/src/OpenGLSupport.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h index a08bcdf1..5f92580b 100644 --- a/src/OpenGLSupport.h +++ b/src/OpenGLSupport.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Platform.h b/src/Platform.h index dfe83d06..b6effdc4 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/RTC.cpp b/src/RTC.cpp index 83e5bdbe..0d80b2ca 100644 --- a/src/RTC.cpp +++ b/src/RTC.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/RTC.h b/src/RTC.h index 7f904a69..05cd80f8 100644 --- a/src/RTC.h +++ b/src/RTC.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/SPI.cpp b/src/SPI.cpp index 759bbd90..1a5873e1 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/SPI.h b/src/SPI.h index 9b987caa..086de1a6 100644 --- a/src/SPI.h +++ b/src/SPI.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/SPU.cpp b/src/SPU.cpp index 9d5f04f0..710533ef 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/SPU.h b/src/SPU.h index 53a8e0a3..74a44710 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Savestate.cpp b/src/Savestate.cpp index fff2ec77..cb3d6a52 100644 --- a/src/Savestate.cpp +++ b/src/Savestate.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Savestate.h b/src/Savestate.h index ef86f3ce..60d00e75 100644 --- a/src/Savestate.h +++ b/src/Savestate.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Wifi.cpp b/src/Wifi.cpp index dbe836f7..ab827244 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/Wifi.h b/src/Wifi.h index c97264b0..dd3eeb34 100644 --- a/src/Wifi.h +++ b/src/Wifi.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp index 4d4ee193..3a5de370 100644 --- a/src/WifiAP.cpp +++ b/src/WifiAP.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/WifiAP.h b/src/WifiAP.h index e62c0fb2..97946a50 100644 --- a/src/WifiAP.h +++ b/src/WifiAP.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgAudioSettings.cpp b/src/libui_sdl/DlgAudioSettings.cpp index d6493219..43836ae9 100644 --- a/src/libui_sdl/DlgAudioSettings.cpp +++ b/src/libui_sdl/DlgAudioSettings.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgAudioSettings.h b/src/libui_sdl/DlgAudioSettings.h index f058c25b..7a5afccd 100644 --- a/src/libui_sdl/DlgAudioSettings.h +++ b/src/libui_sdl/DlgAudioSettings.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgEmuSettings.cpp b/src/libui_sdl/DlgEmuSettings.cpp index 768560d5..c50f2169 100644 --- a/src/libui_sdl/DlgEmuSettings.cpp +++ b/src/libui_sdl/DlgEmuSettings.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgEmuSettings.h b/src/libui_sdl/DlgEmuSettings.h index baff7ce1..d937448b 100644 --- a/src/libui_sdl/DlgEmuSettings.h +++ b/src/libui_sdl/DlgEmuSettings.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp index 21394b13..f4245b4f 100644 --- a/src/libui_sdl/DlgInputConfig.cpp +++ b/src/libui_sdl/DlgInputConfig.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgInputConfig.h b/src/libui_sdl/DlgInputConfig.h index 94c73250..89ac034e 100644 --- a/src/libui_sdl/DlgInputConfig.h +++ b/src/libui_sdl/DlgInputConfig.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgVideoSettings.cpp b/src/libui_sdl/DlgVideoSettings.cpp index ff88ba8e..1062be1c 100644 --- a/src/libui_sdl/DlgVideoSettings.cpp +++ b/src/libui_sdl/DlgVideoSettings.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgVideoSettings.h b/src/libui_sdl/DlgVideoSettings.h index 25a938fa..17072e0d 100644 --- a/src/libui_sdl/DlgVideoSettings.h +++ b/src/libui_sdl/DlgVideoSettings.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgWifiSettings.cpp b/src/libui_sdl/DlgWifiSettings.cpp index 09080a0f..d1ce8bd7 100644 --- a/src/libui_sdl/DlgWifiSettings.cpp +++ b/src/libui_sdl/DlgWifiSettings.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/DlgWifiSettings.h b/src/libui_sdl/DlgWifiSettings.h index 466ce10f..a12cbfd0 100644 --- a/src/libui_sdl/DlgWifiSettings.h +++ b/src/libui_sdl/DlgWifiSettings.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp index 44af0a36..ce278bcb 100644 --- a/src/libui_sdl/LAN_PCap.cpp +++ b/src/libui_sdl/LAN_PCap.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. @@ -133,7 +133,7 @@ bool Init(bool open_adapter) return false; } } - + PCapAdapter = NULL; PacketLen = 0; RXNum = 0; @@ -172,7 +172,7 @@ bool Init(bool open_adapter) #else strncpy(adata->DeviceName, dev->name, 127); adata->DeviceName[127] = '\0'; - + strncpy(adata->FriendlyName, adata->DeviceName, 127); adata->FriendlyName[127] = '\0'; #endif // __WIN32__ @@ -250,7 +250,7 @@ bool Init(bool open_adapter) printf("getifaddrs() shat itself :(\n"); return false; } - + for (int i = 0; i < NumAdapters; i++) { adata = &Adapters[i]; @@ -262,14 +262,14 @@ bool Init(bool open_adapter) curaddr = curaddr->ifa_next; continue; } - + if (!curaddr->ifa_addr) { - printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); + printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); curaddr = curaddr->ifa_next; continue; } - + u16 af = curaddr->ifa_addr->sa_family; if (af == AF_INET) { @@ -279,23 +279,23 @@ bool Init(bool open_adapter) else if (af == AF_PACKET) { struct sockaddr_ll* sa = (sockaddr_ll*)curaddr->ifa_addr; - if (sa->sll_halen != 6) + if (sa->sll_halen != 6) printf("weird MAC length %d for %s\n", sa->sll_halen, curaddr->ifa_name); else memcpy(adata->MAC, sa->sll_addr, 6); } - + curaddr = curaddr->ifa_next; } } - + freeifaddrs(addrs); #endif // __WIN32__ if (!open_adapter) return true; if (PCapAdapter) pcap_close(PCapAdapter); - + // open pcap device PCapAdapterData = &Adapters[0]; for (int i = 0; i < NumAdapters; i++) diff --git a/src/libui_sdl/LAN_PCap.h b/src/libui_sdl/LAN_PCap.h index 6ca43e89..250b8e90 100644 --- a/src/libui_sdl/LAN_PCap.h +++ b/src/libui_sdl/LAN_PCap.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/LAN_Socket.cpp b/src/libui_sdl/LAN_Socket.cpp index a9f2cd7a..c6fbd4b6 100644 --- a/src/libui_sdl/LAN_Socket.cpp +++ b/src/libui_sdl/LAN_Socket.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/LAN_Socket.h b/src/libui_sdl/LAN_Socket.h index a0abe45e..8453a5f4 100644 --- a/src/libui_sdl/LAN_Socket.h +++ b/src/libui_sdl/LAN_Socket.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp index fde440ae..6e45bf5f 100644 --- a/src/libui_sdl/MelonCap.cpp +++ b/src/libui_sdl/MelonCap.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/MelonCap.h b/src/libui_sdl/MelonCap.h index 1185dea0..33a391bd 100644 --- a/src/libui_sdl/MelonCap.h +++ b/src/libui_sdl/MelonCap.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/OSD.cpp b/src/libui_sdl/OSD.cpp index bd44e99f..a01e39b9 100644 --- a/src/libui_sdl/OSD.cpp +++ b/src/libui_sdl/OSD.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/OSD.h b/src/libui_sdl/OSD.h index afe403ff..12294ea7 100644 --- a/src/libui_sdl/OSD.h +++ b/src/libui_sdl/OSD.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp index cc1b7345..54fa568a 100644 --- a/src/libui_sdl/Platform.cpp +++ b/src/libui_sdl/Platform.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. @@ -189,7 +189,7 @@ FILE* OpenDataFile(const char* path) FILE* f = fopen(path, "rb"); if (f) return f; - + return NULL; } diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp index a2eaab94..f78b1957 100644 --- a/src/libui_sdl/PlatformConfig.cpp +++ b/src/libui_sdl/PlatformConfig.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h index 682b9bc1..9e02862f 100644 --- a/src/libui_sdl/PlatformConfig.h +++ b/src/libui_sdl/PlatformConfig.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/font.h b/src/libui_sdl/font.h index 8647b7a5..f2e4f878 100644 --- a/src/libui_sdl/font.h +++ b/src/libui_sdl/font.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 130c8f91..9d52985e 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. @@ -2760,7 +2760,7 @@ int main(int argc, char** argv) char* locationName = EmuDirectory; #endif char msgboxtext[512]; - sprintf(msgboxtext, + sprintf(msgboxtext, "One or more of the following required files don't exist or couldn't be accessed:\n\n" "bios7.bin -- ARM7 BIOS\n" "bios9.bin -- ARM9 BIOS\n" diff --git a/src/libui_sdl/main_shaders.h b/src/libui_sdl/main_shaders.h index 6504520f..22d4dd9d 100644 --- a/src/libui_sdl/main_shaders.h +++ b/src/libui_sdl/main_shaders.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/types.h b/src/types.h index 9b1edc9f..234d4c04 100644 --- a/src/types.h +++ b/src/types.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/version.h b/src/version.h index 2e18ba91..62506011 100644 --- a/src/version.h +++ b/src/version.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. From eb44833171e3ce4da049a37a0bd639b71e618215 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 14 Feb 2020 21:19:36 +0100 Subject: [PATCH 54/71] well, more AR shito --- src/AREngine.cpp | 152 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 146 insertions(+), 6 deletions(-) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 45684738..d74d5331 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -53,10 +53,10 @@ void Reset() NumCheatCodes = 0; // TODO: acquire codes from a sensible source! +#define TEMP_PUTCODE(a, b) *ptr++ = a; *ptr++ = b; CheatEntry* entry = &CheatCodes[0]; u32* ptr = &entry->Code[0]; -#define TEMP_PUTCODE(a, b) *ptr++ = a; *ptr++ = b; - // NSMBDS EUR - giant fucking Mario + /*// NSMBDS EUR - giant fucking Mario TEMP_PUTCODE(0x1209DBD0, 0x0000027C); TEMP_PUTCODE(0x2209DBC0, 0x00000003); TEMP_PUTCODE(0x94000130, 0xFFFD0000); @@ -64,6 +64,44 @@ void Reset() TEMP_PUTCODE(0x2209DBC0, 0x00000003); entry->Enabled = true; NumCheatCodes++; + + entry = &CheatCodes[1]; + ptr = &entry->Code[0];*/ + // NSMBDS EUR - jump to the sky + /*TEMP_PUTCODE(0x9209DC90, 0xFFFD0002); + TEMP_PUTCODE(0x920DC910, 0x00000000); + TEMP_PUTCODE(0x021C1944, 0x00004000); + TEMP_PUTCODE(0xD2000000, 0x00000000); + TEMP_PUTCODE(0x9209DC90, 0xFFFE0001); + TEMP_PUTCODE(0x920DC910, 0x00000000); + TEMP_PUTCODE(0x021C1944, 0x00004000); + TEMP_PUTCODE(0xD2000000, 0x00000000);*/ + // SM64DS EUR redcoin + /*TEMP_PUTCODE(0x0210CC3E, 0x00000121); + TEMP_PUTCODE(0x5209F30C, 0x00000008); + TEMP_PUTCODE(0x0209F30C, 0x00000000); + TEMP_PUTCODE(0xD2000000, 0x00000000);*/ + // SM64DS EUR shroom-o-matic + /*TEMP_PUTCODE(0x9209D09A , 0x00000000); + TEMP_PUTCODE(0x6209B468 , 0x00000000); + TEMP_PUTCODE(0xB209B468 , 0x00000000); + TEMP_PUTCODE(0x10000672 , 0x000003FF); + TEMP_PUTCODE(0xD2000000 , 0x00000000); + TEMP_PUTCODE(0x9209D09A , 0x00000000); + TEMP_PUTCODE(0x94000130 , 0xFCBF0000); + TEMP_PUTCODE(0x6209B468 , 0x00000000); + TEMP_PUTCODE(0xB209B468 , 0x00000000); + TEMP_PUTCODE(0x200006B3 , 0x00000001); + TEMP_PUTCODE(0x200006B4 , 0x00000001); + TEMP_PUTCODE(0xD2000000 , 0x00000000); + TEMP_PUTCODE(0x9209D09A , 0x00000000); + TEMP_PUTCODE(0x94000130 , 0xFC7F0000); + TEMP_PUTCODE(0x6209B468 , 0x00000000); + TEMP_PUTCODE(0xB209B468 , 0x00000000); + TEMP_PUTCODE(0x10000672 , 0x00000000); + TEMP_PUTCODE(0xD2000000 , 0x00000000);*/ + entry->Enabled = true; + NumCheatCodes++; } @@ -77,6 +115,8 @@ void RunCheat(CheatEntry* entry) { u32* code = &entry->Code[0]; + u32 offset = 0; + u32 datareg = 0; u32 cond = 1; u32 condstack = 0; @@ -100,18 +140,88 @@ void RunCheat(CheatEntry* entry) switch (op) { case16(0x00): // 32-bit write - NDS::ARM7Write32(a & 0x0FFFFFFF, b); + NDS::ARM7Write32((a & 0x0FFFFFFF) + offset, b); break; case16(0x10): // 16-bit write - NDS::ARM7Write16(a & 0x0FFFFFFF, b & 0xFFFF); + NDS::ARM7Write16((a & 0x0FFFFFFF) + offset, b & 0xFFFF); break; case16(0x20): // 8-bit write - NDS::ARM7Write8(a & 0x0FFFFFFF, b & 0xFF); + NDS::ARM7Write8((a & 0x0FFFFFFF) + offset, b & 0xFF); break; - case16(0x90): // IF b.l = ((~b.h) & u16[a]) + case16(0x30): // IF b > u32[a] + { + condstack <<= 1; + condstack |= cond; + + u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); + + cond = (b > chk) ? 1:0; + } + break; + + case16(0x40): // IF b < u32[a] + { + condstack <<= 1; + condstack |= cond; + + u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); + + cond = (b < chk) ? 1:0; + } + break; + + case16(0x50): // IF b == u32[a] + { + condstack <<= 1; + condstack |= cond; + + u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); + + cond = (b == chk) ? 1:0; + } + break; + + case16(0x60): // IF b != u32[a] + { + condstack <<= 1; + condstack |= cond; + + u32 chk = NDS::ARM7Read32(a & 0x0FFFFFFF); + + cond = (b != chk) ? 1:0; + } + break; + + case16(0x70): // IF b.l > ((~b.h) & u16[a]) + { + condstack <<= 1; + condstack |= cond; + + u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); + u16 chk = ~(b >> 16); + chk &= val; + + cond = ((b & 0xFFFF) > chk) ? 1:0; + } + break; + + case16(0x80): // IF b.l < ((~b.h) & u16[a]) + { + condstack <<= 1; + condstack |= cond; + + u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); + u16 chk = ~(b >> 16); + chk &= val; + + cond = ((b & 0xFFFF) < chk) ? 1:0; + } + break; + + case16(0x90): // IF b.l == ((~b.h) & u16[a]) { condstack <<= 1; condstack |= cond; @@ -124,6 +234,36 @@ void RunCheat(CheatEntry* entry) } break; + case16(0xA0): // IF b.l != ((~b.h) & u16[a]) + { + condstack <<= 1; + condstack |= cond; + + u16 val = NDS::ARM7Read16(a & 0x0FFFFFFF); + u16 chk = ~(b >> 16); + chk &= val; + + cond = ((b & 0xFFFF) != chk) ? 1:0; + } + break; + + case16(0xB0): // offset = u32[a + offset] + offset = NDS::ARM7Read32((a & 0x0FFFFFFF) + offset); + break; + + case 0xD0: // ENDIF + cond = condstack & 0x1; + condstack >>= 1; + break; + + case 0xD2: // NEXT+FLUSH + // TODO: loop shenanigans! + offset = 0; + datareg = 0; + condstack = 0; + cond = 1; + break; + default: printf("!! bad AR opcode %08X %08X\n", a, b); return; From 85a6a5bb386f0e10c31cbd60831cb22e7434f422 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 14 Feb 2020 23:34:26 +0100 Subject: [PATCH 55/71] * add support for a bunch of codes (all of them minus the loop shit, really) * hook it betterer so it doesn't asplode --- src/AREngine.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++++++- src/ARM.cpp | 9 ++++ src/GPU.cpp | 4 -- 3 files changed, 132 insertions(+), 5 deletions(-) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index d74d5331..7de65808 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -100,6 +100,25 @@ void Reset() TEMP_PUTCODE(0xB209B468 , 0x00000000); TEMP_PUTCODE(0x10000672 , 0x00000000); TEMP_PUTCODE(0xD2000000 , 0x00000000);*/ + // SM64DS EUR swim through floor + TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) + TEMP_PUTCODE(0x823FDFF8 , 0xFBFF0000); // IF 0000 < ((~FBFF) & u16[023FDFF8]) + TEMP_PUTCODE(0xDA000000 , 0x023FDFFA); // datareg = u16[023FDFFA + offset] + TEMP_PUTCODE(0xD4000000 , 0x00000001); // datareg += 1 + TEMP_PUTCODE(0xD7000000 , 0x023FDFFA); // u16[023FDFFA + offset] = datareg; offset += 2 + TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH + TEMP_PUTCODE(0xD3000000 , 0x027FFFA8); // offset = 027FFFA8 + TEMP_PUTCODE(0xF23FDFF8 , 0x00000002); // copy offset->023FDFF8, 2 + TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH + TEMP_PUTCODE(0x923FDFFA , 0xFFFE0000); // IF 0000 = ((~FFFE) & u16[023FDFFA]) + TEMP_PUTCODE(0x02037E7C , 0xE2000020); // u32[02037E7C] = E2000020 + TEMP_PUTCODE(0xD0000000 , 0x00000000); // ENDIF + TEMP_PUTCODE(0x923FDFFA , 0xFFFE0001); // IF 0001 = ((~FFFE) & u16[023FDFFA]) + TEMP_PUTCODE(0x02037E7C , 0xE2000000); // u32[02037E7C] = E2000000 + TEMP_PUTCODE(0xD0000000 , 0x00000000); // ENDIF + TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) + TEMP_PUTCODE(0x02037E7C , 0xE3A000FF); // u32[02037E7C] = E3A000FF + TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH entry->Enabled = true; NumCheatCodes++; } @@ -132,7 +151,12 @@ void RunCheat(CheatEntry* entry) { if (!cond) { - // TODO: skip parameters for opcode Ex + if ((op & 0xF0) == 0xE0) + { + for (u32 i = 0; i < b; i += 8) + *code += 2; + } + continue; } } @@ -264,6 +288,104 @@ void RunCheat(CheatEntry* entry) cond = 1; break; + case 0xD3: // offset = b + offset = b; + break; + + case 0xD4: // datareg += b + datareg += b; + break; + + case 0xD5: // datareg = b + datareg = b; + break; + + case 0xD6: // u32[b+offset] = datareg / offset += 4 + NDS::ARM7Write32(b + offset, datareg); + offset += 4; + break; + + case 0xD7: // u16[b+offset] = datareg / offset += 2 + NDS::ARM7Write16(b + offset, datareg & 0xFFFF); + offset += 2; + break; + + case 0xD8: // u8[b+offset] = datareg / offset += 1 + NDS::ARM7Write8(b + offset, datareg & 0xFF); + offset += 1; + break; + + case 0xD9: // datareg = u32[b+offset] + datareg = NDS::ARM7Read32(b + offset); + break; + + case 0xDA: // datareg = u16[b+offset] + datareg = NDS::ARM7Read16(b + offset); + break; + + case 0xDB: // datareg = u8[b+offset] + datareg = NDS::ARM7Read8(b + offset); + break; + + case 0xDC: // offset += b + offset += b; + break; + + case16(0xE0): // copy b param bytes to address a+offset + { + // TODO: check for bad alignment of dstaddr + + u32 dstaddr = (a & 0x0FFFFFFF) + offset; + u32 bytesleft = b; + while (bytesleft >= 8) + { + NDS::ARM7Write32(dstaddr, *code++); dstaddr += 4; + NDS::ARM7Write32(dstaddr, *code++); dstaddr += 4; + bytesleft -= 8; + } + if (bytesleft > 0) + { + u8* leftover = (u8*)code; + *code += 2; + if (bytesleft >= 4) + { + NDS::ARM7Write32(dstaddr, *(u32*)leftover); dstaddr += 4; + leftover += 4; + bytesleft -= 4; + } + while (bytesleft > 0) + { + NDS::ARM7Write8(dstaddr, *leftover++); dstaddr++; + bytesleft--; + } + } + } + break; + + case16(0xF0): // copy b bytes from address offset to address a + { + // TODO: check for bad alignment of srcaddr/dstaddr + + u32 srcaddr = offset; + u32 dstaddr = (a & 0x0FFFFFFF); + u32 bytesleft = b; + while (bytesleft >= 4) + { + NDS::ARM7Write32(dstaddr, NDS::ARM7Read32(srcaddr)); + srcaddr += 4; + dstaddr += 4; + bytesleft -= 4; + } + while (bytesleft > 0) + { + NDS::ARM7Write8(dstaddr, NDS::ARM7Read8(srcaddr)); + srcaddr++; + dstaddr++; + bytesleft--; + } + } + break; + default: printf("!! bad AR opcode %08X %08X\n", a, b); return; diff --git a/src/ARM.cpp b/src/ARM.cpp index 43838ca0..2faffcd6 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -20,6 +20,7 @@ #include "NDS.h" #include "ARM.h" #include "ARMInterpreter.h" +#include "AREngine.h" // instruction timing notes @@ -408,6 +409,14 @@ void ARM::TriggerIRQ() R_IRQ[2] = oldcpsr; R[14] = R[15] + (oldcpsr & 0x20 ? 2 : 0); JumpTo(ExceptionBase + 0x18); + + // ARDS cheat support + // normally, those work by hijacking the ARM7 VBlank handler + if (Num == 1) + { + if ((NDS::IF[1] & NDS::IE[1]) & (1< #include "NDS.h" #include "GPU.h" -#include "AREngine.h" namespace GPU { @@ -986,9 +985,6 @@ void StartScanline(u32 line) GPU2D_A->VBlank(); GPU2D_B->VBlank(); GPU3D::VBlank(); - - // TODO: verify when AR cheats actually run! - AREngine::RunCheats(); } else if (VCount == 144) { From 51dbb7165e272d3d1f460213a6787b1a6d7e6c46 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Feb 2020 00:36:22 +0100 Subject: [PATCH 56/71] finish the AR interpreter, I guess or mostly --- src/AREngine.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 7de65808..f8a1a231 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -101,7 +101,7 @@ void Reset() TEMP_PUTCODE(0x10000672 , 0x00000000); TEMP_PUTCODE(0xD2000000 , 0x00000000);*/ // SM64DS EUR swim through floor - TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) + /*TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) TEMP_PUTCODE(0x823FDFF8 , 0xFBFF0000); // IF 0000 < ((~FBFF) & u16[023FDFF8]) TEMP_PUTCODE(0xDA000000 , 0x023FDFFA); // datareg = u16[023FDFFA + offset] TEMP_PUTCODE(0xD4000000 , 0x00000001); // datareg += 1 @@ -118,9 +118,21 @@ void Reset() TEMP_PUTCODE(0xD0000000 , 0x00000000); // ENDIF TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) TEMP_PUTCODE(0x02037E7C , 0xE3A000FF); // u32[02037E7C] = E3A000FF - TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH + TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH*/ + // MKDS EUR shitty CPU-stalker code + /*TEMP_PUTCODE(0x94000130 , 0xFEBB0000); + TEMP_PUTCODE(0x023CDD4C , 0x00000001); + TEMP_PUTCODE(0xD2000000 , 0x00000000); + TEMP_PUTCODE(0x923CDD4C , 0x00000001); + TEMP_PUTCODE(0x6217AD18 , 0x00000000); + TEMP_PUTCODE(0xB217AD18 , 0x00000000); + TEMP_PUTCODE(0xC0000000 , 0x00000002); + TEMP_PUTCODE(0xD9000000 , 0x00000628); + TEMP_PUTCODE(0xD6000000 , 0x00000080); + TEMP_PUTCODE(0xDC000000 , 0x00000000); + TEMP_PUTCODE(0xD2000000 , 0x00000000); entry->Enabled = true; - NumCheatCodes++; + NumCheatCodes++;*/ } @@ -139,6 +151,14 @@ void RunCheat(CheatEntry* entry) u32 cond = 1; u32 condstack = 0; + u32* loopstart = code; + u32 loopcount = 0; + u32 loopcond = 1; + u32 loopcondstack = 0; + + // TODO: does anything reset this?? + u32 c5count = 0; + for (;;) { u32 a = *code++; @@ -275,17 +295,74 @@ void RunCheat(CheatEntry* entry) offset = NDS::ARM7Read32((a & 0x0FFFFFFF) + offset); break; + case 0xC0: // FOR 0..b + loopstart = code; // points to the first opcode after the FOR + loopcount = b; + loopcond = cond; // checkme + loopcondstack = condstack; // (GBAtek is not very clear there) + break; + + case 0xC4: // offset = pointer to C4000000 opcode + // theoretically used for safe storage, by accessing [offset+4] + // in practice could be used for a self-modifying AR code + // could be implemented with some hackery, but, does anything even + // use it?? + printf("AR: !! THE FUCKING C4000000 OPCODE. TELL ARISOTURA.\n"); + return; + + case 0xC5: // count++ / IF (count & b.l) == b.h + { + // with weird condition checking, apparently + // oh well + + c5count++; + if (!cond) break; + + condstack <<= 1; + condstack |= cond; + + u16 mask = b & 0xFFFF; + u16 chk = b >> 16; + + cond = ((c5count & mask) == chk) ? 1:0; + } + break; + + case 0xC6: // u32[b] = offset + NDS::ARM7Write32(b, offset); + break; + case 0xD0: // ENDIF cond = condstack & 0x1; condstack >>= 1; break; + case 0xD1: // NEXT + if (loopcount > 0) + { + loopcount--; + code = loopstart; + } + else + { + cond = loopcond; + condstack = loopcondstack; + } + break; + case 0xD2: // NEXT+FLUSH - // TODO: loop shenanigans! - offset = 0; - datareg = 0; - condstack = 0; - cond = 1; + if (loopcount > 0) + { + loopcount--; + code = loopstart; + } + else + { + offset = 0; + datareg = 0; + condstack = 0; + cond = 1; + } break; case 0xD3: // offset = b From ed39122c67ab1fbdaf5d2ab78fe1573378797e1b Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Feb 2020 16:07:13 +0100 Subject: [PATCH 57/71] Arisotura will you ever clean up after yourself. this is like your goddamn apartment, it's a mess. --- src/AREngine.cpp | 89 ++++++++---------------------------------------- 1 file changed, 14 insertions(+), 75 deletions(-) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index f8a1a231..e8fb314d 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -56,83 +56,22 @@ void Reset() #define TEMP_PUTCODE(a, b) *ptr++ = a; *ptr++ = b; CheatEntry* entry = &CheatCodes[0]; u32* ptr = &entry->Code[0]; - /*// NSMBDS EUR - giant fucking Mario - TEMP_PUTCODE(0x1209DBD0, 0x0000027C); - TEMP_PUTCODE(0x2209DBC0, 0x00000003); - TEMP_PUTCODE(0x94000130, 0xFFFD0000); - TEMP_PUTCODE(0x1209DBD0, 0x00000000); - TEMP_PUTCODE(0x2209DBC0, 0x00000003); + // what do we put in here? + // heh. noone knows. the world is full of mysteries + // like + // WHAT IS MY FUCKING GENDER + // probably I am nonbinary, like Mario + // oh + // noone told you? + // well... + // also why won't my video save. maybe there is too much crap in this computer. + // shrug. + // or why is this text warping weirdly. I should check the video driver. + // or the video card. + // well. + // entry->Enabled = true; NumCheatCodes++; - - entry = &CheatCodes[1]; - ptr = &entry->Code[0];*/ - // NSMBDS EUR - jump to the sky - /*TEMP_PUTCODE(0x9209DC90, 0xFFFD0002); - TEMP_PUTCODE(0x920DC910, 0x00000000); - TEMP_PUTCODE(0x021C1944, 0x00004000); - TEMP_PUTCODE(0xD2000000, 0x00000000); - TEMP_PUTCODE(0x9209DC90, 0xFFFE0001); - TEMP_PUTCODE(0x920DC910, 0x00000000); - TEMP_PUTCODE(0x021C1944, 0x00004000); - TEMP_PUTCODE(0xD2000000, 0x00000000);*/ - // SM64DS EUR redcoin - /*TEMP_PUTCODE(0x0210CC3E, 0x00000121); - TEMP_PUTCODE(0x5209F30C, 0x00000008); - TEMP_PUTCODE(0x0209F30C, 0x00000000); - TEMP_PUTCODE(0xD2000000, 0x00000000);*/ - // SM64DS EUR shroom-o-matic - /*TEMP_PUTCODE(0x9209D09A , 0x00000000); - TEMP_PUTCODE(0x6209B468 , 0x00000000); - TEMP_PUTCODE(0xB209B468 , 0x00000000); - TEMP_PUTCODE(0x10000672 , 0x000003FF); - TEMP_PUTCODE(0xD2000000 , 0x00000000); - TEMP_PUTCODE(0x9209D09A , 0x00000000); - TEMP_PUTCODE(0x94000130 , 0xFCBF0000); - TEMP_PUTCODE(0x6209B468 , 0x00000000); - TEMP_PUTCODE(0xB209B468 , 0x00000000); - TEMP_PUTCODE(0x200006B3 , 0x00000001); - TEMP_PUTCODE(0x200006B4 , 0x00000001); - TEMP_PUTCODE(0xD2000000 , 0x00000000); - TEMP_PUTCODE(0x9209D09A , 0x00000000); - TEMP_PUTCODE(0x94000130 , 0xFC7F0000); - TEMP_PUTCODE(0x6209B468 , 0x00000000); - TEMP_PUTCODE(0xB209B468 , 0x00000000); - TEMP_PUTCODE(0x10000672 , 0x00000000); - TEMP_PUTCODE(0xD2000000 , 0x00000000);*/ - // SM64DS EUR swim through floor - /*TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) - TEMP_PUTCODE(0x823FDFF8 , 0xFBFF0000); // IF 0000 < ((~FBFF) & u16[023FDFF8]) - TEMP_PUTCODE(0xDA000000 , 0x023FDFFA); // datareg = u16[023FDFFA + offset] - TEMP_PUTCODE(0xD4000000 , 0x00000001); // datareg += 1 - TEMP_PUTCODE(0xD7000000 , 0x023FDFFA); // u16[023FDFFA + offset] = datareg; offset += 2 - TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH - TEMP_PUTCODE(0xD3000000 , 0x027FFFA8); // offset = 027FFFA8 - TEMP_PUTCODE(0xF23FDFF8 , 0x00000002); // copy offset->023FDFF8, 2 - TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH - TEMP_PUTCODE(0x923FDFFA , 0xFFFE0000); // IF 0000 = ((~FFFE) & u16[023FDFFA]) - TEMP_PUTCODE(0x02037E7C , 0xE2000020); // u32[02037E7C] = E2000020 - TEMP_PUTCODE(0xD0000000 , 0x00000000); // ENDIF - TEMP_PUTCODE(0x923FDFFA , 0xFFFE0001); // IF 0001 = ((~FFFE) & u16[023FDFFA]) - TEMP_PUTCODE(0x02037E7C , 0xE2000000); // u32[02037E7C] = E2000000 - TEMP_PUTCODE(0xD0000000 , 0x00000000); // ENDIF - TEMP_PUTCODE(0x927FFFA8 , 0xFBFF0000); // IF 0000 = ((~FBFF) & u16[027FFFA8]) - TEMP_PUTCODE(0x02037E7C , 0xE3A000FF); // u32[02037E7C] = E3A000FF - TEMP_PUTCODE(0xD2000000 , 0x00000000); // NEXT/FLUSH*/ - // MKDS EUR shitty CPU-stalker code - /*TEMP_PUTCODE(0x94000130 , 0xFEBB0000); - TEMP_PUTCODE(0x023CDD4C , 0x00000001); - TEMP_PUTCODE(0xD2000000 , 0x00000000); - TEMP_PUTCODE(0x923CDD4C , 0x00000001); - TEMP_PUTCODE(0x6217AD18 , 0x00000000); - TEMP_PUTCODE(0xB217AD18 , 0x00000000); - TEMP_PUTCODE(0xC0000000 , 0x00000002); - TEMP_PUTCODE(0xD9000000 , 0x00000628); - TEMP_PUTCODE(0xD6000000 , 0x00000080); - TEMP_PUTCODE(0xDC000000 , 0x00000000); - TEMP_PUTCODE(0xD2000000 , 0x00000000); - entry->Enabled = true; - NumCheatCodes++;*/ } From e40d414c567c46fd971b2b09d669a2eae7ce674a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Feb 2020 16:20:53 +0100 Subject: [PATCH 58/71] now we can even parse the code from a text code. bahaahhhh --- src/AREngine.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index e8fb314d..760ca398 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -37,6 +37,69 @@ CheatEntry CheatCodes[64]; u32 NumCheatCodes; +void ParseTextCode(char* text, u32* code, int len) // or whatever this should be named? +{ + // TODO: they should atleast ensure they parsed all the crap before the actual code. we ain't taking care of that. + // this is melonDS not kindergarten. seriously. + + u32 cur_word = 0; + u32 ndigits = 0; + u32 nout = 0; + + char c; + while ((c = *text++) != '\0') + { + // hope they didn't forget the terminator, either + // otherwise + // they will be the ones getting terminated + // blarg. + + // so, what do we do here. + u32 val; + if (c >= '0' && c <= '9') + val = c - '0'; + else if (c >= 'a' && c <= 'f') + val = c - 'a' + 0xA; + else if (c >= 'A' && c <= 'F') + val = c - 'A' + 0xA; + else + continue; + + // okay, there's atleast that. + + cur_word <<= 4; + cur_word |= val; + + // now I figure we can't keep doing that forever? can we? + // maybe we can, after all + // but it's not a good idea. + + ndigits++; + if (ndigits >= 8) + { + if (nout >= len) + { + // OH SHIT SHIT SHIT SHIT + printf("AR: code too long!\n"); + return; + } + + *code++ = cur_word; + nout++; + + ndigits = 0; + cur_word = 0; + } + } + + if (nout & 1) + { + printf("AR: code was missing one word??\n"); + *code++ = 0; + } +} + + bool Init() { return true; @@ -70,6 +133,32 @@ void Reset() // or the video card. // well. // + + + char* test = R"(9209D09A 00000000 +6209B468 00000000 +B209B468 00000000 +10000672 000003FF +D2000000 00000000 +9209D09A 00000000 +94000130 FCBF0000 +6209B468 00000000 +B209B468 00000000 +200006B3 00000001 +200006B4 00000001 +D2000000 00000000 +9209D09A 00000000 +94000130 FC7F0000 +6209B468 00000000 +B209B468 00000000 +10000672 00000000 +D2000000 00000000)"; + ParseTextCode(test, entry->Code, 2*64); + printf("PARSED CODE:\n"); + for (int i = 0; i < 2*64; i+=2) + { + printf("%08X %08X\n", entry->Code[i], entry->Code[i+1]); + } entry->Enabled = true; NumCheatCodes++; } From 3a4947fbbe8a346b4e8a6d99ecbc4507f55dd39e Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Feb 2020 17:26:48 +0100 Subject: [PATCH 59/71] also that might have been bad for security. who knows. --- src/AREngine.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 760ca398..ab3969ac 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -95,6 +95,12 @@ void ParseTextCode(char* text, u32* code, int len) // or whatever this should be if (nout & 1) { printf("AR: code was missing one word??\n"); + if (nout >= len) + { + // OH SHIT SHIT SHIT SHIT + printf("AR: code too long!\n"); + return; + } *code++ = 0; } } From 3eb613650dce5e02a96b84b160b832fcadf09ab5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 16 Feb 2020 11:21:45 +0100 Subject: [PATCH 60/71] change ParseTextCode() so we can specify the length of an individual AR code within a bigger string. --- src/AREngine.cpp | 49 ++++++++++-------------------------------------- 1 file changed, 10 insertions(+), 39 deletions(-) diff --git a/src/AREngine.cpp b/src/AREngine.cpp index ab3969ac..2b6df65b 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -37,24 +37,16 @@ CheatEntry CheatCodes[64]; u32 NumCheatCodes; -void ParseTextCode(char* text, u32* code, int len) // or whatever this should be named? +void ParseTextCode(char* text, int tlen, u32* code, int clen) // or whatever this should be named? { - // TODO: they should atleast ensure they parsed all the crap before the actual code. we ain't taking care of that. - // this is melonDS not kindergarten. seriously. - u32 cur_word = 0; u32 ndigits = 0; + u32 nin = 0; u32 nout = 0; char c; while ((c = *text++) != '\0') { - // hope they didn't forget the terminator, either - // otherwise - // they will be the ones getting terminated - // blarg. - - // so, what do we do here. u32 val; if (c >= '0' && c <= '9') val = c - '0'; @@ -65,21 +57,14 @@ void ParseTextCode(char* text, u32* code, int len) // or whatever this should be else continue; - // okay, there's atleast that. - cur_word <<= 4; cur_word |= val; - // now I figure we can't keep doing that forever? can we? - // maybe we can, after all - // but it's not a good idea. - ndigits++; if (ndigits >= 8) { - if (nout >= len) + if (nout >= clen) { - // OH SHIT SHIT SHIT SHIT printf("AR: code too long!\n"); return; } @@ -90,14 +75,16 @@ void ParseTextCode(char* text, u32* code, int len) // or whatever this should be ndigits = 0; cur_word = 0; } + + nin++; + if (nin >= tlen) break; } if (nout & 1) { - printf("AR: code was missing one word??\n"); - if (nout >= len) + printf("AR: code was missing one word\n"); + if (nout >= clen) { - // OH SHIT SHIT SHIT SHIT printf("AR: code too long!\n"); return; } @@ -122,26 +109,10 @@ void Reset() NumCheatCodes = 0; // TODO: acquire codes from a sensible source! -#define TEMP_PUTCODE(a, b) *ptr++ = a; *ptr++ = b; CheatEntry* entry = &CheatCodes[0]; u32* ptr = &entry->Code[0]; - // what do we put in here? - // heh. noone knows. the world is full of mysteries - // like - // WHAT IS MY FUCKING GENDER - // probably I am nonbinary, like Mario - // oh - // noone told you? - // well... - // also why won't my video save. maybe there is too much crap in this computer. - // shrug. - // or why is this text warping weirdly. I should check the video driver. - // or the video card. - // well. - // - - char* test = R"(9209D09A 00000000 + /*char* test = R"(9209D09A 00000000 6209B468 00000000 B209B468 00000000 10000672 000003FF @@ -166,7 +137,7 @@ D2000000 00000000)"; printf("%08X %08X\n", entry->Code[i], entry->Code[i+1]); } entry->Enabled = true; - NumCheatCodes++; + NumCheatCodes++;*/ } From 228c625e620c821228b0d865915409f822da50e0 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 24 Feb 2020 17:42:05 +0100 Subject: [PATCH 61/71] fix teh comment --- src/Savestate.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Savestate.cpp b/src/Savestate.cpp index cb3d6a52..0337ff25 100644 --- a/src/Savestate.cpp +++ b/src/Savestate.cpp @@ -28,11 +28,7 @@ 04 - version major 06 - version minor 08 - length - 0C - game serial - 10 - ARM9 binary checksum - 14 - ARM7 binary checksum - 18 - reserved - 1C - reserved + 0C - reserved (should be game serial later!) section header: 00 - section magic From 8b1caae852e9cdbb256e49e85a313d5c348577e5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 24 Feb 2020 17:56:01 +0100 Subject: [PATCH 62/71] flesh shit out for loading a cheat file --- melonDS.cbp | 2 ++ src/ARCodeList.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/ARCodeList.h | 33 +++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 1 + 4 files changed, 74 insertions(+) create mode 100644 src/ARCodeList.cpp create mode 100644 src/ARCodeList.h diff --git a/melonDS.cbp b/melonDS.cbp index 58f86a63..8d900d1f 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -100,6 +100,8 @@ + + diff --git a/src/ARCodeList.cpp b/src/ARCodeList.cpp new file mode 100644 index 00000000..380481fb --- /dev/null +++ b/src/ARCodeList.cpp @@ -0,0 +1,38 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include "ARCodeList.h" + +/* + Action Replay code list format + + header: + 00 - magic MLAR + 04 - version major + 06 - version minor + 08 - length + 0C - number of codes + + code header: + 00 - magic MLCD + 04 - name length + 08 - code length + 0C - enable flag + 10 - code data (UTF8 name then actual code) +*/ diff --git a/src/ARCodeList.h b/src/ARCodeList.h new file mode 100644 index 00000000..b46510c0 --- /dev/null +++ b/src/ARCodeList.h @@ -0,0 +1,33 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef ARCODELIST_H +#define ARCODELIST_H + +#include "types.h" + +#define ARCL_MAJOR 1 +#define ARCL_MINOR 1 + +class ARCodeList +{ +public: + // +}; + +#endif // ARCODELIST_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b760ba8..5537e6d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ project(core) add_library(core STATIC + ARCodeList.cpp AREngine.cpp ARM.cpp ARMInterpreter.cpp From 5f99a681512627aa6f63325a676301bc7fa4d927 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 24 Feb 2020 18:31:44 +0100 Subject: [PATCH 63/71] detect whether we are running the game --- src/ARM.cpp | 2 ++ src/NDS.cpp | 32 +++++++++++++++++++++++++------- src/NDS.h | 2 ++ src/Savestate.h | 4 ++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index 2faffcd6..6248de2c 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -231,6 +231,8 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) PrefetchAbort(); return; }*/ + + NDS::MonitorARM9Jump(addr); } void ARMv4::JumpTo(u32 addr, bool restorecpsr) diff --git a/src/NDS.cpp b/src/NDS.cpp index 713e8ac4..09d255d3 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -101,6 +101,7 @@ u8 ARM7WRAM[0x10000]; u16 ExMemCnt[2]; +// TODO: these belong in NDSCart! u8 ROMSeed0[2*8]; u8 ROMSeed1[2*8]; @@ -145,6 +146,8 @@ u16 RCnt; bool Running; +bool RunningGame; + void DivDone(u32 param); void SqrtDone(u32 param); @@ -393,6 +396,7 @@ void Reset() FILE* f; u32 i; + RunningGame = false; LastSysClockCycles = 0; f = Platform::OpenLocalFile("bios9.bin", "rb"); @@ -676,21 +680,16 @@ bool DoSavestate(Savestate* file) file->Var16(&KeyCnt); file->Var16(&RCnt); - - for (int i = 0; i < 8; i++) - DMAs[i]->DoSavestate(file); - file->Var8(&WRAMCnt); + file->Var32((u32*)&RunningGame); + if (!file->Saving) { // 'dept of redundancy dept' // but we do need to update the mappings MapSharedWRAM(WRAMCnt); - } - if (!file->Saving) - { InitTimings(); SetGBASlotTimings(); @@ -699,6 +698,9 @@ bool DoSavestate(Savestate* file) SetWifiWaitCnt(tmp); // force timing table update } + for (int i = 0; i < 8; i++) + DMAs[i]->DoSavestate(file); + ARM9->DoSavestate(file); ARM7->DoSavestate(file); @@ -1276,6 +1278,22 @@ void NocashPrint(u32 ncpu, u32 addr) +void MonitorARM9Jump(u32 addr) +{ + // checkme: can the entrypoint addr be THUMB? + + if ((!RunningGame) && NDSCart::CartROM) + { + if (addr == *(u32*)&NDSCart::CartROM[0x24]) + { + printf("Game is now booting\n"); + RunningGame = true; + } + } +} + + + void HandleTimerOverflow(u32 tid) { Timer* timer = &Timers[tid]; diff --git a/src/NDS.h b/src/NDS.h index 4e41520e..c7b455ee 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -174,6 +174,8 @@ u32 GetPC(u32 cpu); u64 GetSysClockCycles(int num); void NocashPrint(u32 cpu, u32 addr); +void MonitorARM9Jump(u32 addr); + bool DMAsInMode(u32 cpu, u32 mode); bool DMAsRunning(u32 cpu); void CheckDMAs(u32 cpu, u32 mode); diff --git a/src/Savestate.h b/src/Savestate.h index 60d00e75..4793b771 100644 --- a/src/Savestate.h +++ b/src/Savestate.h @@ -22,8 +22,8 @@ #include #include "types.h" -#define SAVESTATE_MAJOR 4 -#define SAVESTATE_MINOR 1 +#define SAVESTATE_MAJOR 5 +#define SAVESTATE_MINOR 0 class Savestate { From ab911571e03e81a641f33856ccd02c85af80b10b Mon Sep 17 00:00:00 2001 From: niemand-deu <42780488+niemand-deu@users.noreply.github.com> Date: Wed, 26 Feb 2020 03:56:03 +0100 Subject: [PATCH 64/71] Update main.cpp --- src/libui_sdl/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 9d52985e..8e8bf9ec 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -2714,7 +2714,7 @@ int main(int argc, char** argv) } #else const char* confdir = g_get_user_config_dir(); - const char* confname = "/melonds"; + const char* confname = "/melonDS"; EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1]; strcat(EmuDirectory, confdir); strcat(EmuDirectory, confname); From 104b2a03aad74121358828a2c7c3a1a636f66a42 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 30 Mar 2020 11:04:50 +0200 Subject: [PATCH 65/71] properly handle ROMs with encrypted secure area --- src/NDS.cpp | 19 +++++++++++++- src/NDSCart.cpp | 70 ++++++++++++++++++++++++++++++++++--------------- src/NDSCart.h | 1 + 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index 09d255d3..a2ab6ce9 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -318,7 +318,24 @@ void SetupDirectBoot() MapSharedWRAM(3); - for (u32 i = 0; i < bootparams[3]; i+=4) + u32 arm9start = 0; + + // load the ARM9 secure area + if (bootparams[0] >= 0x4000 && bootparams[0] < 0x8000) + { + u8 securearea[0x800]; + NDSCart::DecryptSecureArea(securearea); + + for (u32 i = 0; i < 0x800; i+=4) + { + ARM9Write32(bootparams[2]+i, *(u32*)&securearea[i]); + arm9start += 4; + } + } + + // CHECKME: firmware seems to load this in 0x200 byte chunks + + for (u32 i = arm9start; i < bootparams[3]; i+=4) { u32 tmp = *(u32*)&NDSCart::CartROM[bootparams[0]+i]; ARM9Write32(bootparams[2]+i, tmp); diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index c3130116..cd04470d 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -865,6 +865,35 @@ bool ReadROMParams(u32 gamecode, u32* params) } +void DecryptSecureArea(u8* out) +{ + u32 gamecode = *(u32*)&CartROM[0x0C]; + u32 arm9base = *(u32*)&CartROM[0x20]; + + memcpy(out, &CartROM[arm9base], 0x800); + + Key1_InitKeycode(gamecode, 2, 2); + Key1_Decrypt((u32*)&out[0]); + + Key1_InitKeycode(gamecode, 3, 2); + for (u32 i = 0; i < 0x800; i += 8) + Key1_Decrypt((u32*)&out[i]); + + if (!strncasecmp((const char*)out, "encryObj", 8)) + { + printf("Secure area decryption OK\n"); + *(u32*)&out[0] = 0xE7FFDEFF; + *(u32*)&out[4] = 0xE7FFDEFF; + } + else + { + printf("Secure area decryption failed\n"); + for (u32 i = 0; i < 0x800; i += 4) + *(u32*)&out[i] = 0xE7FFDEFF; + } +} + + bool LoadROM(const char* path, const char* sram, bool direct) { // TODO: streaming mode? for really big ROMs or systems with limited RAM @@ -933,28 +962,8 @@ bool LoadROM(const char* path, const char* sram, bool direct) printf("Cart ID: %08X\n", CartID); - if (*(u32*)&CartROM[0x20] < 0x4000) - { - //ApplyDLDIPatch(); - } - - if (direct) - { - // TODO: in the case of an already-encrypted secure area, direct boot - // needs it decrypted - NDS::SetupDirectBoot(); - CmdEncMode = 2; - } - - CartInserted = true; - - // TODO: support more fancy cart types (homebrew?, flashcarts, etc) - if (CartID & 0x08000000) - ROMCommandHandler = ROMCommand_RetailNAND; - else - ROMCommandHandler = ROMCommand_Retail; - u32 arm9base = *(u32*)&CartROM[0x20]; + if (arm9base < 0x8000) { if (arm9base >= 0x4000) @@ -975,9 +984,28 @@ bool LoadROM(const char* path, const char* sram, bool direct) } } else + { CartIsHomebrew = true; + //ApplyDLDIPatch(); + } } + if (direct) + { + // TODO: in the case of an already-encrypted secure area, direct boot + // needs it decrypted + NDS::SetupDirectBoot(); + CmdEncMode = 2; + } + + CartInserted = true; + + // TODO: support more fancy cart types (homebrew?, flashcarts, etc) + if (CartID & 0x08000000) + ROMCommandHandler = ROMCommand_RetailNAND; + else + ROMCommandHandler = ROMCommand_Retail; + // encryption Key1_InitKeycode(gamecode, 2, 2); diff --git a/src/NDSCart.h b/src/NDSCart.h index 4167aa64..f19aea12 100644 --- a/src/NDSCart.h +++ b/src/NDSCart.h @@ -44,6 +44,7 @@ void Reset(); void DoSavestate(Savestate* file); +void DecryptSecureArea(u8* out); bool LoadROM(const char* path, const char* sram, bool direct); void RelocateSave(const char* path, bool write); From d412630a49b8fa07dde47c40f0f5f93d68c83f38 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 30 Mar 2020 13:28:51 +0200 Subject: [PATCH 66/71] should probably be a strncmp() and not strncasecmp() --- src/NDSCart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index cd04470d..5a2a0d0c 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -879,7 +879,7 @@ void DecryptSecureArea(u8* out) for (u32 i = 0; i < 0x800; i += 8) Key1_Decrypt((u32*)&out[i]); - if (!strncasecmp((const char*)out, "encryObj", 8)) + if (!strncmp((const char*)out, "encryObj", 8)) { printf("Secure area decryption OK\n"); *(u32*)&out[0] = 0xE7FFDEFF; From 4c560f3324e68e4aab20f6855ddc1a3f569ca0c7 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 11 Apr 2020 23:56:36 +0200 Subject: [PATCH 67/71] GPU3D: swap vin and vout during clipping, giving results that are closer to hardware. fixes #598 and also fixes #379 --- src/GPU3D.cpp | 2 +- src/libui_sdl/MelonCap.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 52bc10f9..1b316d5d 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -888,7 +888,7 @@ void StallPolygonPipeline(s32 delay, s32 nonstalldelay) template -void ClipSegment(Vertex* outbuf, Vertex* vout, Vertex* vin) +void ClipSegment(Vertex* outbuf, Vertex* vin, Vertex* vout) { s64 factor_num = vin->Position[3] - (plane*vin->Position[comp]); s32 factor_den = factor_num - (vout->Position[3] - (plane*vout->Position[comp])); diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp index 6e45bf5f..2658b666 100644 --- a/src/libui_sdl/MelonCap.cpp +++ b/src/libui_sdl/MelonCap.cpp @@ -336,8 +336,8 @@ void Update() colA &= mask; colB &= mask; - if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF00FF00; - else WinBitmapData[(y*768) + x + 512] = 0xFFFF0000; + if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF000000;//0xFF00FF00; + else WinBitmapData[(y*768) + x + 512] = 0xFFFFFFFF;//0xFFFF0000; } } From 33b4cdb077a3c45338331ce0e381c2487c7b16ff Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 12 Apr 2020 14:01:43 +0200 Subject: [PATCH 68/71] GPU3D: implement zero-dot W limit (DISP_1DOT_DEPTH) --- src/GPU3D.cpp | 176 ++++++++++++++++++++++++++++++++---------------- src/Savestate.h | 2 +- 2 files changed, 118 insertions(+), 60 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 1b316d5d..cfb48900 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -181,6 +181,8 @@ u8 RenderFogDensityTable[34]; u32 RenderClearAttr1, RenderClearAttr2; +u32 ZeroDotWLimit; + u32 GXStat; u32 ExecParams[32]; @@ -332,6 +334,8 @@ void Reset() DispCnt = 0; AlphaRef = 0; + ZeroDotWLimit = 0; // CHECKME + GXStat = 0; memset(ExecParams, 0, 32*4); @@ -409,6 +413,8 @@ void DoSavestate(Savestate* file) file->Var32(&DispCnt); file->Var8(&AlphaRef); + file->Var32(&ZeroDotWLimit); + file->Var32(&GXStat); file->VarArray(ExecParams, 32*4); @@ -569,27 +575,12 @@ void DoSavestate(Savestate* file) // probably not worth storing the vblank-latched Renderxxxxxx variables - if (file->IsAtleastVersion(2, 1)) - { - // command stall queue, only in version 2.1 and up - CmdStallQueue->DoSavestate(file); - file->Var32((u32*)&VertexPipeline); - file->Var32((u32*)&NormalPipeline); - file->Var32((u32*)&PolygonPipeline); - file->Var32((u32*)&VertexSlotCounter); - file->Var32(&VertexSlotsFree); - } - else - { - // for version 2.0, just clear it. not having it doesn't matter - // if this comes from older melonDS revisions. - CmdStallQueue->Clear(); - VertexPipeline = 0; - NormalPipeline = 0; - PolygonPipeline = 0; - VertexSlotCounter = 0; - VertexSlotsFree = 1; - } + CmdStallQueue->DoSavestate(file); + file->Var32((u32*)&VertexPipeline); + file->Var32((u32*)&NormalPipeline); + file->Var32((u32*)&PolygonPipeline); + file->Var32((u32*)&VertexSlotCounter); + file->Var32(&VertexSlotsFree); if (!file->Saving) { @@ -1170,6 +1161,89 @@ void SubmitPolygon() return; } + // reject the polygon if it's not going to fit in polygon/vertex RAM + + if (NumPolygons >= 2048 || NumVertices+nverts > 6144) + { + LastStripPolygon = NULL; + DispCnt |= (1<<13); + return; + } + + // compute screen coordinates + + for (int i = clipstart; i < nverts; i++) + { + Vertex* vtx = &clippedvertices[i]; + + // W is truncated to 24 bits at this point + // if this W is zero, the polygon isn't rendered + vtx->Position[3] &= 0x00FFFFFF; + + // viewport transform + s32 posX, posY; + s32 w = vtx->Position[3]; + if (w == 0) + { + posX = 0; + posY = 0; + } + else + { + posX = (((s64)(vtx->Position[0] + w) * Viewport[4]) / (((s64)w) << 1)) + Viewport[0]; + posY = (((s64)(-vtx->Position[1] + w) * Viewport[5]) / (((s64)w) << 1)) + Viewport[3]; + } + + vtx->FinalPosition[0] = posX & 0x1FF; + vtx->FinalPosition[1] = posY & 0xFF; + + // hi-res positions + if (w != 0) + { + posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4); + posY = ((((s64)(-vtx->Position[1] + w) * Viewport[5]) << 4) / (((s64)w) << 1)) + (Viewport[3] << 4); + + vtx->HiresPosition[0] = posX & 0x1FFF; + vtx->HiresPosition[1] = posY & 0xFFF; + } + } + + // zero-dot W check: + // * if the polygon's vertices all have the same screen coordinates, it is considered to be zero-dot + // * if all the vertices have a W greater than the threshold defined in register 0x04000610, + // the polygon is rejected, unless bit13 in the polygon attributes is set + + if (!(CurPolygonAttr & (1<<13))) + { + bool zerodot = true; + bool allbehind = true; + + for (int i = 0; i < nverts; i++) + { + Vertex* vtx = &clippedvertices[i]; + + if (vtx->FinalPosition[0] != clippedvertices[0].FinalPosition[0] || + vtx->FinalPosition[1] != clippedvertices[0].FinalPosition[1]) + { + zerodot = false; + break; + } + + s32 w = vtx->Position[3]; + if (w <= ZeroDotWLimit) + { + allbehind = false; + break; + } + } + + if (zerodot && allbehind) + { + LastStripPolygon = NULL; + return; + } + } + // build the actual polygon if (nverts == 4) @@ -1187,13 +1261,6 @@ void SubmitPolygon() else VertexSlotsFree = 0b1110; } - if (NumPolygons >= 2048 || NumVertices+nverts > 6144) - { - LastStripPolygon = NULL; - DispCnt |= (1<<13); - return; - } - Polygon* poly = &CurPolygonRAM[NumPolygons++]; poly->NumVertices = 0; @@ -1248,37 +1315,6 @@ void SubmitPolygon() NumVertices++; poly->NumVertices++; - // W is truncated to 24 bits at this point - // if this W is zero, the polygon isn't rendered - vtx->Position[3] &= 0x00FFFFFF; - - // viewport transform - s32 posX, posY; - s32 w = vtx->Position[3]; - if (w == 0) - { - posX = 0; - posY = 0; - } - else - { - posX = (((s64)(vtx->Position[0] + w) * Viewport[4]) / (((s64)w) << 1)) + Viewport[0]; - posY = (((s64)(-vtx->Position[1] + w) * Viewport[5]) / (((s64)w) << 1)) + Viewport[3]; - } - - vtx->FinalPosition[0] = posX & 0x1FF; - vtx->FinalPosition[1] = posY & 0xFF; - - // hi-res positions - if (w != 0) - { - posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4); - posY = ((((s64)(-vtx->Position[1] + w) * Viewport[5]) << 4) / (((s64)w) << 1)) + (Viewport[3] << 4); - - vtx->HiresPosition[0] = posX & 0x1FFF; - vtx->HiresPosition[1] = posY & 0xFFF; - } - vtx->FinalColor[0] = vtx->Color[0] >> 12; if (vtx->FinalColor[0]) vtx->FinalColor[0] = ((vtx->FinalColor[0] << 4) + 0xF); vtx->FinalColor[1] = vtx->Color[1] >> 12; @@ -2716,12 +2752,24 @@ void Write8(u32 addr, u8 val) return; } + if (addr >= 0x04000330 && addr < 0x04000340) + { + ((u8*)EdgeTable)[addr - 0x04000330] = val; + return; + } + if (addr >= 0x04000360 && addr < 0x04000380) { FogDensityTable[addr - 0x04000360] = val & 0x7F; return; } + if (addr >= 0x04000380 && addr < 0x040003C0) + { + ((u8*)ToonTable)[addr - 0x04000380] = val; + return; + } + printf("unknown GPU3D write8 %08X %02X\n", addr, val); } @@ -2782,6 +2830,11 @@ void Write16(u32 addr, u16 val) GXStat |= (val << 16); CheckFIFOIRQ(); return; + + case 0x04000610: + val &= 0x7FFF; + ZeroDotWLimit = (val * 0x200) + 0x1FF; + return; } if (addr >= 0x04000330 && addr < 0x04000340) @@ -2853,6 +2906,11 @@ void Write32(u32 addr, u32 val) GXStat |= val; CheckFIFOIRQ(); return; + + case 0x04000610: + val &= 0x7FFF; + ZeroDotWLimit = (val * 0x200) + 0x1FF; + return; } if (addr >= 0x04000400 && addr < 0x04000440) diff --git a/src/Savestate.h b/src/Savestate.h index 4793b771..a5447b33 100644 --- a/src/Savestate.h +++ b/src/Savestate.h @@ -22,7 +22,7 @@ #include #include "types.h" -#define SAVESTATE_MAJOR 5 +#define SAVESTATE_MAJOR 6 #define SAVESTATE_MINOR 0 class Savestate From ec6e4a2d1ee8e7d4b9726ed89677f46ec90bf317 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 12 Apr 2020 16:40:08 +0200 Subject: [PATCH 69/71] GPU3D: more accurate viewport transform (emulate quirk with W greater than 0xFFFF) --- src/GPU3D.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index cfb48900..4f146ae7 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -1181,8 +1181,11 @@ void SubmitPolygon() vtx->Position[3] &= 0x00FFFFFF; // viewport transform - s32 posX, posY; - s32 w = vtx->Position[3]; + // note: the DS performs these divisions using a 32-bit divider + // thus, if W is greater than 0xFFFF, some precision is sacrificed + // to make the numbers fit into the divider + u32 posX, posY; + u32 w = vtx->Position[3]; if (w == 0) { posX = 0; @@ -1190,14 +1193,27 @@ void SubmitPolygon() } else { - posX = (((s64)(vtx->Position[0] + w) * Viewport[4]) / (((s64)w) << 1)) + Viewport[0]; - posY = (((s64)(-vtx->Position[1] + w) * Viewport[5]) / (((s64)w) << 1)) + Viewport[3]; + posX = vtx->Position[0] + w; + posY = -vtx->Position[1] + w; + u32 den = w; + + if (w > 0xFFFF) + { + posX >>= 1; + posY >>= 1; + den >>= 1; + } + + den <<= 1; + posX = ((posX * Viewport[4]) / den) + Viewport[0]; + posY = ((posY * Viewport[5]) / den) + Viewport[3]; } vtx->FinalPosition[0] = posX & 0x1FF; vtx->FinalPosition[1] = posY & 0xFF; // hi-res positions + // to consider: only do this when using the GL renderer? apply the aforementioned quirk to this? if (w != 0) { posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4); @@ -1229,8 +1245,7 @@ void SubmitPolygon() break; } - s32 w = vtx->Position[3]; - if (w <= ZeroDotWLimit) + if (vtx->Position[3] <= ZeroDotWLimit) { allbehind = false; break; From a6150a9a9eaab7431b62a527f538c570ab8a6990 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 12 Apr 2020 16:59:06 +0200 Subject: [PATCH 70/71] Use pkg-config to find SDL2 on Windows --- src/libui_sdl/CMakeLists.txt | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index 8c8467bd..bcecc818 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -22,13 +22,12 @@ option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static set(BUILD_SHARED_LIBS OFF) add_subdirectory(libui) -find_package(SDL2 REQUIRED) -include_directories(${SDL2_INCLUDE_DIR}) -#string(STRIP ${SDL2_LIBRARIES} SDL2_LIBRARIES) +find_package(PkgConfig REQUIRED) +pkg_check_modules(SDL2 REQUIRED sdl2) add_executable(melonDS ${SOURCES_LIBUI}) -target_link_libraries(melonDS - core ${SDL2_LIBRARIES} libui) +target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) +target_link_libraries(melonDS core libui ${SDL2_LIBRARIES}) if (UNIX) option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) @@ -38,12 +37,9 @@ if (UNIX) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk+-3.0) - pkg_check_modules(SDL2 REQUIRED sdl2) - target_include_directories(melonDS - PRIVATE ${GTK3_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS} - ) - target_link_libraries(melonDS ${GTK3_LIBRARIES} ${SDL2_LIBRARIES}) + target_include_directories(melonDS PRIVATE ${GTK3_INCLUDE_DIRS}) + target_link_libraries(melonDS ${GTK3_LIBRARIES}) ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) From 4b57416552ec2fa95216e2b044559f215723bf70 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 12 Apr 2020 17:15:39 +0200 Subject: [PATCH 71/71] Windows: explicitly link gdi32 --- src/libui_sdl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt index bcecc818..a3a7f8a9 100644 --- a/src/libui_sdl/CMakeLists.txt +++ b/src/libui_sdl/CMakeLists.txt @@ -59,7 +59,7 @@ if (UNIX) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi) + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) endif () install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)