run slot1 through a modular addon system

This commit is contained in:
zeromus 2010-07-21 05:47:05 +00:00
parent 295ffa90b1
commit 384c6bca66
15 changed files with 679 additions and 337 deletions

View File

@ -858,6 +858,7 @@ void MMU_Init(void) {
//MMU.bupmem.fp = NULL;
rtcInit();
addonsInit();
slot1Init();
if(Mic_Init() == FALSE)
INFO("Microphone init failed.\n");
else
@ -873,6 +874,7 @@ void MMU_DeInit(void) {
// fclose(MMU.bupmem.fp);
//mc_free(&MMU.bupmem);
addonsClose();
slot1Close();
Mic_DeInit();
}
@ -950,6 +952,7 @@ void MMU_Reset()
rtcInit();
partie = 1;
addonsReset();
slot1Close();
Mic_Reset();
MMU.gfx3dCycles = 0;
@ -1078,7 +1081,10 @@ static void execdiv() {
template<int PROCNUM>
void FASTCALL MMU_writeToGCControl(u32 val)
{
nds_dscard& card = MMU.dscard[PROCNUM];
const int TEST_PROCNUM = 0; //PROCNUM
nds_dscard& card = MMU.dscard[TEST_PROCNUM];
memcpy(&card.command[0], &MMU.MMU_MEM[TEST_PROCNUM][0x40][0x1A8], 8);
if(!(val & 0x80000000))
{
@ -1086,11 +1092,17 @@ void FASTCALL MMU_writeToGCControl(u32 val)
card.transfer_count = 0;
val &= 0x7F7FFFFF;
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val);
T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val);
return;
}
memcpy(&card.command[0], &MMU.MMU_MEM[PROCNUM][0x40][0x1A8], 8);
u32 shift = (val>>24&7);
if(shift == 7)
card.transfer_count = 1;
else if(shift == 0)
card.transfer_count = 0;
else
card.transfer_count = (0x100<<shift)/4;
switch (card.mode)
{
@ -1106,7 +1118,7 @@ void FASTCALL MMU_writeToGCControl(u32 val)
card.transfer_count = 0;
val &= 0x7F7FFFFF;
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val);
T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val);
return;
}
break;
@ -1115,156 +1127,35 @@ void FASTCALL MMU_writeToGCControl(u32 val)
break;
}
switch(card.command[0])
switch(card.command[0])
{
// Dummy
case 0x9F:
{
card.address = 0;
card.transfer_count = 0x800;
}
break;
case 0x9F: //Dummy
card.address = 0;
card.transfer_count = 0x800;
break;
// Nand Init
case 0x94:
{
card.address = 0;
card.transfer_count = 0x80;
}
break;
case 0x90: //Get ROM chip ID
break;
// Nand Error?
case 0xD6:
{
card.address = 0;
card.transfer_count = 1;
}
break;
// Nand Write? ---- PROGRAM for INTERNAL DATA MOVE/RANDOM DATA INPUT
//case 0x8B:
case 0x85:
{
card.address = 0;
//card.transfer_count = 0x80;
// needs for WarioWare D.I.Y - ingame saves don't work but game don't freeze in main menu
card.transfer_count = 0;
}
break;
// Data read
case 0x00:
case 0xB7:
{
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
card.transfer_count = 0x80;
}
break;
// Get ROM chip ID
case 0x90:
case 0xB8:
{
card.address = 0;
card.transfer_count = 1;
}
break;
// Switch to KEY1 mode
case 0x3C:
{
card.address = 0;
card.transfer_count = 0;
card.mode = CardMode_KEY1;
}
break;
// --- Ninja SD commands -------------------------------------
// NJSD init/reset
case 0x20:
{
card.address = 0;
card.transfer_count = 0;
}
break;
// NJSD_sendCLK()
case 0xE0:
{
card.address = 0;
card.transfer_count = 0;
NDS_makeInt(PROCNUM, 20);
}
break;
// NJSD_sendCMDN() / NJSD_sendCMDR()
case 0xF0:
case 0xF1:
switch (card.command[2])
{
// GO_IDLE_STATE
case 0x40:
card.address = 0;
card.transfer_count = 0;
NDS_makeInt(PROCNUM, 20);
break;
case 0x42: // ALL_SEND_CID
case 0x43: // SEND_RELATIVE_ADDR
case 0x47: // SELECT_CARD
case 0x49: // SEND_CSD
case 0x4D:
case 0x77: // APP_CMD
case 0x69: // SD_APP_OP_COND
card.address = 0;
card.transfer_count = 6;
NDS_makeInt(PROCNUM, 20);
break;
// SET_BLOCKLEN
case 0x50:
card.address = 0;
card.transfer_count = 6;
card.blocklen = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24);
NDS_makeInt(PROCNUM, 20);
break;
// READ_SINGLE_BLOCK
case 0x51:
card.address = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24);
card.transfer_count = (card.blocklen + 3) >> 2;
NDS_makeInt(PROCNUM, 20);
break;
}
break;
// --- Ninja SD commands end ---------------------------------
default:
{
INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
card.command[0], card.command[1], card.command[2], card.command[3],
card.command[4], card.command[5], card.command[6], card.command[7]);
INFO("FROM: %08X\n", (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr);
card.address = 0;
card.transfer_count = 0;
}
break;
case 0x3C: //Switch to KEY1 mode
card.mode = CardMode_KEY1;
break;
default:
//fall through to the special slot1 handler
slot1_device.write32(REG_GCROMCTRL,val);
break;
}
if(card.transfer_count == 0)
{
val &= 0x7F7FFFFF;
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val);
T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val);
return;
}
val |= 0x00800000;
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val);
T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val);
// Launch DMA if start flag was set to "DS Cart"
//printf("triggering card dma\n");
@ -1276,7 +1167,9 @@ void FASTCALL MMU_writeToGCControl(u32 val)
template<int PROCNUM>
u32 MMU_readFromGC()
{
nds_dscard& card = MMU.dscard[PROCNUM];
const int TEST_PROCNUM = 0; //PROCNUM
nds_dscard& card = MMU.dscard[TEST_PROCNUM];
u32 val = 0;
if(card.transfer_count == 0)
@ -1284,130 +1177,16 @@ u32 MMU_readFromGC()
switch(card.command[0])
{
// Dummy
case 0x9F:
case 0x9F: //Dummy
return 0xFFFFFFFF;
case 0x3C: //Switch to KEY1 mode
val = 0xFFFFFFFF;
break;
// Nand Init?
case 0x94:
val = 0; //Unsure what to return here so return 0 for now
break;
// Nand Status?
case 0xD6:
//0x80 == busy
// Made in Ore/WariWare D.I.Y. need set value to 0x80
val = 0x20; //0x20 == ready
break;
//case 0x8B:
case 0x85:
val = 0; //Unsure what to return here so return 0 for now
break;
// Data read
case 0x00:
case 0xB7:
{
// Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart
if((card.command[0] == 0xB7) && (card.address < 0x8000))
{
INFO("Read below 0x8000 (0x%04X) from: ARM%s %08X\n",
card.address, (PROCNUM ? "7":"9"), (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr);
card.address = (0x8000 + (card.address&0x1FF));
}
if(card.address >= gameInfo.romsize)
{
DEBUG_Notify.ReadBeyondEndOfCart(card.address,gameInfo.romsize);
val = 0xFFFFFFFF;
}
else
//but, this is actually handled by the cart rom buffer being oversized and full of 0xFF.
//is this a good idea? We think so.
val = T1ReadLong(MMU.CART_ROM, card.address & MMU.CART_ROM_MASK);
}
break;
// Get ROM chip ID
case 0x90:
case 0xB8:
{
// Note: the BIOS stores the chip ID in main memory
// Most games continuously compare the chip ID with
// the value in memory, probably to know if the card
// was removed.
// As DeSmuME boots directly from the game, the chip
// ID in main mem is zero and this value needs to be
// zero too.
//staff of kings verifies this (it also uses the arm7 IRQ 20)
if(nds.cardEjected)
val = 0xFFFFFFFF;
else val = 0x00000000;
}
break;
// Switch to KEY1 mode
case 0x3C:
val = 0xFFFFFFFF;
break;
// --- Ninja SD commands -------------------------------------
// NJSD_sendCMDN() / NJSD_sendCMDR()
case 0xF0:
case 0xF1:
switch (card.command[2])
{
// ALL_SEND_CID
case 0x42:
if (card.transfer_count == 2) val = 0x44534A4E;
else val = 0x00000000;
// SEND_RELATIVE_ADDR
case 0x43:
case 0x47:
case 0x49:
case 0x50:
val = 0x00000000;
break;
case 0x4D:
if (card.transfer_count == 2) val = 0x09000000;
else val = 0x00000000;
break;
// APP_CMD
case 0x77:
if (card.transfer_count == 2) val = 0x00000037;
else val = 0x00000000;
break;
// SD_APP_OP_COND
case 0x69:
if (card.transfer_count == 2) val = 0x00008000;
else val = 0x00000000;
break;
// READ_SINGLE_BLOCK
case 0x51:
val = 0x00000000;
break;
}
break;
// --- Ninja SD commands end ---------------------------------
default:
INFO("READ CARD command: %02X%02X%02X%02X% 02X%02X%02X%02X\t",
card.command[0], card.command[1], card.command[2], card.command[3],
card.command[4], card.command[5], card.command[6], card.command[7]);
INFO("FROM: %08X\n", (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr);
val = slot1_device.read32(REG_GCDATAIN);
break;
}
card.address += 4; // increment address
@ -1417,77 +1196,17 @@ u32 MMU_readFromGC()
return val; // return data
// transfer is done
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4,
T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4) & 0x7F7FFFFF);
T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4,
T1ReadLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4) & 0x7F7FFFFF);
// if needed, throw irq for the end of transfer
if(MMU.AUX_SPI_CNT & 0x4000)
NDS_makeInt(PROCNUM, 19);
NDS_makeInt(TEST_PROCNUM, 19);
return val;
}
//INLINE void check_access(u32 adr, u32 access) {
// /* every other mode: sys */
// access |= 1;
// if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) {
// /* is user mode access */
// access ^= 1 ;
// }
// if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) {
// execute = FALSE ;
// }
//}
//INLINE void check_access_write(u32 adr) {
// u32 access = CP15_ACCESS_WRITE;
// check_access(adr, access)
//}
//
//u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access)
//{
// /* on arm9 we need to check the MPU regions */
// if (proc == ARMCPU_ARM9)
// check_access(u32 adr, u32 access);
// return MMU_read8(proc,adr);
//}
//u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access)
//{
// /* on arm9 we need to check the MPU regions */
// if (proc == ARMCPU_ARM9)
// check_access(u32 adr, u32 access);
// return MMU_read16(proc,adr);
//}
//u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access)
//{
// /* on arm9 we need to check the MPU regions */
// if (proc == ARMCPU_ARM9)
// check_access(u32 adr, u32 access);
// return MMU_read32(proc,adr);
//}
//
//void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val)
//{
// /* check MPU region on ARM9 */
// if (proc == ARMCPU_ARM9)
// check_access_write(adr);
// MMU_write8(proc,adr,val);
//}
//void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val)
//{
// /* check MPU region on ARM9 */
// if (proc == ARMCPU_ARM9)
// check_access_write(adr);
// MMU_write16(proc,adr,val) ;
//}
//void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val)
//{
// /* check MPU region on ARM9 */
// if (proc == ARMCPU_ARM9)
// check_access_write(adr);
// MMU_write32(proc,adr,val) ;
//}
//does some validation on the game's choice of IF value, correcting it if necessary
static void validateIF_arm9()

