diff --git a/Makefile b/Makefile index 5558d17..a476a3e 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ include $(DEVKITARM)/ds_rules export TARGET := NINTV-DS export TOPDIR := $(CURDIR) -export VERSION := 5.9b +export VERSION := 6.0 ICON := -b $(CURDIR)/logo.bmp "NINTV-DS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/NINTV-DS" diff --git a/NINTV-DS.nds b/NINTV-DS.nds index c767b10..92ad8c0 100644 Binary files a/NINTV-DS.nds and b/NINTV-DS.nds differ diff --git a/README.md b/README.md index daf2924..ec332d6 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ Missing / Known Issues : License : ----------------------- -Copyright © 2021-2024 Dave Bernazzani (wavemotion-dave) +Copyright © 2021-2025 Dave Bernazzani (wavemotion-dave) Copying and distribution of this emulator, its source code and associated readme files, with or without modification, are permitted in any medium without @@ -175,6 +175,12 @@ Credits : -------------------------------------------------------------------------------- History : -------------------------------------------------------------------------------- +V6.0 : 01-Jan-2024 by wavemotion-dave + * Multi-overlays now supported for games like Mr. BASIC Meets Bits 'n Bytes, Inty BASIC Showcase collections, etc. + * Left/Right overlays now supported for games like Chess or Lode Runner. + * Ability to pick a different overlay for the game being played. + * A batch of new overlays to finally get the original 125 done! + V5.9 : 27-Oct-2024 by wavemotion-dave * Overlay overload... more than 220 custom Nintellivision overlays in the extras.zip pack. diff --git a/arm9/gfx/bgTop.png b/arm9/gfx/bgTop.png index 2227bf8..a8845e3 100644 Binary files a/arm9/gfx/bgTop.png and b/arm9/gfx/bgTop.png differ diff --git a/arm9/source/cheat.cpp b/arm9/source/cheat.cpp index b615bf2..a63e1d9 100644 --- a/arm9/source/cheat.cpp +++ b/arm9/source/cheat.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without diff --git a/arm9/source/config.cpp b/arm9/source/config.cpp index 8d67812..0e7fbdc 100644 --- a/arm9/source/config.cpp +++ b/arm9/source/config.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without @@ -208,6 +208,10 @@ static void SetDefaultGameConfig(UINT32 crc) if (crc == 0x650fc1b4) myConfig.controller_type = CONTROLLER_P2; // MLB Baseball and Super Pro Baseball use the P2 controller if (crc == 0x275F3512) myConfig.controller_type = CONTROLLER_P2; // Turbo uses the P2 controller + if (crc == 0x15E88FCE) myConfig.key_START_map = OVL_META_SWITCH; // Swords and Serpents wants to map the START button to swap controllers + if (crc == 0xB35C1101) myConfig.key_START_map = OVL_META_SWITCH; // Auto Racing wants to map the START button to swap controllers + if (crc == 0x515E1D7E) myConfig.key_START_map = OVL_META_SWITCH; // Body Slam - Super Pro Wrestling wants to map the START button to swap controllers + if (crc == 0xc047d487) myConfig.dpad_config = DPAD_STRICT_4WAY; // Beauty and the Beast is best with Strict 4-way if (crc == 0xD1D352A0) myConfig.dpad_config = DPAD_STRICT_4WAY; // Tower of Doom is best with Strict 4-way if (crc == 0xD8C9856A) myConfig.dpad_config = DPAD_DIAGONALS; // Q-Bert is best with diagonal @@ -476,7 +480,7 @@ struct options_t UINT8 option_max; }; -#define KEY_MAP_OPTIONS "KEY-1", "KEY-2", "KEY-3", "KEY-4", "KEY-5", "KEY-6", "KEY-7", "KEY-8", "KEY-9", "KEY-CLR", "KEY-0", "KEY-ENT", "FIRE", "L-ACT", "R-ACT", "RESET", "LOAD", "CONFIG", "SCORES", "QUIT", "STATE", "MENU", "SWITCH", "MANUAL", "SHOW DISC", "SHOW KBD", "DISC UP", "DISC DOWN", "SPEEDUP", "FASTLOAD SLOT 1" +#define KEY_MAP_OPTIONS "KEY-1", "KEY-2", "KEY-3", "KEY-4", "KEY-5", "KEY-6", "KEY-7", "KEY-8", "KEY-9", "KEY-CLR", "KEY-0", "KEY-ENT", "FIRE", "L-ACT", "R-ACT", "RESET", "LOAD", "CONFIG", "SCORES", "QUIT", "STATE", "MENU", "SWITCH L/R", "MANUAL", "SHOW DISC", "SHOW KBD", "DISC UP", "DISC DOWN", "SPEEDUP", "FASTLOAD SLOT 1" const struct options_t Option_Table[3][20] = { diff --git a/arm9/source/database.cpp b/arm9/source/database.cpp index 7aa5cb1..cd48c49 100644 --- a/arm9/source/database.cpp +++ b/arm9/source/database.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without @@ -209,7 +209,7 @@ const struct Database_t database[] = {0xC1F1CA74, "Thunder Castle (Matel 1982)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x2000}, {DB_ROM16, 0xD000, 0x1000}, {DB_ROM16, 0xF000, 0x1000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}}}, {0xD1D352A0, "Tower of Doom (INTV 1986)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x2000}, {DB_ROM16, 0x9000, 0x2000}, {DB_ROM16, 0xD000, 0x1000}, {DB_ROM16, 0xF000, 0x1000}, {DB_NONE, 0x0000, 0x0000}}}, {0x1AC989E2, "Triple Action (Matel 1981)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x1000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}}}, - {0x095638C0, "Triple Challenge (INTV 1986)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x2000}, {DB_ROM16, 0x9000, 0x2000}, {DB_ROM16, 0xC000, 0x0800}, {DB_ROM16, 0xD000, 0x1000}, {DB_NONE, 0x0000, 0x0000}}}, + {0x095638C0, "Triple Challenge (INTV 1986)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x2000}, {DB_ROM16, 0x9000, 0x2000}, {DB_ROM16, 0xC000, 0x0800}, {DB_RAM8, 0xD000, 0x0400}, {DB_NONE, 0x0000, 0x0000}}}, {0x7A558CF5, "Tron Maze-A-Tron (Matel 1981)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x2000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}}}, {0xCA447BBD, "Tron Deadly Discs (Matel 1981)", 0, 0, 0, 0, {{DB_ROM16, 0x5000, 0x1000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}}}, {0x07FB9435, "Tron Solar Sailer (Matel 1982)", 1, 0, 0, 0, {{DB_ROM16, 0x5000, 0x2000}, {DB_ROM16, 0xD000, 0x1000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}, {DB_NONE, 0x0000, 0x0000}}}, diff --git a/arm9/source/debugger.cpp b/arm9/source/debugger.cpp index 40e031c..a47b54e 100644 --- a/arm9/source/debugger.cpp +++ b/arm9/source/debugger.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without @@ -34,12 +34,6 @@ INT32 debug[DEBUG_SIZE] __attribute__((section(".dtcm"))) = {0}; -int getMemUsed(void) // returns the amount of used memory in bytes -{ - struct mallinfo mi = mallinfo(); - return mi.uordblks; -} - #ifdef DEBUG_ENABLE UINT32 debug_opcodes=0; diff --git a/arm9/source/emucore/CRC32.cpp b/arm9/source/emucore/CRC32.cpp index 728677e..1e4f669 100644 --- a/arm9/source/emucore/CRC32.cpp +++ b/arm9/source/emucore/CRC32.cpp @@ -12,13 +12,10 @@ #include #include #include "CRC32.h" +#include "types.h" #define CRC32_POLY 0x04C11DB7 -#ifndef _MAX_PATH -#define _MAX_PATH 255 -#endif - const UINT32 crc32_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, // 0 [0x00 .. 0x07] 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, // 8 [0x08 .. 0x0F] diff --git a/arm9/source/emucore/Rip.cpp b/arm9/source/emucore/Rip.cpp index ffa8c93..f47b582 100644 --- a/arm9/source/emucore/Rip.cpp +++ b/arm9/source/emucore/Rip.cpp @@ -92,6 +92,7 @@ Rip::Rip(UINT32 systemID) crc(0) { memset(filename, 0, sizeof(filename)); + memset(overlayname, 0, sizeof(overlayname)); JLP16Bit = NULL; } @@ -157,7 +158,7 @@ void ForceLoadOptions(UINT32 crc) } } -char cfgFilename[128]; +char cfgFilename[MAX_PATH]; Rip* Rip::LoadBin(const CHAR* filename) { // Create the path to the .cfg file (which may or may not exist...) diff --git a/arm9/source/emucore/Rip.h b/arm9/source/emucore/Rip.h index 5961210..2d9f648 100644 --- a/arm9/source/emucore/Rip.h +++ b/arm9/source/emucore/Rip.h @@ -61,6 +61,14 @@ public: return this->filename; } + void SetOverlayName(const CHAR* fname) { + strncpy(this->overlayname, fname, sizeof(this->overlayname)); + } + + const CHAR* GetOverlayName() { + return this->overlayname; + } + UINT32 GetCRC() { return this->crc; } UINT32 GetSize() { return this->mySize; } JLP *JLP16Bit; @@ -71,8 +79,12 @@ private: void AddPeripheralUsage(const CHAR* periphName, PeripheralCompatibility usage); static Rip* LoadBinCfg(const CHAR* cfgFile, UINT32 crc, size_t size); + // Set the filename and default overlay name for this game... void SetFileName(const CHAR* fname) { strncpy(this->filename, fname, sizeof(this->filename)); + strcat(this->overlayname, this->filename); + this->overlayname[strlen(this->overlayname)-4] = 0; + strcat(this->overlayname, ".ovl"); } UINT32 targetSystemID; @@ -82,6 +94,7 @@ private: PeripheralCompatibility peripheralUsages[MAX_PERIPHERALS]; UINT32 peripheralCount; CHAR filename[MAX_PATH]; + CHAR overlayname[MAX_PATH]; UINT32 mySize; UINT32 crc; }; diff --git a/arm9/source/emucore/types.h b/arm9/source/emucore/types.h index 687c69b..379893d 100644 --- a/arm9/source/emucore/types.h +++ b/arm9/source/emucore/types.h @@ -96,7 +96,7 @@ typedef struct #endif #ifndef MAX_PATH -#define MAX_PATH 256 +#define MAX_PATH 167 #endif #ifdef __cplusplus diff --git a/arm9/source/highscore.cpp b/arm9/source/highscore.cpp index 4c632c2..efd4c29 100644 --- a/arm9/source/highscore.cpp +++ b/arm9/source/highscore.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without diff --git a/arm9/source/loadgame.cpp b/arm9/source/loadgame.cpp index 8eb02e5..e27ae45 100644 --- a/arm9/source/loadgame.cpp +++ b/arm9/source/loadgame.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without @@ -32,8 +32,9 @@ // ------------------------------------------------------------- // We support up to 512 files per directory. More than enough. // ------------------------------------------------------------- -FICA_INTV intvromlist[512]; -u16 countintv=0, ucFicAct=0; +FICA_INTV intvromlist[MAX_ROMS]; +u16 countintv=0; +static u16 ucFicAct=0; char szName[256]; char szName2[256]; extern char directory[]; @@ -63,7 +64,10 @@ BOOL LoadCart(const CHAR* filename) bIsFatalError = false; bGameLoaded = FALSE; - bShowDisc = false; // Normal overlay to start + bShowDisc = false; // Normal overlay to start + multi_ovls = 0; // And assume non-multi-overlay + multi_ovl_idx = 0; // if the .ovl file indicates we are multi, this will get used to pull in alternate overlay graphics + bmulti_LR = 0; // Not a L/R multi-overlay // Clear out the debug array with every new game loaded memset(debug, 0x00, DEBUG_SIZE * (sizeof(UINT32))); @@ -430,7 +434,7 @@ void intvFindFiles(void) while (((pent=readdir(pdir))!=NULL)) { strcpy(szName2,pent->d_name); - szName2[127] = NULL; + szName2[MAX_PATH-1] = NULL; if (pent->d_type == DT_DIR) { if (!( (szName2[0] == '.') && (strlen(szName2) == 1))) diff --git a/arm9/source/loadgame.h b/arm9/source/loadgame.h index c7142fc..bc8084c 100644 --- a/arm9/source/loadgame.h +++ b/arm9/source/loadgame.h @@ -15,9 +15,11 @@ #include #include "types.h" +#define MAX_ROMS 512 + typedef struct FICtoLoad { - char filename[126]; + char filename[MAX_PATH]; UINT8 directory; UINT8 favorite; } FICA_INTV; diff --git a/arm9/source/manual.cpp b/arm9/source/manual.cpp index 0a8c6e9..af5a3b6 100644 --- a/arm9/source/manual.cpp +++ b/arm9/source/manual.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without diff --git a/arm9/source/nintv-ds.cpp b/arm9/source/nintv-ds.cpp index 2fe66e0..2f6b20c 100644 --- a/arm9/source/nintv-ds.cpp +++ b/arm9/source/nintv-ds.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without @@ -64,6 +64,9 @@ UINT8 bShowKeyboard __attribute__((section(".dtcm"))) = false; // -------------------------------------------------- UINT8 hud_x = 3; UINT8 hud_y = 0; +UINT8 multi_ovls = 0; +UINT8 multi_ovl_idx = 0; +UINT8 bmulti_LR = 0; UINT16 keypad_pressed = 0; UINT16 ecs_debounce_timer = 0; @@ -344,6 +347,32 @@ void HandleScreenStretch(void) } } + +extern u8 *fake_heap_end; // current heap start +extern u8 *fake_heap_start; // current heap end + +u8* getHeapStart() { + return fake_heap_start; +} + +u8* getHeapEnd() { + return (u8*)sbrk(0); +} + +u8* getHeapLimit() { + return fake_heap_end; +} + +int getMemUsed() { // returns the amount of used memory in bytes + struct mallinfo mi = mallinfo(); + return mi.uordblks; +} + +int getMemFree() { // returns the amount of free memory in bytes + struct mallinfo mi = mallinfo(); + return mi.fordblks + (getHeapLimit() - getHeapEnd()); +} + // ------------------------------------------------------------------------- // Show some information about the game/emulator on the bottom LCD screen. // ------------------------------------------------------------------------- @@ -367,7 +396,7 @@ void dsShowEmuInfo(void) sprintf(tmpStr, "ECS Enabled: %s ", (bUseECS ? "YES":"NO")); dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "Tutorvision: %s ", (bUseTutorvision ? "YES":"NO")); dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "Total Frames: %-9u ", global_frames); dsPrintValue(0, idx++, 0, tmpStr); - sprintf(tmpStr, "Memory Used: %-9d ", getMemUsed()); dsPrintValue(0, idx++, 0, tmpStr); + sprintf(tmpStr, "Memory Free: %-9d ", getMemFree()); dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "RAM Indexes: %d / %d / %d", fast_ram16_idx, slow_ram16_idx, slow_ram8_idx); dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "MEMS MAPPED: %-9d ", currentEmu->memoryBus.getMemCount());dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "RIP ROM Count: %-9d ", currentRip->GetROMCount()); dsPrintValue(0, idx++, 0, tmpStr); @@ -380,7 +409,7 @@ void dsShowEmuInfo(void) { sprintf(tmpStr, "Build Date: %s", __DATE__); dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "CPU Mode: %s", isDSiMode() ? "DSI 134MHz 16MB":"DS 67MHz 4 MB"); dsPrintValue(0, idx++, 0, tmpStr); - sprintf(tmpStr, "Memory Used: %-9d ", getMemUsed()); dsPrintValue(0, idx++, 0, tmpStr); + sprintf(tmpStr, "Memory Used: %-9d ", getMemFree()); dsPrintValue(0, idx++, 0, tmpStr); sprintf(tmpStr, "NO GAME IS LOADED!"); dsPrintValue(0, idx++, 0, tmpStr); } @@ -402,7 +431,7 @@ void dsShowEmuInfo(void) // so we now just store all the extra goodies in this menu... By default the SELECT // button will bring this up. // ------------------------------------------------------------------------------------- -#define MAIN_MENU_ITEMS 14 +#define MAIN_MENU_ITEMS 15 const char *main_menu[MAIN_MENU_ITEMS] = { "RESET EMULATOR", @@ -417,6 +446,7 @@ const char *main_menu[MAIN_MENU_ITEMS] = "SCREEN STRETCH", "SHOW DISC", "SHOW KEYBOARD", + "PICK OVERLAY", "QUIT EMULATOR", "EXIT THIS MENU", }; @@ -430,7 +460,7 @@ int menu_entry(void) dsShowBannerScreen(); swiWaitForVBlank(); dsPrintValue(8,3,0, (char*)"MAIN MENU"); - dsPrintValue(4,20,0, (char*)"PRESS UP/DOWN AND A=SELECT"); + dsPrintValue(4,22,0, (char*)"PRESS UP/DOWN AND A=SELECT"); for (int i=0; i myOverlay[OVL_META_SWAPOVL].x1 && touch.px < myOverlay[OVL_META_SWAPOVL].x2 && touch.py > myOverlay[OVL_META_SWAPOVL].y1 && touch.py < myOverlay[OVL_META_SWAPOVL].y2) + { + ds_handle_meta(OVL_META_SWAPOVL); + while (keysCurrent() & KEY_TOUCH) // Wait for release + { + WAITVBL; + } + } // --------------------------------------------------------------------------------------------------------- // And, finally, if the ECS keyboard is being shown, we must check for any presses on this virtual keyboard diff --git a/arm9/source/nintv-ds.h b/arm9/source/nintv-ds.h index f42ceda..c672722 100644 --- a/arm9/source/nintv-ds.h +++ b/arm9/source/nintv-ds.h @@ -28,6 +28,7 @@ extern UINT16 emu_frames; extern UINT16 frames_per_sec_calc; extern UINT8 oneSecTick; extern UINT8 hud_x, hud_y; +extern UINT8 multi_ovls, multi_ovl_idx, bmulti_LR; extern UINT8 b_dsi_mode; diff --git a/arm9/source/overlay.cpp b/arm9/source/overlay.cpp index 2f231a5..734cd35 100644 --- a/arm9/source/overlay.cpp +++ b/arm9/source/overlay.cpp @@ -1,10 +1,10 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // -// Copying and distribution of this emulator, its source code and associated -// readme files, with or without modification, are permitted in any medium without +// Copying and distribution of this emulator, its source code and associated +// readme files, with or without modification, are permitted in any medium without // royalty provided the this copyright notice is used and wavemotion-dave (NINTV-DS) -// and Kyle Davis (BLISS) are thanked profusely. +// and Kyle Davis (BLISS) are thanked profusely. // // The NINTV-DS emulator is offered as-is, without any warranty. // ===================================================================================== @@ -30,14 +30,24 @@ #include "bgTop.h" #include "Emulator.h" #include "Rip.h" +#include "loadgame.h" +#include "printf.h" // ------------------------------------------------ -// Reuse the char buffer from the game load... +// Reuse the char buffer from the game load... // we wouldn't need to use this at the same time. // ------------------------------------------------ extern char szName[]; extern Rip *currentRip; +char tile_str[16]; +char map_str[16]; +char pal_str[16]; +char ovl_str[16]; +char disc_str[16]; +char hudx_str[16]; +char hudy_str[16]; + // ---------------------------------------------------------------------------------------- // This is the default overlay that matches the main non-custom overlay bottom screen. // ---------------------------------------------------------------------------------------- @@ -46,7 +56,7 @@ struct Overlay_t defaultOverlay[OVL_MAX] = {120, 155, 30, 60}, // KEY_1 {158, 192, 30, 60}, // KEY_2 {195, 230, 30, 60}, // KEY_3 - + {120, 155, 65, 95}, // KEY_4 {158, 192, 65, 95}, // KEY_5 {195, 230, 65, 95}, // KEY_6 @@ -62,7 +72,7 @@ struct Overlay_t defaultOverlay[OVL_MAX] = {255, 255, 255, 255}, // KEY_FIRE {255, 255, 255, 255}, // KEY_L_ACT {255, 255, 255, 255}, // KEY_R_ACT - + { 10, 87, 10, 40}, // META_RESET { 10, 87, 41, 70}, // META_LOAD { 10, 87, 71, 100}, // META_CONFIG @@ -74,6 +84,7 @@ struct Overlay_t defaultOverlay[OVL_MAX] = {255, 255, 255, 255}, // META_MANUAL { 50, 86, 161, 191}, // META_DISC { 8, 49, 161, 191}, // META_KEYBOARD + {255, 255, 255, 255}, // META_SWAPOVL }; // ---------------------------------------------------------------------------------------- @@ -84,7 +95,7 @@ struct Overlay_t ecsOverlay[OVL_MAX] = {255, 255, 255, 255}, // KEY_1 {255, 255, 255, 255}, // KEY_2 {255, 255, 255, 255}, // KEY_3 - + {255, 255, 255, 255}, // KEY_4 {255, 255, 255, 255}, // KEY_5 {255, 255, 255, 255}, // KEY_6 @@ -100,7 +111,7 @@ struct Overlay_t ecsOverlay[OVL_MAX] = {255, 255, 255, 255}, // KEY_FIRE {255, 255, 255, 255}, // KEY_L_ACT {255, 255, 255, 255}, // KEY_R_ACT - + {255, 255, 255, 255}, // META_RESET {255, 255, 255, 255}, // META_LOAD {255, 255, 255, 255}, // META_CONFIG @@ -112,6 +123,7 @@ struct Overlay_t ecsOverlay[OVL_MAX] = {255, 255, 255, 255}, // META_MANUAL {255, 255, 255, 255}, // META_DISC {255, 255, 255, 255}, // META_KEYBOARD + {255, 255, 255, 255}, // META_SWAPOVL }; // ---------------------------------------------------------------------------------------- @@ -122,7 +134,7 @@ struct Overlay_t discOverlay[OVL_MAX] = {255, 255, 255, 255}, // KEY_1 {255, 255, 255, 255}, // KEY_2 {255, 255, 255, 255}, // KEY_3 - + {255, 255, 255, 255}, // KEY_4 {255, 255, 255, 255}, // KEY_5 {255, 255, 255, 255}, // KEY_6 @@ -138,7 +150,7 @@ struct Overlay_t discOverlay[OVL_MAX] = {255, 255, 255, 255}, // KEY_FIRE {255, 255, 255, 255}, // KEY_L_ACT {255, 255, 255, 255}, // KEY_R_ACT - + {255, 255, 255, 255}, // META_RESET {255, 255, 255, 255}, // META_LOAD {255, 255, 255, 255}, // META_CONFIG @@ -150,6 +162,7 @@ struct Overlay_t discOverlay[OVL_MAX] = {255, 255, 255, 255}, // META_MANUAL {255, 255, 255, 255}, // META_DISC {255, 255, 255, 255}, // META_KEYBOARD + {255, 255, 255, 255}, // META_SWAPOVL }; struct Overlay_t myOverlay[OVL_MAX]; @@ -163,13 +176,13 @@ unsigned int *customTiles = (unsigned int *) 0x06880000; //60K of video unsigned short *customMap = (unsigned short *)0x0688F000; // 4K of video memory for the map (generally about 2.5K) unsigned short customPal[512]; -char directory[192]; -char filename[192]; +char directory[192]; // Overlay directory +char filename[192]; // Overlay filename // ----------------------------------------------------------------------- -// Map of game CRC to default Overlay file... this will help so that -// users don't need to rename every .rom file to match exactly the +// Map of game CRC to default Overlay file... this will help so that +// users don't need to rename every .rom file to match exactly the // .ovl file. Most users just want to pick game, play game, enjoy game. // ----------------------------------------------------------------------- struct MapRomToOvl_t @@ -181,8 +194,9 @@ struct MapRomToOvl_t }; -struct MapRomToOvl_t MapRomToOvl[] = +struct MapRomToOvl_t MapRomToOvl[] = { + {0x9415dad4 , "2048", "2048", "2048.ovl"}, {0xD7C78754 , "4-TRIS", "4-TRIS", "4-TRIS.ovl"}, {0xB91488E2 , "4TRIS", "4TRIS", "4-TRIS.ovl"}, {0xA6E89A53 , "DRAGONS", "SWORDS", "A Tale of Dragons and Swords.ovl"}, @@ -198,8 +212,8 @@ struct MapRomToOvl_t MapRomToOvl[] = {0x2F9C93FC , "TREASURE", "TARMIN", "AD&D Treasure of Tarmin.ovl"}, {0x2F9C93FC , "MINOTAUR", "MINOTAUR", "AD&D Treasure of Tarmin.ovl"}, {0x9BA5A798 , "ANTARCTIC", "TALES", "Antarctic Tales.ovl"}, - {0xc4f83541 , "ANTHROPOMOR","FORCE", "Anthropomorphic Force.ovl"}, - {0x6F91FBC1 , "ARMOR", "BATTLE", "Armor Battle.ovl"}, + {0xc4f83541 , "ANTHROPOMOR","FORCE", "Anthropomorphic Force.ovl"}, + {0x6F91FBC1 , "ARMOR", "BATTLE", "Armor Battle.ovl"}, {0x5578C764 , "ASTRO", "INVADERS", "Astro Invaders.ovl"}, {0xFFFFFFFF , "ASTROSMASH", "SUPER", "Astrosmash-SuperPro.ovl"}, {0xFFFFFFFF , "ASTROSMASH", "COMPETITION", "Astrosmash-SuperPro.ovl"}, @@ -212,15 +226,16 @@ struct MapRomToOvl_t MapRomToOvl[] = {0x8B2727D9 , "BEACHHEAD", "BEACHHEAD", "BeachHead.ovl"}, {0xEAF650CC , "BEAMRIDER", "BEAMRIDER", "Beamrider.ovl"}, {0xC047D487 , "BEAUTY", "BEAST", "Beauty and the Beast.ovl"}, - {0xFFFFFFFF , "BEAST", "SP", "BeautyBeast - SP.ovl"}, - {0xB03F739B , "BLOCKADE", "RUNNER", "Blockade Runner.ovl"}, + {0xFFFFFFFF , "BEAST", "SP", "BeautyBeast - SP.ovl"}, + {0xB03F739B , "BLOCKADE", "RUNNER", "Blockade Runner.ovl"}, + {0x515E1D7E , "BODY", "SLAM", "Body Slam - Super Pro Wrestling.ovl"}, {0x32697B72 , "BOMB", "SQUAD", "Bomb Squad.ovl"}, {0xAB87C16F , "BOXING", "BOXING", "Boxing.ovl"}, {0xF8E5398D , "BUCK", "ROGERS", "Buck Rogers.ovl"}, {0x999CCEED , "BUMP", "JUMP", "Bump 'n' Jump.ovl"}, {0x43806375 , "BURGER", "TIME", "Burger Time.ovl"}, {0xC92BAAE8 , "BURGER", "TIME", "Burger Time.ovl"}, - {0xFFFFFFFF , "BURGRTM", "BURGRTM", "Burger Time.ovl"}, + {0xFFFFFFFF , "BURGRTM", "BURGRTM", "Burger Time.ovl"}, {0xFFFFFFFF , "SUPER", "CHEF", "Burger Time.ovl"}, {0xFFFFFFFF , "MASTER", "CHEF", "Burger Time.ovl"}, {0xFA492BBD , "BUZZ", "BOMBERS", "Buzz Bombers.ovl"}, @@ -284,16 +299,16 @@ struct MapRomToOvl_t MapRomToOvl[] = {0xc412dcde , "JUMPKING", "JUNIOR", "Jumpking Junior.ovl"}, {0x4422868E , "KING", "MOUNTAIN", "King of the Mountain.ovl"}, {0x87D95C72 , "KING", "MOUNTAIN", "King of the Mountain.ovl"}, - {0xFFFFFFFF , "SPKOTM", "SPKOTM", "King of the Mountain.ovl"}, + {0xFFFFFFFF , "SPKOTM", "SPKOTM", "King of the Mountain.ovl"}, {0x30e2819b , "KEYBOARD", "FUN", "Keyboard Fun.ovl"}, {0x8C9819A2 , "KOOL", "AID", "Kool-Aid Man.ovl"}, - {0xFFFFFFFF , "CAVES", "KROZ", "Kroz.ovl"}, + {0xFFFFFFFF , "CAVES", "KROZ", "Kroz.ovl"}, {0xA6840736 , "LADY", "BUG", "Lady Bug.ovl"}, {0x604611C0 , "POKER", "BLACKJACK", "Las Vegas Poker & Blackjack.ovl"}, {0x48D74D3C , "VEGAS", "ROULETTE", "Las Vegas Roulette.ovl"}, {0xd2d1ad9e , "LASER", "SHARKS", "Laser Sharks.ovl"}, {0x632F6ADF , "LEARNING", "FUN II", "Learning Fun II.ovl"}, - {0x2C5FD5FA , "LEARNING", "FUN I", "Learning Fun I.ovl"}, + {0x2C5FD5FA , "LEARNING", "FUN I", "Learning Fun I.ovl"}, {0xE00D1399 , "LOCK", "CHASE", "Lock-n-Chase.ovl"}, {0x5C7E9848 , "LOCK", "CHASE", "Lock-n-Chase.ovl"}, {0x6B6E80EE , "LOCO", "MOTION" "Loco-Motion.ovl"}, @@ -301,25 +316,29 @@ struct MapRomToOvl_t MapRomToOvl[] = {0x573B9B6D , "MASTERS", "UNIVERSE", "Masters of the Universe - The Power of He-Man.ovl"}, {0xEB4383E0 , "MAXIT", "MAXIT", "Maxit.ovl"}, {0x7A558CF5 , "MAZE", "TRON", "Maze-A-Tron.ovl"}, + {0xFF68AA22, "MELODY", "BLASTER", "Melody Blaster.ovl"}, {0xE806AD91 , "MICRO", "SURGEON", "Microsurgeon.ovl"}, {0x9D57498F , "MIND", "STRIKE", "Mind Strike.ovl"}, {0xec2e2320 , "MISSILE", "DOMINATION", "Missile Domination.ovl"}, - {0x11FB9974 , "MISSION", "X", "Mission X.ovl"}, - {0xb229d5c7 , "MOON", "BLAST", "Moon Blast.ovl"}, + {0x11FB9974 , "MISSION", "X", "Mission X.ovl"}, + {0xb229d5c7 , "MOON", "BLAST", "Moon Blast.ovl"}, {0x5F6E1AF6 , "MOTOCROSS", "MOTOCROSS", "Motocross.ovl"}, {0x598662F2 , "MOUSE", "TRAP", "Mouse Trap.ovl"}, {0xE367E450 , "MR", "CHESS", "MrChess.ovl"}, {0xDBAB54CA , "NASL", "SOCCER", "NASL Soccer.ovl"}, {0x09dc0db2 , "NINJA", "ODYSSEY", "Ninja Odyssey.ovl"}, {0x4B91CF16 , "NFL", "FOOTBALL", "NFL Football.ovl"}, + {0x76564A13 , "NHL", "HOCKEY", "NHL Hockey.ovl"}, {0x613e109b , "JR", "PAC", "Jr Pac-Man.ovl"}, + {0xBEF0B0C7 , "MR", "BASIC", "MrBASIC.ovl"}, {0x0753544F , "MS", "PAC", "Ms Pac-Man.ovl"}, {0x7334CD44 , "NIGHT", "STALKER", "Night Stalker.ovl"}, - {0xFFFFFFFF , "MSTALKER", "MSTALKER", "Night Stalker.ovl"}, + {0x6B5EA9C4 , "MOUNTAIN", "MADNESS", "Mountain Madness - Super Pro Skiing.ovl"}, + {0xFFFFFFFF , "MSTALKER", "MSTALKER", "Night Stalker.ovl"}, {0x5EE2CC2A , "NOVA", "BLAST", "Nova Blast.ovl"}, - {0xFFFFFFFF , "OLD", "SCHOOL", "Old School.ovl"}, - {0xFFFFFFFF , "OLD", "SKOOL", "Old School.ovl"}, - {0xFFFFFFFF , "OMEGA", "RACE", "Omega Race.ovl"}, + {0xFFFFFFFF , "OLD", "SCHOOL", "Old School.ovl"}, + {0xFFFFFFFF , "OLD", "SKOOL", "Old School.ovl"}, + {0xFFFFFFFF , "OMEGA", "RACE", "Omega Race.ovl"}, {0x36A7711B , "OPERATION", "CLOUDFIRE", "Operation Cloudfire.ovl"}, {0xFFFFFFFF , "OREGON", "BOUND", "Oregon Bound.ovl"}, {0xFFFFFFFF , "OREGON", "TRAIL", "Oregon Bound.ovl"}, @@ -365,7 +384,6 @@ struct MapRomToOvl_t MapRomToOvl[] = {0x8F7D3069 , "SUPER", "COBRA", "Super Cobra.ovl"}, {0x7C32C9B8 , "SUPER", "COBRA", "Super Cobra.ovl"}, {0xe9e3f60d , "MAZE", "CHASE", "Scooby Doo's Maze Chase.ovl"}, - {0xBEF0B0C7 , "MAZE", "CHASE", "Scooby Doo's Maze Chase.ovl"}, {0xFFFFFFFF , "SCOOBY", "DOO", "Scooby Doo's Maze Chase.ovl"}, {0x99AE29A9 , "SEA", "BATTLE", "Sea Battle.ovl"}, {0x2A4C761D , "SHARK!", "SHARK!", "Shark! Shark!.ovl"}, @@ -373,8 +391,8 @@ struct MapRomToOvl_t MapRomToOvl[] = {0xFFFFFFFF , "SHARK SHARK","SHARK SHARK", "Shark! Shark!.ovl"}, {0xFF7CB79E , "SHARP", "SHOT", "Sharp Shot.ovl"}, {0xF093E801 , "US", "SKIING", "Skiing.ovl"}, - {0x0e6198a5 , "GADHLAN", "THUR", "Gadhlan Thur.ovl"}, - {0xFFFFFFFF , "GRAIL", "GODS", "Grail of the Gods.ovl"}, + {0x0e6198a5 , "GADHLAN", "THUR", "Gadhlan Thur.ovl"}, + {0xFFFFFFFF , "GRAIL", "GODS", "Grail of the Gods.ovl"}, {0xFFFFFFFF , "SACRED", "TRIBE", "Sacred Tribe.ovl"}, {0xFFFFFFFF , "SEA", "VENTURE", "Sea Venture.ovl"}, {0xE8B8EBA5 , "SPACE", "ARMADA", "Space Armada.ovl"}, @@ -398,11 +416,13 @@ struct MapRomToOvl_t MapRomToOvl[] = {0xD6F44FA5 , "TNT", "COWBOY", "TNT Cowboy.ovl"}, {0xCA447BBD , "DEADLY", "DISCS", "TRON Deadly Discs.ovl"}, {0xFFFFFFFF , "DEADLIER", "DISCS", "TRON Deadly Discs.ovl"}, + {0xFFFFFFFF , "DEADLY", "DOGS", "Deadly Dogs.ovl"}, {0x07FB9435 , "SOLAR", "SAILOR", "TRON Solar Sailor.ovl"}, {0xbb759a58 , "SOLAR", "SAILER", "TRON Solar Sailor.ovl"}, {0xFFFFFFFF , "TRON", "SOLAR", "TRON Solar Sailor.ovl"}, {0x4c963cb2 , "TENNIS2", "TENNIS2", "Super Pro Tennis.ovl"}, - {0x4c963cb2 , "SUPER", "TENNIS", "Super Pro Tennis.ovl"}, + {0x4c963cb2 , "SUPER", "TENNIS", "Super Pro Tennis.ovl"}, + {0x16BFB8EB , "SUPER", "DECATHLON", "Super Pro Decathlon.ovl"}, {0x03E9E62E , "TENNIS", "TENNIS", "Tennis.ovl"}, {0xB7923858 , "SHOW", "MUST", "The Show Must Go On.ovl"}, {0xF3DF94E0 , "THIN", "ICE", "Thin Ice.ovl"}, @@ -414,7 +434,8 @@ struct MapRomToOvl_t MapRomToOvl[] = {0x67ca7c0a , "MYSTIC", "CASTLE", "Mystic Castle.ovl"}, {0xD1D352A0 , "TOWER", "DOOM", "Tower of Doom.ovl"}, {0x734F3260 , "TRUCKIN", "TRUCKIN", "Truckin.ovl"}, - {0x1AC989E2 , "TRIPLE", "ACTION", "Triple Action.ovl"}, + {0x1AC989E2 , "TRIPLE", "ACTION", "Triple Action.ovl"}, + {0x095638c0 , "TRIPLE", "CHALLENGE", "Triple Challenge.ovl"}, {0x6FA698B3 , "TUTANKHAM", "TUTANKHAM", "Tutankham.ovl"}, {0x275F3512 , "TURBO", "COLECO", "Turbo.ovl"}, {0x752FD927 , "USCF", "CHESS", "USCF Chess.ovl"}, @@ -455,21 +476,19 @@ struct MapRomToOvl_t MapRomToOvl[] = {0x7fd5d202 , "DEATH", "STRIKE", "Death Star Strike.ovl"}, {0x8ae91ade , "ISTAR", "ISTAR", "istar.ovl"}, {0xa1b83fdb , "ONION", "ONION", "Onion.ovl"}, + {0x3ccc255f , "SHOWCASE", "VOL 1", "Inty-BASIC-Showcase1.ovl"}, + {0xde8eac39 , "SHOWCASE", "VOL 2", "Inty-BASIC-Showcase2.ovl"}, {0x00000000 , "xxx", "zzz", "generic.ovl"}, }; -// ----------------------------------------------------------------------------------------------- -// Custom overlays are read in and must be in a very strict format. See the documenatation -// for custom overlays for details on the format this must be in. We could probably use a -// bit more error checking here... but we expect customer overlay designers to know what's up. -// ----------------------------------------------------------------------------------------------- -void load_custom_overlay(bool bCustomGeneric) +// -------------------------------------------------------------------------------------- +// Get the directory in which the .ovl files are located... this is set in Global Config +// -------------------------------------------------------------------------------------- +void get_ovl_directory(void) { - FILE *fp = NULL; - // ------------------------------------------------------- - // Read the associated .ovl file and parse it... Start by + // Read the associated .ovl file and parse it... Start by // getting the root folder where overlays are stored... // ------------------------------------------------------- if (myGlobalConfig.ovl_dir == 1) // In: /ROMS/OVL @@ -488,68 +507,105 @@ void load_custom_overlay(bool bCustomGeneric) { strcpy(directory, "./"); // In: Same DIR as ROM files } +} + +// ----------------------------------------------------------------------------------------------- +// Custom overlays are read in and must be in a very strict format. See the documentation +// for custom overlays for details on the format this must be in. We could probably use a +// bit more error checking here... but we expect customer overlay designers to know what's up. +// ----------------------------------------------------------------------------------------------- +void load_custom_overlay(bool bCustomGeneric) +{ + FILE *fp = NULL; + + get_ovl_directory(); + + // Is this a multi-overlay? If so, we setup for special handling + if (multi_ovl_idx) + { + sprintf(tile_str, ".til%d", multi_ovl_idx); + sprintf(map_str, ".ma%d", multi_ovl_idx); + sprintf(pal_str, ".pa%d", multi_ovl_idx); + sprintf(ovl_str, ".ov%d", multi_ovl_idx); + sprintf(disc_str, ".dis%d", multi_ovl_idx); + sprintf(hudx_str, ".hu%dx", multi_ovl_idx); + sprintf(hudy_str, ".hu%dy", multi_ovl_idx); + } + else + { + strcpy(tile_str, ".tile"); + strcpy(map_str, ".map"); + strcpy(pal_str, ".pal"); + strcpy(ovl_str, ".ovl"); + strcpy(disc_str, ".disc"); + strcpy(hudx_str, ".hudx"); + strcpy(hudy_str, ".hudy"); + } u8 bFound = 0; // If we have a game (RIP) loaded, try to find a matching overlay if (currentRip != NULL) { - strcpy(filename, directory); - strcat(filename, currentRip->GetFileName()); - filename[strlen(filename)-4] = 0; - strcat(filename, ".ovl"); - fp = fopen(filename, "rb"); - if (fp != NULL) // If file found + // If user picked the special 'Generic Overlay' we force the generic overlay to be used instead... + if (strcmp(currentRip->GetOverlayName(), "--Generic Overlay--") != 0) { - bFound = 1; - } - else // Not found... try to find it using the RomToOvl[] table - { - UINT16 i=0; - while (MapRomToOvl[i].crc != 0x00000000) + strcpy(filename, directory); + strcat(filename, currentRip->GetOverlayName()); + fp = fopen(filename, "rb"); + if (fp != NULL) // If file found { - if (MapRomToOvl[i].crc == currentRip->GetCRC()) - { - strcpy(filename, directory); - strcat(filename, MapRomToOvl[i].ovl_filename); - fp = fopen(filename, "rb"); - if (fp != NULL) bFound = 1; - break; - } - i++; + bFound = 1; } - - // If still not found after searching for CRC32... try fuzzy name search... - if (!bFound) + else // Not found... try to find it using the RomToOvl[] table { UINT16 i=0; while (MapRomToOvl[i].crc != 0x00000000) { - // It has to match both string searches to be valid... Uppercase for the compare... - strcpy(szName, currentRip->GetFileName()); - for (int j=0; jGetCRC()) { strcpy(filename, directory); strcat(filename, MapRomToOvl[i].ovl_filename); fp = fopen(filename, "rb"); - if (fp != NULL) bFound = 1; + if (fp != NULL) {bFound = 1;} break; } i++; } + + // If still not found after searching for CRC32... try fuzzy name search... + if (!bFound) + { + UINT16 i=0; + while (MapRomToOvl[i].crc != 0x00000000) + { + // It has to match both string searches to be valid... Uppercase for the compare... + strcpy(szName, currentRip->GetFileName()); + for (int j=0; j 8) multi_ovls = 8; // Limit to something reasonable... + } + } + + // Handle Tile Line + if (strstr(szName, tile_str) != NULL) + { + char *ptr = strstr(szName, tile_str); ptr += 6; customTiles[tiles_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customTiles[tiles_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; @@ -638,9 +713,9 @@ void load_custom_overlay(bool bCustomGeneric) } // Handle Map Line - if (strstr(szName, ".map") != NULL) + if (strstr(szName, map_str) != NULL) { - char *ptr = strstr(szName, ".map"); + char *ptr = strstr(szName, map_str); ptr += 4; customMap[map_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customMap[map_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; @@ -650,12 +725,12 @@ void load_custom_overlay(bool bCustomGeneric) customMap[map_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customMap[map_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customMap[map_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; - } + } // Handle Palette Line - if (strstr(szName, ".pal") != NULL) + if (strstr(szName, pal_str) != NULL) { - char *ptr = strstr(szName, ".pal"); + char *ptr = strstr(szName, pal_str); ptr += 4; customPal[pal_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customPal[pal_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; @@ -665,7 +740,7 @@ void load_custom_overlay(bool bCustomGeneric) customPal[pal_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customPal[pal_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customPal[pal_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; - } + } } while (!feof(fp)); fclose(fp); @@ -678,27 +753,27 @@ void load_custom_overlay(bool bCustomGeneric) decompress(bgBottomTiles, bgGetGfxPtr(bg0b), LZ77Vram); decompress(bgBottomMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); dmaCopy((void *) bgBottomPal,(u16*) BG_PALETTE_SUB,256*2); - } + } } // --------------------------------------------------------------------------- -// This puts the overlay on the main screen. It can be one of the built-in +// This puts the overlay on the main screen. It can be one of the built-in // overlays or it might be a custom overlay that will be rendered... // --------------------------------------------------------------------------- void show_overlay(u8 bShowKeyboard, u8 bShowDisc) { // Assume default overlay... custom can change it below... memcpy(&myOverlay, &defaultOverlay, sizeof(myOverlay)); - + swiWaitForVBlank(); - + if (bShowKeyboard) // ECS keyboard overlay { decompress(bgBottom_ECSTiles, bgGetGfxPtr(bg0b), LZ77Vram); decompress(bgBottom_ECSMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); dmaCopy((void *) bgBottom_ECSPal,(u16*) BG_PALETTE_SUB,256*2); - // ECS Overlay... + // ECS Overlay... memcpy(&myOverlay, &ecsOverlay, sizeof(myOverlay)); } else // Default Overlay... which might be custom!! @@ -708,27 +783,360 @@ void show_overlay(u8 bShowKeyboard, u8 bShowDisc) decompress(bgBottom_discTiles, bgGetGfxPtr(bg0b), LZ77Vram); decompress(bgBottom_discMap, (void*) bgGetMapPtr(bg0b), LZ77Vram); dmaCopy((void *) bgBottom_discPal,(u16*) BG_PALETTE_SUB,256*2); - // Disc Overlay... + // Disc Overlay... memcpy(&myOverlay, &discOverlay, sizeof(myOverlay)); } else { - load_custom_overlay(true); // This will try to load nintv-ds.ovl or else default to the generic background + load_custom_overlay(true); // This will try to load the correct overlay for this game or else default to the generic keyboard overlay } } - + unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32); dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2); REG_BLDCNT=0; REG_BLDCNT_SUB=0; REG_BLDY=0; REG_BLDY_SUB=0; - - swiWaitForVBlank(); - + + swiWaitForVBlank(); + if (bShowKeyboard) // ECS keyboard overlay { dsPrintValue(1,22,ecs_ctrl_key?1:0,ecs_ctrl_key ? (char*)"@": (char*)" "); dsPrintValue(5,22,0,ecs_shift_key ? (char*)"@": (char*)" "); - } + } +} + +// -------------------------------------------------------------------------- +// Allow the user to pick an overlay file for the current game. This overlay +// will override the normal overlay for the game until a new game is loaded. +// -------------------------------------------------------------------------- +FICA_INTV overlayfiles[MAX_ROMS]; +u16 countovls=0; +static u16 ucFicAct=0; +extern char szName[]; +extern char szName2[]; +char originalPath[MAX_PATH]; + +// ---------------------------------------------------------------------------------------- +// Find all .bin, .int and .rom files in the current directory (or, if this is the first +// time we are loading up files, use the global configuration to determine what directory +// we should be starting in... after the first time we just load up the current directory). +// ---------------------------------------------------------------------------------------- +void ovlFindFiles(void) +{ + DIR *pdir; + struct dirent *pent; + + countovls = 0; + memset(overlayfiles, 0x00, sizeof(overlayfiles)); + + strcpy(overlayfiles[countovls++].filename, "--Generic Overlay--"); + + get_ovl_directory(); // Find the overlay directory from global config selection + pdir = opendir(directory); // We only allow selection of overlays from the overlay directory... + + if (pdir) + { + while (((pent=readdir(pdir))!=NULL)) + { + strcpy(szName2,pent->d_name); + szName2[MAX_PATH-1] = NULL; + if (strlen(szName2)>4) + { + if ( (strcasecmp(strrchr(szName2, '.'), ".ovl") == 0) ) + { + overlayfiles[countovls].directory = false; + strcpy(overlayfiles[countovls].filename,szName2); + countovls++; + } + } + } + closedir(pdir); + } + + // ---------------------------------------------- + // If we found any files, go sort the list... + // ---------------------------------------------- + if (countovls) + { + extern int intvFilescmp (const void *c1, const void *c2); + qsort(overlayfiles, countovls, sizeof (FICA_INTV), intvFilescmp); + } +} + +// -------------------------------------------------------------------------- +// Display the files - up to 18 in a page. This is carried over from the +// oldest emulators I've worked on and there is some bug in here where +// it occasionally gets out of sync... it's minor enough to not be an +// issue but at some point this routine should be re-written... +// -------------------------------------------------------------------------- +void OvlDisplayFiles(unsigned int NoDebGame,u32 ucSel) +{ + unsigned short ucBcl,ucGame; + + // Display all games if possible + unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32); + dmaFillWords(dmaVal | (dmaVal<<16),(void*) (bgGetMapPtr(bg1b)),32*24*2); + sprintf(szName,"%04d/%04d %s",(int)(1+ucSel+NoDebGame),countovls, "OVERLAYS"); + dsPrintValue(16-strlen(szName)/2,2,0,szName); + dsPrintValue(31,4,0,(char *) (NoDebGame>0 ? "<" : " ")); + dsPrintValue(31,20,0,(char *) (NoDebGame+14" : " ")); + + dsPrintValue(4,23,0,(char*)"A=PICK OVERLAY, B=BACK"); + + for (ucBcl=0;ucBcl<17; ucBcl++) + { + ucGame= ucBcl+NoDebGame; + if (ucGame < countovls) + { + strcpy(szName,overlayfiles[ucGame].filename); + szName[29]='\0'; + if (overlayfiles[ucGame].directory) + { + szName[27]='\0'; + sprintf(szName2,"[%s]",szName); + dsPrintValue(0,4+ucBcl,(ucSel == ucBcl ? 1 : 0),szName2); + } + else + { + if (overlayfiles[ucGame].favorite) + { + dsPrintValue(0,4+ucBcl,0, (char*)"@"); + } + dsPrintValue(1,4+ucBcl,(ucSel == ucBcl ? 1 : 0),szName); + } + } + } +} + + +u8 pick_overlay(void) +{ + u8 bDone=false, bRet=false; + u16 ucHaut=0x00, ucBas=0x00,ucSHaut=0x00, ucSBas=0x00,ovlSelected= 0, firstOvlDisplay=0,nbRomPerPage, uNbRSPage; + u16 uLenFic=0, ucFlip=0, ucFlop=0; + + getcwd(originalPath, MAX_PATH); // Save where we started from... we will restore on the way out + + // Find and display all of the .ovl files in a directory + ovlFindFiles(); + + nbRomPerPage = (countovls>=17 ? 17 : countovls); + uNbRSPage = (countovls>=5 ? 5 : countovls); + + if (ucFicAct>countovls-nbRomPerPage) + { + firstOvlDisplay=countovls-nbRomPerPage; + ovlSelected=ucFicAct-countovls+nbRomPerPage; + } + else + { + firstOvlDisplay=ucFicAct; + ovlSelected=0; + } + OvlDisplayFiles(firstOvlDisplay,ovlSelected); + + // ----------------------------------------------------- + // Until the user selects a file or exits the menu... + // ----------------------------------------------------- + while (!bDone) + { + if (keysCurrent() & KEY_UP) + { + if (!ucHaut) + { + ucFicAct = (ucFicAct>0 ? ucFicAct-1 : countovls-1); + if (ovlSelected>uNbRSPage) { ovlSelected -= 1; } + else { + if (firstOvlDisplay>0) { firstOvlDisplay -= 1; } + else { + if (ovlSelected>0) { ovlSelected -= 1; } + else { + firstOvlDisplay=countovls-nbRomPerPage; + ovlSelected=nbRomPerPage-1; + } + } + } + ucHaut=0x01; + OvlDisplayFiles(firstOvlDisplay,ovlSelected); + } + else { + + ucHaut++; + if (ucHaut>10) ucHaut=0; + } + uLenFic=0; ucFlip=0; ucFlop=0; + } + else + { + ucHaut = 0; + } + if (keysCurrent() & KEY_DOWN) + { + if (!ucBas) { + ucFicAct = (ucFicAct< countovls-1 ? ucFicAct+1 : 0); + if (ovlSelected10) ucBas=0; + } + uLenFic=0; ucFlip=0; ucFlop=0; + } + else { + ucBas = 0; + } + + // ------------------------------------------------------------- + // Left and Right on the D-Pad will scroll 1 page at a time... + // ------------------------------------------------------------- + if (keysCurrent() & KEY_RIGHT) + { + if (!ucSBas) + { + ucFicAct = (ucFicAct< countovls-nbRomPerPage ? ucFicAct+nbRomPerPage : countovls-nbRomPerPage); + if (firstOvlDisplay10) ucSBas=0; + } + uLenFic=0; ucFlip=0; ucFlop=0; + } + else {ucSBas = 0;} + + // ------------------------------------------------------------- + // Left and Right on the D-Pad will scroll 1 page at a time... + // ------------------------------------------------------------- + if (keysCurrent() & KEY_LEFT) + { + if (!ucSHaut) + { + ucFicAct = (ucFicAct> nbRomPerPage ? ucFicAct-nbRomPerPage : 0); + if (firstOvlDisplay>nbRomPerPage) { firstOvlDisplay -= nbRomPerPage; } + else { firstOvlDisplay = 0; } + if (ucFicAct == 0) ovlSelected = 0; + if (ovlSelected > ucFicAct) ovlSelected = ucFicAct; + ucSHaut=0x01; + OvlDisplayFiles(firstOvlDisplay,ovlSelected); + } + else + { + ucSHaut++; + if (ucSHaut>10) ucSHaut=0; + } + uLenFic=0; ucFlip=0; ucFlop=0; + } + else { + ucSHaut = 0; + } + + // ------------------------------------------------------------------------- + // They B key will exit out of the ROM selection without picking a new game + // ------------------------------------------------------------------------- + if ( keysCurrent() & KEY_B ) + { + bDone=true; + while (keysCurrent() & KEY_B); + } + + // ------------------------------------------------------------ + // The DS 'A' key will pick the overlay and try to load it... + // ------------------------------------------------------------ + if (keysCurrent() & KEY_A) + { + // If the user picked an actual .ovl filename... use it!! + if (!overlayfiles[ucFicAct].directory) + { + currentRip->SetOverlayName(overlayfiles[ucFicAct].filename); + bDone = 1; + } + else // It's a directory - switch into it + { + chdir(overlayfiles[ucFicAct].filename); + ovlFindFiles(); + ucFicAct = 0; + nbRomPerPage = (countovls>=16 ? 16 : countovls); + uNbRSPage = (countovls>=5 ? 5 : countovls); + if (ucFicAct>countovls-nbRomPerPage) + { + firstOvlDisplay=countovls-nbRomPerPage; + ovlSelected=ucFicAct-countovls+nbRomPerPage; + } + else + { + firstOvlDisplay=ucFicAct; + ovlSelected=0; + } + OvlDisplayFiles(firstOvlDisplay,ovlSelected); + while (keysCurrent() & KEY_A); + } + } + + // -------------------------------------------- + // If the filename is too long... scroll it. + // -------------------------------------------- + if (strlen(overlayfiles[ucFicAct].filename) > 29) + { + if (++ucFlip >= 15) + { + ucFlip = 0; + if ((++uLenFic+29)>strlen(overlayfiles[ucFicAct].filename)) + { + if (++ucFlop >= 15) {uLenFic=0;ucFlop = 0;} + else uLenFic--; + } + strncpy(szName,overlayfiles[ucFicAct].filename+uLenFic,29); + szName[29] = '\0'; + dsPrintValue(1,4+ovlSelected,1,szName); + } + } + swiWaitForVBlank(); + } + + // ---------------------------------------------------------------------- + // We are going back to the main emulation now - restore bottom screen. + // ---------------------------------------------------------------------- + chdir(originalPath); + dsShowScreenMain(false, false); + + return 1; // Tell the caller to load the new overlay (even if it's just the old overlay) +} + +// ------------------------------------------------------------------------------- +// Does this overlay support multiple images/maps? If so, this is a multi-overlay +// and we can move to the next overlay image - this will re-read the .ovl file +// and load up the right graphics and key-map hotspots... woot! +// ------------------------------------------------------------------------------- +void swap_overlay(void) +{ + if (multi_ovls > 1) + { + multi_ovl_idx = (multi_ovl_idx + 1) % multi_ovls; + if (bmulti_LR) + { + myConfig.controller_type = multi_ovl_idx; + } + load_custom_overlay(true); // This will try to load the correct overlay for this game or else default to the generic keyboard overlay + } } // End of Line diff --git a/arm9/source/overlay.h b/arm9/source/overlay.h index 232096a..78ba28b 100644 --- a/arm9/source/overlay.h +++ b/arm9/source/overlay.h @@ -55,18 +55,20 @@ struct Overlay_t #define OVL_META_MANUAL 23 #define OVL_META_DISC 24 #define OVL_META_KEYBOARD 25 +#define OVL_META_SWAPOVL 26 // Used for multi-overlay games (Triple Challenge, Mr BASIC, etc) // These are not likely mapped anywhere... keep them near the back end -#define OVL_META_DISC_UP 26 -#define OVL_META_DISC_DN 27 -#define OVL_META_SPEEDUP 28 -#define OVL_META_FASTLOAD 29 -#define OVL_META_STRETCH 30 -#define OVL_META_GCONFIG 31 -#define OVL_META_CHEATS 32 -#define OVL_META_EMUINFO 33 +#define OVL_META_DISC_UP 27 +#define OVL_META_DISC_DN 28 +#define OVL_META_SPEEDUP 29 +#define OVL_META_FASTLOAD 30 +#define OVL_META_STRETCH 31 +#define OVL_META_GCONFIG 32 +#define OVL_META_CHEATS 33 +#define OVL_META_EMUINFO 34 +#define OVL_META_PICKOVL 35 // Let the user pick any .ovl file -#define OVL_MAX 34 +#define OVL_MAX 36 #define DISC_MAX 16 @@ -82,5 +84,7 @@ extern struct Overlay_t myDisc[DISC_MAX]; extern void load_custom_overlay(void); extern void show_overlay(u8 bShowKeyboard, u8 bShowDisc); +extern u8 pick_overlay(void); +extern void swap_overlay(void); #endif diff --git a/arm9/source/savestate.cpp b/arm9/source/savestate.cpp index 6e7ec97..7278685 100644 --- a/arm9/source/savestate.cpp +++ b/arm9/source/savestate.cpp @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, its source code and associated // readme files, with or without modification, are permitted in any medium without diff --git a/extras.zip b/extras.zip index c7203d3..976a860 100644 Binary files a/extras.zip and b/extras.zip differ diff --git a/extras/overlays/empty.ovl b/extras/overlays/empty.ovl index eaddc33..88c0123 100644 --- a/extras/overlays/empty.ovl +++ b/extras/overlays/empty.ovl @@ -29,6 +29,7 @@ .ovl 255, 255, 255, 255, // META_MANUAL .ovl 50, 86, 161, 191, // META_DISC .ovl 8, 49, 161, 191, // META_KEYBOARD + .ovl 255, 255, 255, 255, // META_SWAPOVL .tile 0x00B8C010,0xF000003C,0xF001F001,0x73095001,0x01F0F273,0x01F001F0,0xCD1A0950,0x80310110