Version 6.0 is released with new multi-overlay support!

This commit is contained in:
Dave Bernazzani 2025-01-01 08:36:52 -05:00
parent 3acc14b81f
commit cf1ecbd274
23 changed files with 649 additions and 159 deletions

View File

@ -14,7 +14,7 @@ include $(DEVKITARM)/ds_rules
export TARGET := NINTV-DS export TARGET := NINTV-DS
export TOPDIR := $(CURDIR) 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" ICON := -b $(CURDIR)/logo.bmp "NINTV-DS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/NINTV-DS"

Binary file not shown.

View File

@ -147,7 +147,7 @@ Missing / Known Issues :
License : 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 Copying and distribution of this emulator, its source code and associated
readme files, with or without modification, are permitted in any medium without readme files, with or without modification, are permitted in any medium without
@ -175,6 +175,12 @@ Credits :
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
History : 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 V5.9 : 27-Oct-2024 by wavemotion-dave
* Overlay overload... more than 220 custom Nintellivision overlays in the extras.zip pack. * Overlay overload... more than 220 custom Nintellivision overlays in the extras.zip pack.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // readme files, with or without modification, are permitted in any medium without

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // 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 == 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 == 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 == 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 == 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 if (crc == 0xD8C9856A) myConfig.dpad_config = DPAD_DIAGONALS; // Q-Bert is best with diagonal
@ -476,7 +480,7 @@ struct options_t
UINT8 option_max; 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] = const struct options_t Option_Table[3][20] =
{ {

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // 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}}}, {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}}}, {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}}}, {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}}}, {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}}}, {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}}}, {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}}},

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // readme files, with or without modification, are permitted in any medium without
@ -34,12 +34,6 @@
INT32 debug[DEBUG_SIZE] __attribute__((section(".dtcm"))) = {0}; 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 #ifdef DEBUG_ENABLE
UINT32 debug_opcodes=0; UINT32 debug_opcodes=0;

View File

@ -12,13 +12,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "CRC32.h" #include "CRC32.h"
#include "types.h"
#define CRC32_POLY 0x04C11DB7 #define CRC32_POLY 0x04C11DB7
#ifndef _MAX_PATH
#define _MAX_PATH 255
#endif
const UINT32 crc32_table[256] = { const UINT32 crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, // 0 [0x00 .. 0x07] 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, // 0 [0x00 .. 0x07]
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, // 8 [0x08 .. 0x0F] 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, // 8 [0x08 .. 0x0F]

View File

@ -92,6 +92,7 @@ Rip::Rip(UINT32 systemID)
crc(0) crc(0)
{ {
memset(filename, 0, sizeof(filename)); memset(filename, 0, sizeof(filename));
memset(overlayname, 0, sizeof(overlayname));
JLP16Bit = NULL; JLP16Bit = NULL;
} }
@ -157,7 +158,7 @@ void ForceLoadOptions(UINT32 crc)
} }
} }
char cfgFilename[128]; char cfgFilename[MAX_PATH];
Rip* Rip::LoadBin(const CHAR* filename) Rip* Rip::LoadBin(const CHAR* filename)
{ {
// Create the path to the .cfg file (which may or may not exist...) // Create the path to the .cfg file (which may or may not exist...)

View File

@ -61,6 +61,14 @@ public:
return this->filename; 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 GetCRC() { return this->crc; }
UINT32 GetSize() { return this->mySize; } UINT32 GetSize() { return this->mySize; }
JLP *JLP16Bit; JLP *JLP16Bit;
@ -71,8 +79,12 @@ private:
void AddPeripheralUsage(const CHAR* periphName, PeripheralCompatibility usage); void AddPeripheralUsage(const CHAR* periphName, PeripheralCompatibility usage);
static Rip* LoadBinCfg(const CHAR* cfgFile, UINT32 crc, size_t size); 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) { void SetFileName(const CHAR* fname) {
strncpy(this->filename, fname, sizeof(this->filename)); 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; UINT32 targetSystemID;
@ -82,6 +94,7 @@ private:
PeripheralCompatibility peripheralUsages[MAX_PERIPHERALS]; PeripheralCompatibility peripheralUsages[MAX_PERIPHERALS];
UINT32 peripheralCount; UINT32 peripheralCount;
CHAR filename[MAX_PATH]; CHAR filename[MAX_PATH];
CHAR overlayname[MAX_PATH];
UINT32 mySize; UINT32 mySize;
UINT32 crc; UINT32 crc;
}; };

View File

@ -96,7 +96,7 @@ typedef struct
#endif #endif
#ifndef MAX_PATH #ifndef MAX_PATH
#define MAX_PATH 256 #define MAX_PATH 167
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // readme files, with or without modification, are permitted in any medium without

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // 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. // We support up to 512 files per directory. More than enough.
// ------------------------------------------------------------- // -------------------------------------------------------------
FICA_INTV intvromlist[512]; FICA_INTV intvromlist[MAX_ROMS];
u16 countintv=0, ucFicAct=0; u16 countintv=0;
static u16 ucFicAct=0;
char szName[256]; char szName[256];
char szName2[256]; char szName2[256];
extern char directory[]; extern char directory[];
@ -63,7 +64,10 @@ BOOL LoadCart(const CHAR* filename)
bIsFatalError = false; bIsFatalError = false;
bGameLoaded = 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 // Clear out the debug array with every new game loaded
memset(debug, 0x00, DEBUG_SIZE * (sizeof(UINT32))); memset(debug, 0x00, DEBUG_SIZE * (sizeof(UINT32)));
@ -430,7 +434,7 @@ void intvFindFiles(void)
while (((pent=readdir(pdir))!=NULL)) while (((pent=readdir(pdir))!=NULL))
{ {
strcpy(szName2,pent->d_name); strcpy(szName2,pent->d_name);
szName2[127] = NULL; szName2[MAX_PATH-1] = NULL;
if (pent->d_type == DT_DIR) if (pent->d_type == DT_DIR)
{ {
if (!( (szName2[0] == '.') && (strlen(szName2) == 1))) if (!( (szName2[0] == '.') && (strlen(szName2) == 1)))

View File

@ -15,9 +15,11 @@
#include <nds.h> #include <nds.h>
#include "types.h" #include "types.h"
#define MAX_ROMS 512
typedef struct FICtoLoad typedef struct FICtoLoad
{ {
char filename[126]; char filename[MAX_PATH];
UINT8 directory; UINT8 directory;
UINT8 favorite; UINT8 favorite;
} FICA_INTV; } FICA_INTV;

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // readme files, with or without modification, are permitted in any medium without

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // 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_x = 3;
UINT8 hud_y = 0; UINT8 hud_y = 0;
UINT8 multi_ovls = 0;
UINT8 multi_ovl_idx = 0;
UINT8 bmulti_LR = 0;
UINT16 keypad_pressed = 0; UINT16 keypad_pressed = 0;
UINT16 ecs_debounce_timer = 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. // 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, "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, "Tutorvision: %s ", (bUseTutorvision ? "YES":"NO")); dsPrintValue(0, idx++, 0, tmpStr);
sprintf(tmpStr, "Total Frames: %-9u ", global_frames); 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, "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, "MEMS MAPPED: %-9d ", currentEmu->memoryBus.getMemCount());dsPrintValue(0, idx++, 0, tmpStr);
sprintf(tmpStr, "RIP ROM Count: %-9d ", currentRip->GetROMCount()); 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, "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, "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); 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 // so we now just store all the extra goodies in this menu... By default the SELECT
// button will bring this up. // button will bring this up.
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
#define MAIN_MENU_ITEMS 14 #define MAIN_MENU_ITEMS 15
const char *main_menu[MAIN_MENU_ITEMS] = const char *main_menu[MAIN_MENU_ITEMS] =
{ {
"RESET EMULATOR", "RESET EMULATOR",
@ -417,6 +446,7 @@ const char *main_menu[MAIN_MENU_ITEMS] =
"SCREEN STRETCH", "SCREEN STRETCH",
"SHOW DISC", "SHOW DISC",
"SHOW KEYBOARD", "SHOW KEYBOARD",
"PICK OVERLAY",
"QUIT EMULATOR", "QUIT EMULATOR",
"EXIT THIS MENU", "EXIT THIS MENU",
}; };
@ -430,7 +460,7 @@ int menu_entry(void)
dsShowBannerScreen(); dsShowBannerScreen();
swiWaitForVBlank(); swiWaitForVBlank();
dsPrintValue(8,3,0, (char*)"MAIN MENU"); 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<MAIN_MENU_ITEMS; i++) for (int i=0; i<MAIN_MENU_ITEMS; i++)
{ {
@ -502,9 +532,12 @@ int menu_entry(void)
return OVL_META_KEYBOARD; return OVL_META_KEYBOARD;
break; break;
case 12: case 12:
return OVL_META_QUIT; return OVL_META_PICKOVL;
break; break;
case 13: case 13:
return OVL_META_QUIT;
break;
case 14:
bDone=1; bDone=1;
break; break;
} }
@ -705,6 +738,19 @@ void ds_handle_meta(int meta_key)
show_overlay(bShowKeyboard, bShowDisc); show_overlay(bShowKeyboard, bShowDisc);
break; break;
case OVL_META_SWAPOVL:
swap_overlay();
break;
case OVL_META_PICKOVL:
if (pick_overlay()) // Let user select a new overlay... if they did we swap it in now
{
bShowDisc = 0;
bShowKeyboard = 0;
show_overlay(bShowKeyboard, bShowDisc);
}
break;
case OVL_META_FASTLOAD: case OVL_META_FASTLOAD:
{ {
void quick_load(void); void quick_load(void);
@ -820,6 +866,15 @@ UINT8 poll_touch_screen(UINT16 ctrl_disc, UINT16 ctrl_keys, UINT16 ctrl_side)
} }
WAITVBL; WAITVBL;
} }
// SWAP OVERLAY (for multi-overlay games)
else if (touch.px > 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 // And, finally, if the ECS keyboard is being shown, we must check for any presses on this virtual keyboard

View File

@ -28,6 +28,7 @@ extern UINT16 emu_frames;
extern UINT16 frames_per_sec_calc; extern UINT16 frames_per_sec_calc;
extern UINT8 oneSecTick; extern UINT8 oneSecTick;
extern UINT8 hud_x, hud_y; extern UINT8 hud_x, hud_y;
extern UINT8 multi_ovls, multi_ovl_idx, bmulti_LR;
extern UINT8 b_dsi_mode; extern UINT8 b_dsi_mode;

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // readme files, with or without modification, are permitted in any medium without
@ -30,6 +30,8 @@
#include "bgTop.h" #include "bgTop.h"
#include "Emulator.h" #include "Emulator.h"
#include "Rip.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...
@ -38,6 +40,14 @@
extern char szName[]; extern char szName[];
extern Rip *currentRip; 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. // This is the default overlay that matches the main non-custom overlay bottom screen.
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -74,6 +84,7 @@ struct Overlay_t defaultOverlay[OVL_MAX] =
{255, 255, 255, 255}, // META_MANUAL {255, 255, 255, 255}, // META_MANUAL
{ 50, 86, 161, 191}, // META_DISC { 50, 86, 161, 191}, // META_DISC
{ 8, 49, 161, 191}, // META_KEYBOARD { 8, 49, 161, 191}, // META_KEYBOARD
{255, 255, 255, 255}, // META_SWAPOVL
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -112,6 +123,7 @@ struct Overlay_t ecsOverlay[OVL_MAX] =
{255, 255, 255, 255}, // META_MANUAL {255, 255, 255, 255}, // META_MANUAL
{255, 255, 255, 255}, // META_DISC {255, 255, 255, 255}, // META_DISC
{255, 255, 255, 255}, // META_KEYBOARD {255, 255, 255, 255}, // META_KEYBOARD
{255, 255, 255, 255}, // META_SWAPOVL
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -150,6 +162,7 @@ struct Overlay_t discOverlay[OVL_MAX] =
{255, 255, 255, 255}, // META_MANUAL {255, 255, 255, 255}, // META_MANUAL
{255, 255, 255, 255}, // META_DISC {255, 255, 255, 255}, // META_DISC
{255, 255, 255, 255}, // META_KEYBOARD {255, 255, 255, 255}, // META_KEYBOARD
{255, 255, 255, 255}, // META_SWAPOVL
}; };
struct Overlay_t myOverlay[OVL_MAX]; struct Overlay_t myOverlay[OVL_MAX];
@ -163,8 +176,8 @@ 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 *customMap = (unsigned short *)0x0688F000; // 4K of video memory for the map (generally about 2.5K)
unsigned short customPal[512]; unsigned short customPal[512];
char directory[192]; char directory[192]; // Overlay directory
char filename[192]; char filename[192]; // Overlay filename
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -183,6 +196,7 @@ struct MapRomToOvl_t
struct MapRomToOvl_t MapRomToOvl[] = struct MapRomToOvl_t MapRomToOvl[] =
{ {
{0x9415dad4 , "2048", "2048", "2048.ovl"},
{0xD7C78754 , "4-TRIS", "4-TRIS", "4-TRIS.ovl"}, {0xD7C78754 , "4-TRIS", "4-TRIS", "4-TRIS.ovl"},
{0xB91488E2 , "4TRIS", "4TRIS", "4-TRIS.ovl"}, {0xB91488E2 , "4TRIS", "4TRIS", "4-TRIS.ovl"},
{0xA6E89A53 , "DRAGONS", "SWORDS", "A Tale of Dragons and Swords.ovl"}, {0xA6E89A53 , "DRAGONS", "SWORDS", "A Tale of Dragons and Swords.ovl"},
@ -214,6 +228,7 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0xC047D487 , "BEAUTY", "BEAST", "Beauty and the Beast.ovl"}, {0xC047D487 , "BEAUTY", "BEAST", "Beauty and the Beast.ovl"},
{0xFFFFFFFF , "BEAST", "SP", "BeautyBeast - SP.ovl"}, {0xFFFFFFFF , "BEAST", "SP", "BeautyBeast - SP.ovl"},
{0xB03F739B , "BLOCKADE", "RUNNER", "Blockade Runner.ovl"}, {0xB03F739B , "BLOCKADE", "RUNNER", "Blockade Runner.ovl"},
{0x515E1D7E , "BODY", "SLAM", "Body Slam - Super Pro Wrestling.ovl"},
{0x32697B72 , "BOMB", "SQUAD", "Bomb Squad.ovl"}, {0x32697B72 , "BOMB", "SQUAD", "Bomb Squad.ovl"},
{0xAB87C16F , "BOXING", "BOXING", "Boxing.ovl"}, {0xAB87C16F , "BOXING", "BOXING", "Boxing.ovl"},
{0xF8E5398D , "BUCK", "ROGERS", "Buck Rogers.ovl"}, {0xF8E5398D , "BUCK", "ROGERS", "Buck Rogers.ovl"},
@ -301,6 +316,7 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0x573B9B6D , "MASTERS", "UNIVERSE", "Masters of the Universe - The Power of He-Man.ovl"}, {0x573B9B6D , "MASTERS", "UNIVERSE", "Masters of the Universe - The Power of He-Man.ovl"},
{0xEB4383E0 , "MAXIT", "MAXIT", "Maxit.ovl"}, {0xEB4383E0 , "MAXIT", "MAXIT", "Maxit.ovl"},
{0x7A558CF5 , "MAZE", "TRON", "Maze-A-Tron.ovl"}, {0x7A558CF5 , "MAZE", "TRON", "Maze-A-Tron.ovl"},
{0xFF68AA22, "MELODY", "BLASTER", "Melody Blaster.ovl"},
{0xE806AD91 , "MICRO", "SURGEON", "Microsurgeon.ovl"}, {0xE806AD91 , "MICRO", "SURGEON", "Microsurgeon.ovl"},
{0x9D57498F , "MIND", "STRIKE", "Mind Strike.ovl"}, {0x9D57498F , "MIND", "STRIKE", "Mind Strike.ovl"},
{0xec2e2320 , "MISSILE", "DOMINATION", "Missile Domination.ovl"}, {0xec2e2320 , "MISSILE", "DOMINATION", "Missile Domination.ovl"},
@ -312,9 +328,12 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0xDBAB54CA , "NASL", "SOCCER", "NASL Soccer.ovl"}, {0xDBAB54CA , "NASL", "SOCCER", "NASL Soccer.ovl"},
{0x09dc0db2 , "NINJA", "ODYSSEY", "Ninja Odyssey.ovl"}, {0x09dc0db2 , "NINJA", "ODYSSEY", "Ninja Odyssey.ovl"},
{0x4B91CF16 , "NFL", "FOOTBALL", "NFL Football.ovl"}, {0x4B91CF16 , "NFL", "FOOTBALL", "NFL Football.ovl"},
{0x76564A13 , "NHL", "HOCKEY", "NHL Hockey.ovl"},
{0x613e109b , "JR", "PAC", "Jr Pac-Man.ovl"}, {0x613e109b , "JR", "PAC", "Jr Pac-Man.ovl"},
{0xBEF0B0C7 , "MR", "BASIC", "MrBASIC.ovl"},
{0x0753544F , "MS", "PAC", "Ms Pac-Man.ovl"}, {0x0753544F , "MS", "PAC", "Ms Pac-Man.ovl"},
{0x7334CD44 , "NIGHT", "STALKER", "Night Stalker.ovl"}, {0x7334CD44 , "NIGHT", "STALKER", "Night Stalker.ovl"},
{0x6B5EA9C4 , "MOUNTAIN", "MADNESS", "Mountain Madness - Super Pro Skiing.ovl"},
{0xFFFFFFFF , "MSTALKER", "MSTALKER", "Night Stalker.ovl"}, {0xFFFFFFFF , "MSTALKER", "MSTALKER", "Night Stalker.ovl"},
{0x5EE2CC2A , "NOVA", "BLAST", "Nova Blast.ovl"}, {0x5EE2CC2A , "NOVA", "BLAST", "Nova Blast.ovl"},
{0xFFFFFFFF , "OLD", "SCHOOL", "Old School.ovl"}, {0xFFFFFFFF , "OLD", "SCHOOL", "Old School.ovl"},
@ -365,7 +384,6 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0x8F7D3069 , "SUPER", "COBRA", "Super Cobra.ovl"}, {0x8F7D3069 , "SUPER", "COBRA", "Super Cobra.ovl"},
{0x7C32C9B8 , "SUPER", "COBRA", "Super Cobra.ovl"}, {0x7C32C9B8 , "SUPER", "COBRA", "Super Cobra.ovl"},
{0xe9e3f60d , "MAZE", "CHASE", "Scooby Doo's Maze Chase.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"}, {0xFFFFFFFF , "SCOOBY", "DOO", "Scooby Doo's Maze Chase.ovl"},
{0x99AE29A9 , "SEA", "BATTLE", "Sea Battle.ovl"}, {0x99AE29A9 , "SEA", "BATTLE", "Sea Battle.ovl"},
{0x2A4C761D , "SHARK!", "SHARK!", "Shark! Shark!.ovl"}, {0x2A4C761D , "SHARK!", "SHARK!", "Shark! Shark!.ovl"},
@ -398,11 +416,13 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0xD6F44FA5 , "TNT", "COWBOY", "TNT Cowboy.ovl"}, {0xD6F44FA5 , "TNT", "COWBOY", "TNT Cowboy.ovl"},
{0xCA447BBD , "DEADLY", "DISCS", "TRON Deadly Discs.ovl"}, {0xCA447BBD , "DEADLY", "DISCS", "TRON Deadly Discs.ovl"},
{0xFFFFFFFF , "DEADLIER", "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"}, {0x07FB9435 , "SOLAR", "SAILOR", "TRON Solar Sailor.ovl"},
{0xbb759a58 , "SOLAR", "SAILER", "TRON Solar Sailor.ovl"}, {0xbb759a58 , "SOLAR", "SAILER", "TRON Solar Sailor.ovl"},
{0xFFFFFFFF , "TRON", "SOLAR", "TRON Solar Sailor.ovl"}, {0xFFFFFFFF , "TRON", "SOLAR", "TRON Solar Sailor.ovl"},
{0x4c963cb2 , "TENNIS2", "TENNIS2", "Super Pro Tennis.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"}, {0x03E9E62E , "TENNIS", "TENNIS", "Tennis.ovl"},
{0xB7923858 , "SHOW", "MUST", "The Show Must Go On.ovl"}, {0xB7923858 , "SHOW", "MUST", "The Show Must Go On.ovl"},
{0xF3DF94E0 , "THIN", "ICE", "Thin Ice.ovl"}, {0xF3DF94E0 , "THIN", "ICE", "Thin Ice.ovl"},
@ -415,6 +435,7 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0xD1D352A0 , "TOWER", "DOOM", "Tower of Doom.ovl"}, {0xD1D352A0 , "TOWER", "DOOM", "Tower of Doom.ovl"},
{0x734F3260 , "TRUCKIN", "TRUCKIN", "Truckin.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"}, {0x6FA698B3 , "TUTANKHAM", "TUTANKHAM", "Tutankham.ovl"},
{0x275F3512 , "TURBO", "COLECO", "Turbo.ovl"}, {0x275F3512 , "TURBO", "COLECO", "Turbo.ovl"},
{0x752FD927 , "USCF", "CHESS", "USCF Chess.ovl"}, {0x752FD927 , "USCF", "CHESS", "USCF Chess.ovl"},
@ -455,19 +476,17 @@ struct MapRomToOvl_t MapRomToOvl[] =
{0x7fd5d202 , "DEATH", "STRIKE", "Death Star Strike.ovl"}, {0x7fd5d202 , "DEATH", "STRIKE", "Death Star Strike.ovl"},
{0x8ae91ade , "ISTAR", "ISTAR", "istar.ovl"}, {0x8ae91ade , "ISTAR", "ISTAR", "istar.ovl"},
{0xa1b83fdb , "ONION", "ONION", "Onion.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"}, {0x00000000 , "xxx", "zzz", "generic.ovl"},
}; };
// ----------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// Custom overlays are read in and must be in a very strict format. See the documenatation // Get the directory in which the .ovl files are located... this is set in Global Config
// 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 get_ovl_directory(void)
// -----------------------------------------------------------------------------------------------
void load_custom_overlay(bool bCustomGeneric)
{ {
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... // getting the root folder where overlays are stored...
@ -488,60 +507,97 @@ void load_custom_overlay(bool bCustomGeneric)
{ {
strcpy(directory, "./"); // In: Same DIR as ROM files 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; u8 bFound = 0;
// If we have a game (RIP) loaded, try to find a matching overlay // If we have a game (RIP) loaded, try to find a matching overlay
if (currentRip != NULL) if (currentRip != NULL)
{ {
strcpy(filename, directory); // If user picked the special 'Generic Overlay' we force the generic overlay to be used instead...
strcat(filename, currentRip->GetFileName()); if (strcmp(currentRip->GetOverlayName(), "--Generic Overlay--") != 0)
filename[strlen(filename)-4] = 0;
strcat(filename, ".ovl");
fp = fopen(filename, "rb");
if (fp != NULL) // If file found
{ {
bFound = 1; strcpy(filename, directory);
} strcat(filename, currentRip->GetOverlayName());
else // Not found... try to find it using the RomToOvl[] table fp = fopen(filename, "rb");
{ if (fp != NULL) // If file found
UINT16 i=0;
while (MapRomToOvl[i].crc != 0x00000000)
{ {
if (MapRomToOvl[i].crc == currentRip->GetCRC()) bFound = 1;
{
strcpy(filename, directory);
strcat(filename, MapRomToOvl[i].ovl_filename);
fp = fopen(filename, "rb");
if (fp != NULL) bFound = 1;
break;
}
i++;
} }
else // Not found... try to find it using the RomToOvl[] table
// If still not found after searching for CRC32... try fuzzy name search...
if (!bFound)
{ {
UINT16 i=0; UINT16 i=0;
while (MapRomToOvl[i].crc != 0x00000000) while (MapRomToOvl[i].crc != 0x00000000)
{ {
// It has to match both string searches to be valid... Uppercase for the compare... if (MapRomToOvl[i].crc == currentRip->GetCRC())
strcpy(szName, currentRip->GetFileName());
for (int j=0; j<strlen(szName); j++) szName[j] = toupper(szName[j]);
if ((strstr(szName, MapRomToOvl[i].search1) != NULL) && (strstr(szName, MapRomToOvl[i].search2) != NULL))
{ {
strcpy(filename, directory); strcpy(filename, directory);
strcat(filename, MapRomToOvl[i].ovl_filename); strcat(filename, MapRomToOvl[i].ovl_filename);
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if (fp != NULL) bFound = 1; if (fp != NULL) {bFound = 1;}
break; break;
} }
i++; 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<strlen(szName); j++) szName[j] = toupper(szName[j]);
if ((strstr(szName, MapRomToOvl[i].search1) != NULL) && (strstr(szName, MapRomToOvl[i].search2) != NULL))
{
strcpy(filename, directory);
strcat(filename, MapRomToOvl[i].ovl_filename);
fp = fopen(filename, "rb");
if (fp != NULL) {bFound = 1;}
break;
}
i++;
}
}
} }
} }
} }
if (bFound == 0) if (bFound == 0)
{ {
strcpy(filename, directory); strcpy(filename, directory);
@ -569,18 +625,19 @@ void load_custom_overlay(bool bCustomGeneric)
char *token; char *token;
memset(customTiles, 0x00, 0x10000); // Clear the 64K of video memory to prep for custom tiles... memset(customTiles, 0x00, 0x10000); // Clear the 64K of video memory to prep for custom tiles...
memcpy(&myOverlay, &discOverlay, sizeof(myOverlay)); // Start with a blank overlay... memcpy(&myOverlay, &discOverlay, sizeof(myOverlay)); // Start with a blank overlay...
do do
{ {
// Get one line of the .ovl file and try to parse it...
fgets(szName, 255, fp); fgets(szName, 255, fp);
// Handle Overlay Line // Handle Overlay Line
if (strstr(szName, ".ovl") != NULL) if (strstr(szName, ovl_str) != NULL)
{ {
if (ov_idx < OVL_MAX) if (ov_idx < OVL_MAX)
{ {
char *ptr = strstr(szName, ".ovl"); char *ptr = strstr(szName, ovl_str);
ptr += 5; ptr += 5;
myOverlay[ov_idx].x1 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++; myOverlay[ov_idx].x1 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++;
myOverlay[ov_idx].x2 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++; myOverlay[ov_idx].x2 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++;
@ -591,12 +648,12 @@ void load_custom_overlay(bool bCustomGeneric)
} }
// Handle Disc Line // Handle Disc Line
if (strstr(szName, ".disc") != NULL) if (strstr(szName, disc_str) != NULL)
{ {
bUseDiscOverlay = true; bUseDiscOverlay = true;
if (disc_idx < DISC_MAX) if (disc_idx < DISC_MAX)
{ {
char *ptr = strstr(szName, ".disc"); char *ptr = strstr(szName, disc_str);
ptr += 6; ptr += 6;
myDisc[disc_idx].x1 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++; myDisc[disc_idx].x1 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++;
myDisc[disc_idx].x2 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++; myDisc[disc_idx].x2 = strtoul(ptr, &ptr, 10); while (*ptr == ',' || *ptr == ' ') ptr++;
@ -607,25 +664,43 @@ void load_custom_overlay(bool bCustomGeneric)
} }
// Handle HUD_x Line // Handle HUD_x Line
if (strstr(szName, ".hudx") != NULL) if (strstr(szName, hudx_str) != NULL)
{ {
char *ptr = strstr(szName, ".hudx"); char *ptr = strstr(szName, hudx_str);
ptr += 6; ptr += 6;
hud_x = strtoul(ptr, &ptr, 10); hud_x = strtoul(ptr, &ptr, 10);
} }
// Handle HUD_y Line // Handle HUD_y Line
if (strstr(szName, ".hudy") != NULL) if (strstr(szName, hudy_str) != NULL)
{ {
char *ptr = strstr(szName, ".hudy"); char *ptr = strstr(szName, hudy_str);
ptr += 6; ptr += 6;
hud_y = strtoul(ptr, &ptr, 10); hud_y = strtoul(ptr, &ptr, 10);
} }
// Handle Tile Line // Handle MULTI Line
if (strstr(szName, ".tile") != NULL) if (strstr(szName, ".multi") != NULL)
{ {
char *ptr = strstr(szName, ".tile"); char *ptr = strstr(szName, ".multi");
ptr += 7;
if (strstr(ptr, "LR") != NULL)
{
multi_ovls = 2;
bmulti_LR = 1;
}
else
{
bmulti_LR = 0;
multi_ovls = strtoul(ptr, &ptr, 10);
if (multi_ovls > 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; ptr += 6;
customTiles[tiles_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++; customTiles[tiles_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++;
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 // 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; ptr += 4;
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++; customMap[map_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++;
@ -653,9 +728,9 @@ void load_custom_overlay(bool bCustomGeneric)
} }
// Handle Palette Line // 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; ptr += 4;
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++; customPal[pal_idx++] = strtoul(ptr, &ptr, 16); while (*ptr == ',' || *ptr == ' ') ptr++;
@ -713,7 +788,7 @@ void show_overlay(u8 bShowKeyboard, u8 bShowDisc)
} }
else 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
} }
} }
@ -731,4 +806,337 @@ void show_overlay(u8 bShowKeyboard, u8 bShowDisc)
} }
} }
// --------------------------------------------------------------------------
// 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<countovls ? ">" : " "));
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 (ovlSelected<uNbRSPage-1) { ovlSelected += 1; }
else {
if (firstOvlDisplay<countovls-nbRomPerPage) { firstOvlDisplay += 1; }
else {
if (ovlSelected<nbRomPerPage-1) { ovlSelected += 1; }
else {
firstOvlDisplay=0;
ovlSelected=0;
}
}
}
ucBas=0x01;
OvlDisplayFiles(firstOvlDisplay,ovlSelected);
}
else
{
ucBas++;
if (ucBas>10) 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 (firstOvlDisplay<countovls-nbRomPerPage) { firstOvlDisplay += nbRomPerPage; }
else { firstOvlDisplay = countovls-nbRomPerPage; }
if (ucFicAct == countovls-nbRomPerPage) ovlSelected = 0;
ucSBas=0x01;
OvlDisplayFiles(firstOvlDisplay,ovlSelected);
}
else
{
ucSBas++;
if (ucSBas>10) 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 // End of Line

View File

@ -55,18 +55,20 @@ struct Overlay_t
#define OVL_META_MANUAL 23 #define OVL_META_MANUAL 23
#define OVL_META_DISC 24 #define OVL_META_DISC 24
#define OVL_META_KEYBOARD 25 #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 // These are not likely mapped anywhere... keep them near the back end
#define OVL_META_DISC_UP 26 #define OVL_META_DISC_UP 27
#define OVL_META_DISC_DN 27 #define OVL_META_DISC_DN 28
#define OVL_META_SPEEDUP 28 #define OVL_META_SPEEDUP 29
#define OVL_META_FASTLOAD 29 #define OVL_META_FASTLOAD 30
#define OVL_META_STRETCH 30 #define OVL_META_STRETCH 31
#define OVL_META_GCONFIG 31 #define OVL_META_GCONFIG 32
#define OVL_META_CHEATS 32 #define OVL_META_CHEATS 33
#define OVL_META_EMUINFO 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 #define DISC_MAX 16
@ -82,5 +84,7 @@ extern struct Overlay_t myDisc[DISC_MAX];
extern void load_custom_overlay(void); extern void load_custom_overlay(void);
extern void show_overlay(u8 bShowKeyboard, u8 bShowDisc); extern void show_overlay(u8 bShowKeyboard, u8 bShowDisc);
extern u8 pick_overlay(void);
extern void swap_overlay(void);
#endif #endif

View File

@ -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 // Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without // readme files, with or without modification, are permitted in any medium without

Binary file not shown.

View File

@ -29,6 +29,7 @@
.ovl 255, 255, 255, 255, // META_MANUAL .ovl 255, 255, 255, 255, // META_MANUAL
.ovl 50, 86, 161, 191, // META_DISC .ovl 50, 86, 161, 191, // META_DISC
.ovl 8, 49, 161, 191, // META_KEYBOARD .ovl 8, 49, 161, 191, // META_KEYBOARD
.ovl 255, 255, 255, 255, // META_SWAPOVL
.tile 0x00B8C010,0xF000003C,0xF001F001,0x73095001,0x01F0F273,0x01F001F0,0xCD1A0950,0x80310110 .tile 0x00B8C010,0xF000003C,0xF001F001,0x73095001,0x01F0F273,0x01F001F0,0xCD1A0950,0x80310110