View File

@ -49,7 +49,7 @@ libdesmume_a_SOURCES = \
utils/task.cpp utils/task.h \
utils/dlditool.cpp \
addons.cpp addons.h \
addons/compactFlash.cpp addons/gbagame.cpp addons/none.cpp addons/rumblepak.cpp addons/guitarGrip.cpp addons/expMemory.cpp addons/piano.cpp fs.h \
addons/compactFlash.cpp addons/gbagame.cpp addons/none.cpp addons/rumblepak.cpp addons/guitarGrip.cpp addons/expMemory.cpp addons/piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail.cpp fs.h \
cheatSystem.cpp cheatSystem.h \
texcache.cpp texcache.h rasterize.cpp rasterize.h \
metaspu/metaspu.cpp metaspu/metaspu.h \

View File

@ -50,7 +50,7 @@ ADDONINTERFACE addonList[NDS_ADDON_COUNT] = {
};
ADDONINTERFACE addon = addonCFlash; // default none pak
u8 addon_type = NDS_ADDON_CFLASH;
NDS_ADDON_TYPE addon_type = NDS_ADDON_CFLASH;
BOOL addonsInit()
{
@ -67,7 +67,7 @@ void addonsReset()
addon.reset();
}
BOOL addonsChangePak(u8 type)
BOOL addonsChangePak(NDS_ADDON_TYPE type)
{
printf("addonsChangePak\n");
if (type > NDS_ADDON_COUNT) return FALSE;
@ -77,3 +77,44 @@ BOOL addonsChangePak(u8 type)
return addon.init();
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
extern ADDONINTERFACE slot1None;
extern ADDONINTERFACE slot1Retail;
extern ADDONINTERFACE slot1R4;
ADDONINTERFACE slot1List[NDS_SLOT1_COUNT] = {
slot1None,
slot1Retail,
slot1R4
};
ADDONINTERFACE slot1_device = slot1Retail; //default for frontends that dont even configure this
u8 slot1_device_type = NDS_SLOT1_RETAIL;
BOOL slot1Init()
{
return slot1_device.init();
}
void slot1Close()
{
slot1_device.close();
}
void slot1Reset()
{
slot1_device.reset();
}
BOOL slot1Change(NDS_SLOT1_TYPE changeToType)
{
printf("slot1Change to: %d\n", changeToType);
if (changeToType > NDS_SLOT1_COUNT || changeToType < 0) return FALSE;
slot1_device.close();
slot1_device_type = changeToType;
slot1_device = slot1List[slot1_device_type];
return slot1_device.init();
}

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2009 CrazyMax
Copyright (C) 2009 DeSmuME team
Copyright (C) 2009-2010 DeSmuME team
This file is part of DeSmuME
@ -25,7 +25,7 @@
#include "types.h"
#include "debug.h"
typedef struct
struct ADDONINTERFACE
{
// The name of the plugin, this name will appear in the plugins list
const char * name;
@ -54,9 +54,10 @@ typedef struct
//called when the user get info about addon pak (description)
void (*info)(char *info);
} ADDONINTERFACE;
};
enum {
enum NDS_ADDON_TYPE
{
NDS_ADDON_NONE,
NDS_ADDON_CFLASH, // compact flash
NDS_ADDON_RUMBLEPAK, // rumble pack
@ -79,7 +80,7 @@ inline bool CFlash_IsUsingPath() { return CFlash_Mode==ADDON_CFLASH_MODE_Path ||
extern ADDONINTERFACE addon; // current pak
extern ADDONINTERFACE addonList[NDS_ADDON_COUNT]; // lists pointer on paks
extern u8 addon_type; // current type pak
extern NDS_ADDON_TYPE addon_type; // current type pak
extern char GBAgameName[MAX_PATH]; // file name for GBA game (rom)
extern void (*FeedbackON)(BOOL enable); // feedback on/off
@ -87,9 +88,25 @@ extern void (*FeedbackON)(BOOL enable); // feedback on/off
extern BOOL addonsInit(); // Init addons
extern void addonsClose(); // Shutdown addons
extern void addonsReset(); // Reset addon
extern BOOL addonsChangePak(u8 type); // change current adddon
extern BOOL addonsChangePak(NDS_ADDON_TYPE type); // change current adddon
extern void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue); // Guitar grip keys
extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic); //piano keys
#endif
extern ADDONINTERFACE slot1_device; // current slot1 device
enum NDS_SLOT1_TYPE
{
NDS_SLOT1_NONE,
NDS_SLOT1_RETAIL,
NDS_SLOT1_R4,
NDS_SLOT1_COUNT // use for counter addons - MUST TO BE LAST!!!
};
BOOL slot1Init();
void slot1Close();
void slot1Reset();
BOOL slot1Change(NDS_SLOT1_TYPE type); // change current adddon
#endif //__ADDONS_H__

View File

@ -0,0 +1,62 @@
/* Copyright (C) 2010 DeSmuME team
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../addons.h"
static void slot1_info(char *info) { strcpy(info, "Slot1 no-card emulation (card ejected!)"); }
static void slot1_config(void) {}
static BOOL slot1_init() { return (TRUE); }
static void slot1_reset() {}
static void slot1_close() {}
static void slot1_write08(u32 adr, u8 val) {}
static void slot1_write16(u32 adr, u16 val) {}
static void slot1_write32(u32 adr, u32 val) {}
static u8 slot1_read08(u32 adr)
{
return 0xFF;
}
static u16 slot1_read16(u32 adr)
{
return 0xFFFF;
}
static u32 slot1_read32(u32 adr)
{
return 0xFFFFFFFF;
}
ADDONINTERFACE slot1None = {
"Slot1None",
slot1_init,
slot1_reset,
slot1_close,
slot1_config,
slot1_write08,
slot1_write16,
slot1_write32,
slot1_read08,
slot1_read16,
slot1_read32,
slot1_info};

View File

@ -0,0 +1,172 @@
/* Copyright (C) 2010 DeSmuME team
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../addons.h"
#include "../registers.h"
#include "../mmu.h"
#include "../NDSSystem.h"
#include <time.h>
static FILE *img = NULL;
static u32 write_count = 0;
static u32 write_enabled = 0;
static int old_addr = 0;
static void init_r4_flash()
{
srand(time(NULL));
if (!img)
img = fopen("DLDI_R4DS.img", "r+b");
if(!img)
{
INFO("DLDI_R4DS.img not found\n");
}
}
static void info(char *info) { strcpy(info, "Slot1 R4 Emulation"); }
static void config(void) {}
static BOOL init()
{
init_r4_flash();
return TRUE;
}
static void reset() {}
static void close() {}
static void write08(u32 adr, u8 val) {}
static void write16(u32 adr, u16 val) {}
static void write32_GCROMCTRL(u32 val)
{
nds_dscard& card = MMU.dscard[0];
switch(card.command[0])
{
case 0xB0:
break;
case 0xB9:
case 0xBA:
case 0xBB:
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
fseek(img,card.address,SEEK_SET);
break;
case 0xBC:
write_enabled = 1;
write_count = 0x80;
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
fseek(img,card.address,SEEK_SET);
write_count = 0x80;
break;
}
}
static void write32(u32 adr, u32 val)
{
switch(adr)
{
case REG_GCROMCTRL:
write32_GCROMCTRL(val);
break;
}
}
static u8 read08(u32 adr)
{
return 0xFF;
}
static u16 read16(u32 adr)
{
return 0xFFFF;
}
static u32 read32_GCDATAIN()
{
nds_dscard& card = MMU.dscard[0];
u32 val;
switch(card.command[0])
{
//Get ROM chip ID
case 0x90:
case 0xB8:
val = 0xFC2;
break;
case 0xB0:
val = 0x1F4;
break;
case 0xB9:
{
/*if (addr == old_addr)
val = 0;
else
val = 0x1F4;
old_addr = addr;*/
val = (rand() % 100) ? 0x1F4 : 0;
}
break;
case 0xBB:
case 0xBC:
val = 0;
break;
case 0xBA:
//INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img));
fread(&val, 1, 4, img);
//INFO("val %08X\n",val);
break;
default:
val = 0;
} //switch(card.command[0])
return val;
} //read32_GCDATAIN
static u32 read32(u32 adr)
{
switch(adr)
{
case REG_GCDATAIN:
return read32_GCDATAIN();
default:
return 0;
}
}
ADDONINTERFACE slot1R4 = {
"Slot1R4",
init,
reset,
close,
config,
write08,
write16,
write32,
read08,
read16,
read32,
info};

