proof-of-concept system for GBA slot addons
This commit is contained in:
parent
cdff61c209
commit
46656eccda
20
src/DSi.cpp
20
src/DSi.cpp
|
@ -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()
|
||||
|
|
178
src/GBACart.cpp
178
src/GBACart.cpp
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)";
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -235,6 +235,7 @@ private slots:
|
|||
void onBootFirmware();
|
||||
void onInsertCart();
|
||||
void onEjectCart();
|
||||
void onInsertGBAAddon();
|
||||
void onSaveState();
|
||||
void onLoadState();
|
||||
void onUndoStateLoad();
|
||||
|
|
Loading…
Reference in New Issue