proof-of-concept system for GBA slot addons

This commit is contained in:
Arisotura 2022-01-03 10:05:37 +01:00
parent cdff61c209
commit 46656eccda
10 changed files with 246 additions and 78 deletions

View File

@ -530,9 +530,6 @@ void SoftReset()
NDS::MapSharedWRAM(3);
// FIXME!!!!!
//memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000);
// TODO: does the DSP get reset? NWRAM doesn't, so I'm assuming no
// *HOWEVER*, the bootrom (which does get rerun) does remap NWRAM, and thus
// the DSP most likely gets reset
@ -548,9 +545,6 @@ void SoftReset()
DSi_AES::Reset();
//NDS::ARM9->JumpTo(BootAddr[0]);
//NDS::ARM7->JumpTo(BootAddr[1]);
SCFG_BIOS = 0x0101; // TODO: should be zero when booting from BIOS
SCFG_Clock9 = 0x0187; // CHECKME
SCFG_Clock7 = 0x0187;
@ -565,20 +559,6 @@ void SoftReset()
// LCD init flag
GPU::DispStat[0] |= (1<<6);
GPU::DispStat[1] |= (1<<6);
//for (u32 i = 0; i < 0x3C00; i+=4)
// ARM7Write32(0x03FFC400+i, *(u32*)&ARM7Init[i]);
u32 eaddr = 0x03FFE6E4;
ARM7Write32(eaddr+0x00, *(u32*)&eMMC_CID[0]);
ARM7Write32(eaddr+0x04, *(u32*)&eMMC_CID[4]);
ARM7Write32(eaddr+0x08, *(u32*)&eMMC_CID[8]);
ARM7Write32(eaddr+0x0C, *(u32*)&eMMC_CID[12]);
ARM7Write16(eaddr+0x2C, 0x0001);
ARM7Write16(eaddr+0x2E, 0x0001);
ARM7Write16(eaddr+0x3C, 0x0100);
ARM7Write16(eaddr+0x3E, 0x40E0);
ARM7Write16(eaddr+0x42, 0x0001);
}
bool LoadBIOS()

View File