View File

@ -0,0 +1,274 @@
/* Copyright (C) 2010 DeSmuME team
This file is part of DeSmuME
DeSmuME is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DeSmuME is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../addons.h"
#include "../registers.h"
#include "../mmu.h"
#include "../NDSSystem.h"
static void info(char *info) { strcpy(info, "Slot1 Retail card emulation"); }
static void config(void) {}
static BOOL init() { return (TRUE); }
static void reset() {}
static void close() {}
static void write08(u32 adr, u8 val) {}
static void write16(u32 adr, u16 val) {}
static void write32_GCROMCTRL(u32 val)
{
nds_dscard& card = MMU.dscard[0];
switch(card.command[0])
{
case 0x00: //Data read
case 0xB7:
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
card.transfer_count = 0x80;
break;
default:
card.address = 0;
break;
}
}
static void write32(u32 adr, u32 val)
{
switch(adr)
{
case REG_GCROMCTRL:
write32_GCROMCTRL(val);
break;
}
}
static u8 read08(u32 adr)
{
return 0xFF;
}
static u16 read16(u32 adr)
{
return 0xFFFF;
}
static u32 read32_GCDATAIN()
{
nds_dscard& card = MMU.dscard[0];
switch(card.command[0])
{
//Get ROM chip ID
case 0x90:
case 0xB8:
{
// Note: the BIOS stores the chip ID in main memory
// Most games continuously compare the chip ID with
// the value in memory, probably to know if the card
// was removed.
// As DeSmuME boots directly from the game, the chip
// ID in main mem is zero and this value needs to be
// zero too.
//staff of kings verifies this (it also uses the arm7 IRQ 20)
if(nds.cardEjected) //TODO - handle this with ejected card slot1 device (and verify using this case)
return 0xFFFFFFFF;
else return 0;
}
break;
// Data read
case 0x00:
case 0xB7:
{
// Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart
if((card.command[0] == 0xB7) && (card.address < 0x8000))
{
//TODO - refactor this to include the PROCNUM, for debugging purposes if nothing else
//(can refactor gbaslot also)
//INFO("Read below 0x8000 (0x%04X) from: ARM%s %08X\n",
// card.address, (PROCNUM ? "7":"9"), (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr);
card.address = (0x8000 + (card.address&0x1FF));
}
if(card.address >= gameInfo.romsize)
{
DEBUG_Notify.ReadBeyondEndOfCart(card.address,gameInfo.romsize);
return 0xFFFFFFFF;
}
else
//but, this is actually handled by the cart rom buffer being oversized and full of 0xFF.
//is this a good idea? We think so.
return T1ReadLong(MMU.CART_ROM, card.address & MMU.CART_ROM_MASK);
}
break;
default:
return 0;
} //switch(card.command[0])
} //read32_GCDATAIN
static u32 read32(u32 adr)
{
switch(adr)
{
case REG_GCDATAIN:
return read32_GCDATAIN();
default:
return 0;
}
}
ADDONINTERFACE slot1Retail = {
"Slot1Retail",
init,
reset,
close,
config,
write08,
write16,
write32,
read08,
read16,
read32,
info
};
// ///writetoGCControl:
//// --- Ninja SD commands -------------------------------------
// // NJSD init/reset
// case 0x20:
// {
// card.address = 0;
// card.transfer_count = 0;
// }
// break;
// // NJSD_sendCLK()
// case 0xE0:
// {
// card.address = 0;
// card.transfer_count = 0;
// NDS_makeInt(PROCNUM, 20);
// }
// break;
// // NJSD_sendCMDN() / NJSD_sendCMDR()
// case 0xF0:
// case 0xF1:
// switch (card.command[2])
// {
// // GO_IDLE_STATE
// case 0x40:
// card.address = 0;
// card.transfer_count = 0;
// NDS_makeInt(PROCNUM, 20);
// break;
// case 0x42: // ALL_SEND_CID
// case 0x43: // SEND_RELATIVE_ADDR
// case 0x47: // SELECT_CARD
// case 0x49: // SEND_CSD
// case 0x4D:
// case 0x77: // APP_CMD
// case 0x69: // SD_APP_OP_COND
// card.address = 0;
// card.transfer_count = 6;
// NDS_makeInt(PROCNUM, 20);
// break;
// // SET_BLOCKLEN
// case 0x50:
// card.address = 0;
// card.transfer_count = 6;
// card.blocklen = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24);
// NDS_makeInt(PROCNUM, 20);
// break;
// // READ_SINGLE_BLOCK
// case 0x51:
// card.address = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24);
// card.transfer_count = (card.blocklen + 3) >> 2;
// NDS_makeInt(PROCNUM, 20);
// break;
// }
// break;
// // --- Ninja SD commands end ---------------------------------
// //GCDATAIN:
// // --- Ninja SD commands -------------------------------------
// // NJSD_sendCMDN() / NJSD_sendCMDR()
// case 0xF0:
// case 0xF1:
// switch (card.command[2])
// {
// // ALL_SEND_CID
// case 0x42:
// if (card.transfer_count == 2) val = 0x44534A4E;
// else val = 0x00000000;
// // SEND_RELATIVE_ADDR
// case 0x43:
// case 0x47:
// case 0x49:
// case 0x50:
// val = 0x00000000;
// break;
// case 0x4D:
// if (card.transfer_count == 2) val = 0x09000000;
// else val = 0x00000000;
// break;
// // APP_CMD
// case 0x77:
// if (card.transfer_count == 2) val = 0x00000037;
// else val = 0x00000000;
// break;
// // SD_APP_OP_COND
// case 0x69:
// if (card.transfer_count == 2) val = 0x00008000;
// else val = 0x00000000;
// break;
// // READ_SINGLE_BLOCK
// case 0x51:
// val = 0x00000000;
// break;
// }
// break;
// // --- Ninja SD commands end ---------------------------------

View File

@ -29,6 +29,7 @@
#include "movie.h"
#include "addons.h"
#include "NDSSystem.h"
#include "utils/xstring.h"
int scanline_filter_a = 2, scanline_filter_b = 4;
int _commandline_linux_nojoy = 0;
@ -49,6 +50,7 @@ CommandLine::CommandLine()
, _num_cores(-1)
, _rigorous_timing(0)
, _advanced_timing(-1)
, _slot1(NULL)
{
load_slot = 0;
arm9_gdb_port = arm7_gdb_port = 0;
@ -88,6 +90,7 @@ void CommandLine::loadCommonOptions()
{ "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &scanline_filter_b, "Intensity of fadeout for scanlines filter (corner) (default 4)", "SCANLINE_FILTER_B"},
{ "rigorous-timing", 0, 0, G_OPTION_ARG_INT, &_rigorous_timing, "Use some rigorous timings instead of unrealistically generous (default 0)", "RIGOROUS_TIMING"},
{ "advanced-timing", 0, 0, G_OPTION_ARG_INT, &_advanced_timing, "Use advanced BUS-level timing (default 1)", "ADVANCED_TIMING"},
{ "slot1", 0, 0, G_OPTION_ARG_STRING, &_slot1, "Device to load in slot 1 (default retail)", "SLOT1"},
#ifndef _MSC_VER
{ "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL},
{ "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL},
@ -112,6 +115,8 @@ bool CommandLine::parse(int argc,char **argv)
return false;
}
if(_slot1) slot1 = _slot1;
if(slot1.size() != 0) str_lcase((char*)&slot1[0]);
if(_play_movie_file) play_movie_file = _play_movie_file;
if(_record_movie_file) record_movie_file = _record_movie_file;
if(_cflash_image) cflash_image = _cflash_image;
@ -138,6 +143,14 @@ bool CommandLine::parse(int argc,char **argv)
bool CommandLine::validate()
{
if(slot1 != "")
{
if(slot1 != "r4" && slot1 != "retail" && slot1 != "none") {
g_printerr("Invalid slot1 device specified.\n");
return false;
}
}
if (load_slot < 0 || load_slot > 10) {
g_printerr("I only know how to load from slots 1-10, 0 means 'do not load savegame' and is default\n");
return false;
@ -208,5 +221,10 @@ void CommandLine::process_addonCommands()
is_cflash_configured = true;
}
if(slot1 == "retail")
slot1Change(NDS_SLOT1_RETAIL);
else if(slot1 == "r4")
slot1Change(NDS_SLOT1_R4);
}

View File

@ -48,6 +48,7 @@ public:
std::string cflash_image;
std::string cflash_path;
std::string gbaslot_rom;
std::string slot1;
#ifndef _MSC_VER
int disable_sound;
int disable_limiter;
@ -88,6 +89,7 @@ private:
int _num_cores;
int _rigorous_timing;
int _advanced_timing;
char* _slot1;
};
#endif

View File

@ -1521,6 +1521,18 @@
RelativePath="..\addons\rumblepak.cpp"
>
</File>
<File
RelativePath="..\addons\slot1_none.cpp"
>
</File>
<File
RelativePath="..\addons\slot1_r4.cpp"
>
</File>
<File
RelativePath="..\addons\slot1_retail.cpp"
>
</File>
</Filter>
<Filter
Name="metaspu"

View File

@ -1001,6 +1001,18 @@
RelativePath="..\addons\rumblepak.cpp"
>
</File>
<File
RelativePath="..\addons\slot1_none.cpp"
>
</File>
<File
RelativePath="..\addons\slot1_r4.cpp"
>
</File>
<File
RelativePath="..\addons\slot1_retail.cpp"
>
</File>
</Filter>
<Filter
Name="gdbstub"

View File

@ -427,6 +427,9 @@
<ItemGroup>
<ClCompile Include="..\addons.cpp" />
<ClCompile Include="..\addons\piano.cpp" />
<ClCompile Include="..\addons\slot1_none.cpp" />
<ClCompile Include="..\addons\slot1_r4.cpp" />
<ClCompile Include="..\addons\slot1_retail.cpp" />
<ClCompile Include="..\aggdraw.cpp" />
<ClCompile Include="..\arm_instructions.cpp" />
<ClCompile Include="..\armcpu.cpp" />

View File

@ -384,6 +384,15 @@
<ClCompile Include="..\utils\dlditool.cpp">
<Filter>Core\utils</Filter>
</ClCompile>
<ClCompile Include="..\addons\slot1_none.cpp">
<Filter>Core\addons</Filter>
</ClCompile>
<ClCompile Include="..\addons\slot1_r4.cpp">
<Filter>Core\addons</Filter>
</ClCompile>
<ClCompile Include="..\addons\slot1_retail.cpp">
<Filter>Core\addons</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\addons.h">

View File

@ -618,7 +618,7 @@ void GBAslotDialog(HWND hwnd)
Guitar.Enabled = false;
WritePrivateProfileInt("GBAslot","type",temp_type,IniName);
addon_type = temp_type;
addon_type = (NDS_ADDON_TYPE)temp_type;
addonsChangePak(addon_type);
if (romloaded && needReset)
NDS_Reset();

View File

@ -2461,7 +2461,7 @@ int _main()
CommonSettings.cheatsDisable = GetPrivateProfileBool("General", "cheatsDisable", false, IniName);
addon_type = GetPrivateProfileInt("GBAslot", "type", NDS_ADDON_NONE, IniName);
addon_type = (NDS_ADDON_TYPE)GetPrivateProfileInt("GBAslot", "type", NDS_ADDON_NONE, IniName);
win32_CFlash_cfgMode = GetPrivateProfileInt("GBAslot.CFlash", "fileMode", 2, IniName);
win32_CFlash_cfgDirectory = GetPrivateProfileStdString("GBAslot.CFlash", "path", "");
win32_CFlash_cfgFileName = GetPrivateProfileStdString("GBAslot.CFlash", "filename", "");
@ -2552,6 +2552,7 @@ int _main()
cmdline.errorHelp(__argv[0]);
return 1;
}
cmdline.validate();
Desmume_InitOnce();