@ -18,6 +18,7 @@
#include <stdio.h>
#include <string.h>
#include "NDS.h"
#include "GBACart.h"
#include "CRC32.h"
#include "Platform.h"
@ -58,6 +59,10 @@ CartCommon::~CartCommon()
{
}
void CartCommon::Reset()
{
}
void CartCommon::DoSavestate(Savestate* file)
{
file->Section("GBCS");
@ -107,7 +112,16 @@ CartGame::CartGame(u8* rom, u32 len) : CartCommon()
{
ROM = rom;
ROMLength = len;
}
CartGame::~CartGame()
{
//if (SRAMFile) fclose(SRAMFile);
if (SRAM) delete[] SRAM;
}
void CartGame::Reset()
{
memset(&GPIO, 0, sizeof(GPIO));
SRAM = nullptr;
@ -117,12 +131,6 @@ CartGame::CartGame(u8* rom, u32 len) : CartCommon()
SRAMFlashState = {};
}
CartGame::~CartGame()
{
//if (SRAMFile) fclose(SRAMFile);
if (SRAM) delete[] SRAM;
}
void CartGame::DoSavestate(Savestate* file)
{
CartCommon::DoSavestate(file);
@ -554,16 +562,20 @@ const int CartGameSolarSensor::kLuxLevels[11] = {0, 5, 11, 18, 27, 42, 62, 84, 1
CartGameSolarSensor::CartGameSolarSensor(u8* rom, u32 len) : CartGame(rom, len)
{
LightEdge = false;
LightCounter = 0;
LightSample = 0xFF;
LightLevel = 0;
}
CartGameSolarSensor::~CartGameSolarSensor()
{
}
void CartGameSolarSensor::Reset()
{
LightEdge = false;
LightCounter = 0;
LightSample = 0xFF;
LightLevel = 0;
}
void CartGameSolarSensor::DoSavestate(Savestate* file)
{
CartGame::DoSavestate(file);
@ -618,6 +630,86 @@ void CartGameSolarSensor::ProcessGPIO()
}
CartRAMExpansion::CartRAMExpansion() : CartCommon()
{
}
CartRAMExpansion::~CartRAMExpansion()
{
}
void CartRAMExpansion::Reset()
{
memset(RAM, 0xFF, sizeof(RAM));
RAMEnable = 1;
}
void CartRAMExpansion::DoSavestate(Savestate* file)
{
CartCommon::DoSavestate(file);
file->VarArray(RAM, sizeof(RAM));
file->Var16(&RAMEnable);
}
u16 CartRAMExpansion::ROMRead(u32 addr)
{
addr &= 0x01FFFFFF;
if (addr < 0x01000000)
{
switch (addr)
{
case 0xB0: return 0xFFFF;
case 0xB2: return 0x0000;
case 0xB4: return 0x2400;
case 0xB6: return 0x2424;
case 0xB8: return 0xFFFF;
case 0xBA: return 0xFFFF;
case 0xBC: return 0xFFFF;
case 0xBE: return 0x7FFF;
case 0x1FFFC: return 0xFFFF;
case 0x1FFFE: return 0x7FFF;
case 0x240000: return RAMEnable;
case 0x240002: return 0x0000;
}
return 0xFFFF;
}
else if (addr < 0x01800000)
{
if (!RAMEnable) return 0xFFFF;
return *(u16*)&RAM[addr & 0x7FFFFF];
}
return 0xFFFF;
}
void CartRAMExpansion::ROMWrite(u32 addr, u16 val)
{
addr &= 0x01FFFFFF;
if (addr < 0x01000000)
{
switch (addr)
{
case 0x240000:
RAMEnable = val & 0x0001;
return;
}
}
else if (addr < 0x01800000)
{
if (!RAMEnable) return;
*(u16*)&RAM[addr & 0x7FFFFF] = val;
}
}
bool Init()
{
CartROM = nullptr;
@ -636,30 +728,7 @@ void DeInit()
void Reset()
{
// Do not reset cartridge ROM.
// Prefer keeping the inserted cartridge on reset.
// This allows resetting a DS game without losing GBA state,
// and resetting to firmware without the slot being emptied.
// The Stop function will clear the cartridge state via Eject().
// OpenBusDecay doesn't need to be reset, either, as it will be set
// through NDS::SetGBASlotTimings().
}
void Eject()
{
if (Cart) delete Cart;
Cart = nullptr;
if (CartROM) delete[] CartROM;
CartInserted = false;
CartROM = NULL;
CartROMSize = 0;
CartCRC = 0;
CartID = 0;
Reset();
if (Cart) Cart->Reset();
}
void DoSavestate(Savestate* file)
@ -672,10 +741,10 @@ void DoSavestate(Savestate* file)
// since unlike with DS, it's not loaded in advance
file->Var32(&CartROMSize);
if (!CartROMSize) // no GBA cartridge state? nothing to do here
if (!CartROMSize) // no GBA cartridge state? nothing to do here (no! FIXME)
{
// do eject the cartridge if something is inserted
Eject();
EjectCart();
return;
}
@ -760,6 +829,9 @@ bool LoadROM(const u8* romdata, u32 romlen)
else
Cart = new CartGame(CartROM, CartROMSize);
if (Cart)
Cart->Reset();
// save
//printf("GBA save file: %s\n", sram);
@ -782,6 +854,40 @@ void LoadSave(const u8* savedata, u32 savelen)
}
}
void LoadAddon(int type)
{
CartROMSize = 0;
CartROM = nullptr;
CartCRC = 0;
switch (type)
{
case NDS::GBAAddon_RAMExpansion:
Cart = new CartRAMExpansion();
break;
default:
printf("GBACart: !! invalid addon type %d\n", type);
return;
}
CartInserted = true;
}
void EjectCart()
{
if (Cart) delete Cart;
Cart = nullptr;
if (CartROM) delete[] CartROM;
CartInserted = false;
CartROM = nullptr;
CartROMSize = 0;
CartCRC = 0;
CartID = 0;
}
/*bool LoadROM(const char* path, const char* sram)
{
FILE* f = Platform::OpenFile(path, "rb");

View File

@ -31,6 +31,7 @@ class CartCommon
public:
CartCommon();
virtual ~CartCommon();
virtual void Reset();
virtual void DoSavestate(Savestate* file);
@ -54,6 +55,7 @@ class CartGame : public CartCommon
public:
CartGame(u8* rom, u32 len);
virtual ~CartGame() override;
virtual void Reset() override;
virtual void DoSavestate(Savestate* file) override;
@ -124,6 +126,7 @@ class CartGameSolarSensor : public CartGame
public:
CartGameSolarSensor(u8* rom, u32 len);
virtual ~CartGameSolarSensor() override;
virtual void Reset() override;
virtual void DoSavestate(Savestate* file) override;
@ -140,6 +143,24 @@ private:
u8 LightLevel;
};
// CartRAMExpansion -- RAM expansion cart (DS browser, ...)
class CartRAMExpansion : public CartCommon
{
public:
CartRAMExpansion();
~CartRAMExpansion() override;
void Reset() override;
void DoSavestate(Savestate* file) override;
u16 ROMRead(u32 addr) override;
void ROMWrite(u32 addr, u16 val) override;
private:
u8 RAM[0x800000];
u16 RAMEnable;
};
// possible inputs for GBA carts that might accept user input
enum
{
@ -155,13 +176,16 @@ extern u32 CartCRC;
bool Init();
void DeInit();
void Reset();
void Eject();
void DoSavestate(Savestate* file);
bool LoadROM(const u8* romdata, u32 romlen);
void LoadSave(const u8* savedata, u32 savelen);
void LoadAddon(int type);
void EjectCart();
//bool LoadROM(const char* path, const char* sram);
//bool LoadROM(const u8* romdata, u32 filelength, const char *sram);
//void RelocateSave(const char* path, bool write);

View File

@ -943,13 +943,16 @@ bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen)
if (savedata && savelen)
GBACart::LoadSave(savedata, savelen);
}
//Running = true;
void LoadGBAAddon(int type)
{
GBACart::LoadAddon(type);
}
void EjectGBACart()
{
printf("TODO!!!!\n");
GBACart::EjectCart();
}
/*bool LoadROM(const u8* romdata, u32 filelength, const char *sram, bool direct)

View File

@ -164,6 +164,12 @@ struct MemRegion
u32 Mask;
};
// supported GBA slot addon types
enum
{
GBAAddon_RAMExpansion = 1,
};
#ifdef JIT_ENABLED
extern bool EnableJIT;
#endif
@ -246,6 +252,7 @@ bool NeedsDirectBoot();
void SetupDirectBoot(std::string romname);
bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen);
void LoadGBAAddon(int type);
void EjectGBACart();
//void RelocateSave(const char* path, bool write);

View File

@ -320,7 +320,7 @@ int LoadROM(const u8 *romdata, u32 romlength, const char *archivefilename, const
res = SetupDSiNAND();
if (res != Load_OK) return res;
GBACart::Eject();
//GBACart::Eject();
ROMPath[ROMSlot_GBA] = "";
}
else
@ -398,7 +398,7 @@ int LoadROM(const char* file, int slot)
res = SetupDSiNAND();
if (res != Load_OK) return res;
GBACart::Eject();
//GBACart::Eject();
ROMPath[ROMSlot_GBA] = "";
}
else
@ -525,7 +525,7 @@ void UnloadROM(int slot)
}
else if (slot == ROMSlot_GBA)
{
GBACart::Eject();
// GBACart::Eject();
}
ROMPath[slot] = "";
@ -554,7 +554,7 @@ int Reset()
res = SetupDSiNAND();
if (res != Load_OK) return res;
GBACart::Eject();
// GBACart::Eject();
ROMPath[ROMSlot_GBA][0] = '\0';
}
else

View File

@ -44,6 +44,8 @@ std::string BaseROMDir;
std::string BaseROMName;
std::string BaseAssetName;
int GBACartType;
int LastSep(std::string path)
{
@ -256,6 +258,21 @@ QString VerifySetup()
}
void Reset()
{
NDS::SetConsoleType(Config::ConsoleType);
NDS::Reset();
if (!BaseROMName.empty())
{
if (Config::DirectBoot || NDS::NeedsDirectBoot())
{
NDS::SetupDirectBoot(BaseROMName);
}
}
}
bool LoadBIOS()
{
NDS::SetConsoleType(Config::ConsoleType);
@ -413,9 +430,25 @@ QString CartLabel()
void LoadGBAAddon(int type)
{
NDS::LoadGBAAddon(type);
GBACartType = type;
}
// PLACEHOLDER
QString GBACartLabel()
{
switch (GBACartType)
{
case 0:
return "it's a ROM (TODO)";
case NDS::GBAAddon_RAMExpansion:
return "Memory expansion";
}
return "(none)";
}

View File

@ -28,12 +28,15 @@ namespace ROMLoader
{
QString VerifySetup();
void Reset();
bool LoadBIOS();
bool LoadROM(QStringList filepath, bool reset);
void EjectCart();
QString CartLabel();
bool LoadGBAROM(QStringList filepath, bool reset);
void LoadGBAAddon(int type);
void EjectGBACart();
QString GBACartLabel();

View File

@ -1328,14 +1328,17 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
{
QMenu* submenu = menu->addMenu("Insert add-on cart");
actInsertGBAAddon[0] = submenu->addAction("Memory expansion");
/*actInsertGBAAddon[0] = submenu->addAction("Memory expansion");
actInsertGBAAddon[1] = submenu->addAction("Vibrator Pak");
actInsertGBAAddon[2] = submenu->addAction("Guitar Hero grip");
actInsertGBAAddon[3] = submenu->addAction("Fartslapper");
actInsertGBAAddon[4] = submenu->addAction("Fartslapper Mk. II");
actInsertGBAAddon[5] = submenu->addAction("Ghostbusters ray");
actInsertGBAAddon[6] = submenu->addAction("Fridge Pak");
actInsertGBAAddon[7] = submenu->addAction("Fazil");
actInsertGBAAddon[7] = submenu->addAction("Fazil");*/
actInsertGBAAddon[0] = submenu->addAction("Memory expansion");
actInsertGBAAddon[0]->setData(QVariant(NDS::GBAAddon_RAMExpansion));
connect(actInsertGBAAddon[0], &QAction::triggered, this, &MainWindow::onInsertGBAAddon);
}
actEjectGBACart = menu->addAction("Eject cart");
@ -2356,6 +2359,23 @@ void MainWindow::onEjectCart()
actEjectCart->setEnabled(false);
}
void MainWindow::onInsertGBAAddon()
{
QAction* act = (QAction*)sender();
int type = act->data().toInt();
printf("INSERT: %d\n", type);
emuThread->emuPause();
ROMLoader::LoadGBAAddon(type);
emuThread->emuUnpause();
actCurrentGBACart->setText("GBA slot: " + ROMLoader::GBACartLabel());
actEjectGBACart->setEnabled(true);
}
void MainWindow::onSaveState()
{
int slot = ((QAction*)sender())->data().toInt();
@ -2534,19 +2554,10 @@ void MainWindow::onReset()
actUndoStateLoad->setEnabled(false);
int res = Frontend::Reset();
if (res != Frontend::Load_OK)
{
QMessageBox::critical(this,
"melonDS",
loadErrorStr(res));
emuThread->emuUnpause();
}
else
{
OSD::AddMessage(0, "Reset");
emuThread->emuRun();
}
ROMLoader::Reset();
OSD::AddMessage(0, "Reset");
emuThread->emuRun();
}
void MainWindow::onStop()

View File

@ -235,6 +235,7 @@ private slots:
void onBootFirmware();
void onInsertCart();
void onEjectCart();
void onInsertGBAAddon();
void onSaveState();
void onLoadState();
void onUndoStateLoad();