massive slot-1 reorganization and code cleanup
This commit is contained in:
parent
b464ea0461
commit
e0d02ddda2
|
@ -48,7 +48,7 @@
|
|||
#define ASSERT_UNALIGNED(x)
|
||||
#endif
|
||||
|
||||
//#define _LOG_NEW_BOOT
|
||||
//TODO - do we need these here?
|
||||
_KEY1 key1(&MMU.ARM7_BIOS[0x0030]);
|
||||
_KEY2 key2;
|
||||
|
||||
|
@ -995,7 +995,7 @@ void MMU_Reset()
|
|||
memset(MMU.reg_IF_bits, 0, sizeof(u32) * 2);
|
||||
memset(MMU.reg_IF_pending, 0, sizeof(u32) * 2);
|
||||
|
||||
memset(MMU.dscard, 0, sizeof(nds_dscard) * 2);
|
||||
memset(&MMU.dscard, 0, sizeof(MMU.dscard));
|
||||
|
||||
MMU.divRunning = 0;
|
||||
MMU.divResult = 0;
|
||||
|
@ -1035,15 +1035,9 @@ void MMU_Reset()
|
|||
Mic_Reset();
|
||||
MMU.gfx3dCycles = 0;
|
||||
|
||||
memset(MMU.dscard[ARMCPU_ARM9].command, 0, 8);
|
||||
MMU.dscard[ARMCPU_ARM9].address = 0;
|
||||
MMU.dscard[ARMCPU_ARM9].transfer_count = 0;
|
||||
MMU.dscard[ARMCPU_ARM9].mode = CardMode_Normal;
|
||||
MMU.dscard.transfer_count = 0;
|
||||
MMU.dscard.mode = eCardMode_RAW;
|
||||
|
||||
memset(MMU.dscard[ARMCPU_ARM7].command, 0, 8);
|
||||
MMU.dscard[ARMCPU_ARM7].address = 0;
|
||||
MMU.dscard[ARMCPU_ARM7].transfer_count = 0;
|
||||
MMU.dscard[ARMCPU_ARM7].mode = CardMode_Normal;
|
||||
|
||||
//HACK!!!
|
||||
//until we improve all our session tracking stuff, we need to save the backup memory filename
|
||||
|
@ -1285,9 +1279,10 @@ bool DSI_TSC::load_state(EMUFILE* is)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void FASTCALL MMU_endTransfer(u32 PROCNUM, u32 cnt)
|
||||
static void FASTCALL MMU_endTransfer(u32 PROCNUM)
|
||||
{
|
||||
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, cnt & 0x7F7FFFFF);
|
||||
u32 val = T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0x7F7FFFFF;
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val);
|
||||
|
||||
// if needed, throw irq for the end of transfer
|
||||
if(MMU.AUX_SPI_CNT & 0x4000)
|
||||
|
@ -1314,189 +1309,78 @@ void FASTCALL MMU_writeToGCControl(u32 val)
|
|||
|
||||
u32 oldCnt = T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4);
|
||||
#endif
|
||||
|
||||
int dbsize = (val>>24)&7;
|
||||
static int gcctr=0;
|
||||
GCLOG("[GC] [%07d] GCControl: %08X (dbsize:%d)\n",gcctr,val,dbsize);
|
||||
gcctr++;
|
||||
|
||||
GCBUS_Controller& card = MMU.dscard;
|
||||
|
||||
nds_dscard& card = MMU.dscard[PROCNUM];
|
||||
//....pick apart the fields....
|
||||
int keylength = (val&0x1FFF); //key1length high gcromctrl[21:16] ??
|
||||
u8 key2_encryptdata = (val>>13)&1;
|
||||
u8 bit15 = (val>>14)&1;
|
||||
u8 key2_applyseed = (val>>15)&1; //write only strobe
|
||||
//key1length high gcromctrl[21:16] ??
|
||||
u8 key2_encryptcommand = (val>>22)&1;
|
||||
//bit 23 read only status
|
||||
int blocksize_field = (val>>24)&7;
|
||||
u8 clockrate = (val>>27)&1;
|
||||
u8 secureareamode = (val>>28)&1;
|
||||
//RESB bit 29?
|
||||
u8 wr = (val>>30)&1;
|
||||
u8 start = (val>>31)&1; //doubles as busy on read
|
||||
static const int blocksize_table[] = {0,0x200,0x400,0x800,0x1000,0x2000,0x4000,4};
|
||||
int blocksize = blocksize_table[blocksize_field];
|
||||
|
||||
memcpy(&card.command[0], &MMU.MMU_MEM[PROCNUM][0x40][0x1A8], 8);
|
||||
//store written value, without bit 31 and bit 23 set (those will be patched in as operations proceed)
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val & 0x7F7FFFFF);
|
||||
|
||||
card.blocklen = 0;
|
||||
|
||||
if ((val & (1 << 15)) != 0)
|
||||
//if this operation has been triggered by strobing that bit, run it
|
||||
if (key2_applyseed)
|
||||
{
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: KEY2 apply seeds, ctrl %08X (PC:0x%08X)\n", PROCNUM?'7':'9', val, ARMPROC.instruct_adr);
|
||||
printf("ARM%c: KEY2 apply seeds, ctrl %08X (PC:0x%08X)\n", PROCNUM?'7':'9', val, ARMPROC.instruct_adr);
|
||||
#endif
|
||||
|
||||
key2.applySeed(PROCNUM);
|
||||
}
|
||||
|
||||
if ((val & 0x80000000) == 0)
|
||||
{
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
{
|
||||
fprintf(fp_dis7, "ARM%c: Bad I/O, PC:%08X\tcmd %02X (%016llX), ctrl %08X/%08X, old len %08X\n", PROCNUM?'7':'9', ARMPROC.instruct_adr, card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count);
|
||||
}
|
||||
printf("ARM%c: Bad I/O, PC:%08X\n", PROCNUM?'7':'9', ARMPROC.instruct_adr);
|
||||
printf("\tcmd %02X (%016llX), ctrl %08X/%08X, old len %08X\n", card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count);
|
||||
#endif
|
||||
card.address = 0;
|
||||
card.transfer_count = 0;
|
||||
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val & 0x7F7FFFFF);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 shift = ((val >> 24) & 0x07);
|
||||
if(shift == 7)
|
||||
card.transfer_count = 4;
|
||||
else if(shift == 0)
|
||||
card.transfer_count = 0;
|
||||
else
|
||||
card.transfer_count = (0x100 << shift);
|
||||
//pluck out the command registers into a more convenient format
|
||||
GC_Command rawcmd = *(GC_Command*)&MMU.MMU_MEM[PROCNUM][0x40][0x1A8];
|
||||
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: cmd %02X (%016llX), ctrl %08X, old ctrl %08X, size %08X, PC:%08X, delay %X/%X\n", PROCNUM?'7':'9', card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count, ARMPROC.instruct_adr, (val & 0x1FFF), ((val >> 16) & 0x3F));
|
||||
printf("ARM%c: cmd %02X (%016llX), ctrl %08X/%08X, size %08X, PC:%08X\n", PROCNUM?'7':'9', card.command[0], *(u64 *)&card.command[0], val, oldCnt, card.transfer_count, ARMPROC.instruct_adr);
|
||||
if (card.mode != CardMode_Normal)
|
||||
//when writing a 1 to the start bit, a command runs.
|
||||
//the command is transferred to the GC during the next 8 clocks
|
||||
if(start)
|
||||
{
|
||||
u64 rawCmd = (u64)MMU_read32(PROCNUM, 0x037F8074) | ((u64)MMU_read32(PROCNUM, 0x037F8078) << 32);
|
||||
u64 rawCmd2 = rawCmd >> 56;
|
||||
if (card.mode != CardMode_DATA_LOAD)
|
||||
rawCmd2 >>= 4;
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, " RAW cmd %02X (%016llX)\n", rawCmd2, rawCmd);
|
||||
printf(" RAW cmd %02X (%016llX)\n", rawCmd2, rawCmd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (card.mode == CardMode_Normal)
|
||||
{
|
||||
switch(card.command[0])
|
||||
{
|
||||
case 0x9F: //Dummy
|
||||
card.address = 0;
|
||||
card.transfer_count = 0x2000;
|
||||
break;
|
||||
|
||||
case 0x3C: //Switch to KEY1 mode
|
||||
{
|
||||
u32 gameID = MMU_read32(PROCNUM, 0x027FFE0C);
|
||||
key1.init(gameID, 2, 0x08);
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: Activate KEY1 encryption mode (id %08X)\n", PROCNUM?'7':'9', gameID);
|
||||
printf("ARM%c: Activate KEY1 encryption mode (id %08X)\n", PROCNUM?'7':'9', gameID);
|
||||
#endif
|
||||
card.mode = CardMode_KEY1;
|
||||
card.transfer_count = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//fall through to the special slot1 handler
|
||||
slot1_device->write32(PROCNUM, REG_GCROMCTRL,val);
|
||||
break;
|
||||
}
|
||||
GCLOG("[GC] command:"); rawcmd.print();
|
||||
slot1_device->write_command(PROCNUM,rawcmd);
|
||||
}
|
||||
else
|
||||
if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2)
|
||||
{
|
||||
//<zero> really? the values from memory are used here?
|
||||
//somehow I doubt it. are they stored in the gamecard controllers somehow?
|
||||
u32 gameID = MMU_read32(PROCNUM, 0x027FFE0C);
|
||||
u32 chipID = MMU_read32(PROCNUM, 0x027FF800);
|
||||
u64 cmd = bswap64(*(u64 *)&card.command[0]);
|
||||
|
||||
//key1.init(gameID, 2, 0x08);
|
||||
key1.decrypt((u32*)&cmd);
|
||||
*(u64*)&card.command[0] = bswap64(cmd);
|
||||
|
||||
switch (cmd >> 60)
|
||||
{
|
||||
case 0x02: // Get secure area block (4Kbytes) - 910h+11A8h
|
||||
{
|
||||
u32 addr = (u32)((cmd >> 32) & 0xF000);
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
u32 area = (u32)((cmd >> 32) & 0xF000);
|
||||
u32 src = MMU_read32(PROCNUM, 0x0380FC00);
|
||||
u32 dst = MMU_read32(PROCNUM, 0x0380FC04);
|
||||
u32 len = MMU_read32(PROCNUM, 0x0380FC08);
|
||||
u32 size = MMU_read32(PROCNUM, 0x0380FC10);
|
||||
u32 size2 = size;
|
||||
if (size2 == 7)
|
||||
size2 = 4;
|
||||
else
|
||||
if (size2 != 0)
|
||||
size2 = (0x100 << size2);
|
||||
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: Get secure are block: area %04X, src %08X, dst %08X, len %08X, bsize %08X\n", PROCNUM?'7':'9', area, src, dst, len, size);
|
||||
printf("ARM%c: Get secure are block: area %04X, src %08X, dst %08X, len %08X, bsize %08X|%08X\n", PROCNUM?'7':'9', area, src, dst, len, size, size2);
|
||||
#endif
|
||||
card.address = addr;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04: // Activate KEY2 encryption mode - 910h+0
|
||||
card.mode = CardMode_KEY2;
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: Activate KEY2 encryption mode\n", PROCNUM?'7':'9');
|
||||
printf("ARM%c: Activate KEY2 encryption mode\n", PROCNUM?'7':'9');
|
||||
#endif
|
||||
//key2.applySeed(PROCNUM);
|
||||
//card.delay = 0x910;
|
||||
break;
|
||||
case 0x06: // Optional KEY2 disable - 910h+?
|
||||
break;
|
||||
case 0x0A: // Enter main data mode - 910h+0
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: Enter main data mode\n", PROCNUM?'7':'9');
|
||||
printf("ARM%c: Enter main data mode\n", PROCNUM?'7':'9');
|
||||
#endif
|
||||
card.mode = CardMode_DATA_LOAD;
|
||||
//card.delay = 0x910;
|
||||
break;
|
||||
default:
|
||||
slot1_device->write32(PROCNUM, REG_GCROMCTRL, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (card.mode == CardMode_DATA_LOAD)
|
||||
{
|
||||
slot1_device->write32(PROCNUM, REG_GCROMCTRL, val);
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: main data mode cmd %02X (addr %08X, len %08X)\n", PROCNUM?'7':'9', card.command[0], card.address, card.transfer_count);
|
||||
printf("ARM%c: main data mode cmd %02X (addr %08X, len %08X)\n", PROCNUM?'7':'9', card.command[0], card.address, card.transfer_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(card.delay == 0 && card.transfer_count == 0)
|
||||
{
|
||||
MMU_endTransfer(PROCNUM, val);
|
||||
return;
|
||||
//GCLOG("GC operation terminated or declined. please report, unless you just booted from firmware.\n");
|
||||
}
|
||||
|
||||
//the transfer size is determined by the specification here in GCROMCTRL, not any logic private to the card.
|
||||
card.transfer_count = blocksize;
|
||||
|
||||
val |= 0x00800000;
|
||||
T1WriteLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4, val);
|
||||
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val);
|
||||
|
||||
//if there was nothing to be done here, go ahead and flag it as done
|
||||
if(card.transfer_count == 0)
|
||||
{
|
||||
MMU_endTransfer(PROCNUM);
|
||||
return;
|
||||
}
|
||||
|
||||
// Launch DMA if start flag was set to "DS Cart"
|
||||
//printf("triggering card dma\n");
|
||||
triggerDma(EDMAMode_Card);
|
||||
}
|
||||
|
||||
template<int PROCNUM>
|
||||
u32 FASTCALL MMU_readFromGCControl()
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[PROCNUM];
|
||||
GCBUS_Controller& card = MMU.dscard;
|
||||
|
||||
u32 val = T1ReadLong(MMU.MMU_MEM[PROCNUM][0x40], 0x1A4);
|
||||
u32 val = T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -1504,57 +1388,18 @@ u32 FASTCALL MMU_readFromGCControl()
|
|||
template<int PROCNUM>
|
||||
u32 MMU_readFromGC()
|
||||
{
|
||||
const int TEST_PROCNUM = PROCNUM;
|
||||
|
||||
nds_dscard& card = MMU.dscard[TEST_PROCNUM];
|
||||
u32 val = 0;
|
||||
GCBUS_Controller& card = MMU.dscard;
|
||||
|
||||
//???? return the latched / last read value instead perhaps?
|
||||
if(card.transfer_count == 0)
|
||||
return 0;
|
||||
|
||||
u8 cmd = card.command[0];
|
||||
if ((card.mode == CardMode_KEY1) || (card.mode == CardMode_KEY2))
|
||||
cmd >>= 4;
|
||||
u32 val = slot1_device->read_GCDATAIN(PROCNUM);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case 0x9F: //Dummy
|
||||
val = 0xFFFFFFFF;
|
||||
break;
|
||||
|
||||
case 0x3C: //Switch to KEY1 mode
|
||||
val = 0xFFFFFFFF;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
val = T1ReadLong(MMU.CART_ROM, card.address);
|
||||
|
||||
#ifdef _LOG_NEW_BOOT
|
||||
{
|
||||
extern FILE *fp_dis7;
|
||||
if (fp_dis7)
|
||||
fprintf(fp_dis7, "ARM%c: read secury area from %08X (val %08X)\n", PROCNUM?'7':'9', card.address, val);
|
||||
printf("ARM%c: read secury area from %08X (val %08X)\n", PROCNUM?'7':'9', card.address, val);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
val = slot1_device->read32(TEST_PROCNUM, REG_GCDATAIN);
|
||||
break;
|
||||
}
|
||||
|
||||
card.address += 4; // increment address
|
||||
|
||||
card.transfer_count -= 4; // update transfer counter
|
||||
if(card.transfer_count) // if transfer is not ended
|
||||
return val; // return data
|
||||
|
||||
// transfer is done
|
||||
T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4,
|
||||
T1ReadLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4) & 0x7F7FFFFF);
|
||||
|
||||
MMU_endTransfer(PROCNUM, T1ReadLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4));
|
||||
//update transfer counter and complete the transfer if necessary
|
||||
card.transfer_count -= 4;
|
||||
if(!card.transfer_count)
|
||||
MMU_endTransfer(PROCNUM);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -2440,7 +2285,7 @@ void DmaController::doCopy()
|
|||
if(nds.VCount==191) enable = 0;
|
||||
}
|
||||
|
||||
if(startmode == EDMAMode_Card) todo = MMU.dscard[PROCNUM].transfer_count / sz;
|
||||
if(startmode == EDMAMode_Card) todo = MMU.dscard.transfer_count / sz;
|
||||
if(startmode == EDMAMode_GXFifo) todo = std::min(todo,(u32)112);
|
||||
|
||||
//determine how we're going to copy
|
||||
|
@ -3333,10 +3178,10 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
|
|||
}
|
||||
|
||||
case REG_GCROMCTRL :
|
||||
MMU_writeToGCControl<ARMCPU_ARM9>( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4) & 0xFFFF0000) | val);
|
||||
MMU_writeToGCControl<ARMCPU_ARM9>( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val);
|
||||
return;
|
||||
case REG_GCROMCTRL+2 :
|
||||
MMU_writeToGCControl<ARMCPU_ARM9>( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16));
|
||||
MMU_writeToGCControl<ARMCPU_ARM9>( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3771,7 +3616,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
|
|||
case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(32,adr,val); return;
|
||||
|
||||
case REG_GCDATAIN:
|
||||
slot1_device->write32(ARMCPU_ARM9, REG_GCDATAIN,val);
|
||||
slot1_device->write_GCDATAIN(ARMCPU_ARM9 ,val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4121,7 +3966,9 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr)
|
|||
return MMU.timer[ARMCPU_ARM9][(adr&0xF)>>2] | (val<<16);
|
||||
}
|
||||
|
||||
case REG_GCDATAIN: return MMU_readFromGC<ARMCPU_ARM9>();
|
||||
case REG_GCDATAIN:
|
||||
return MMU_readFromGC<ARMCPU_ARM9>();
|
||||
|
||||
case REG_POWCNT1: return readreg_POWCNT1(32,adr);
|
||||
case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(32,adr);
|
||||
|
||||
|
@ -4415,10 +4262,10 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
|
|||
}
|
||||
|
||||
case REG_GCROMCTRL :
|
||||
MMU_writeToGCControl<ARMCPU_ARM7>( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4) & 0xFFFF0000) | val);
|
||||
MMU_writeToGCControl<ARMCPU_ARM7>( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF0000) | val);
|
||||
return;
|
||||
case REG_GCROMCTRL+2 :
|
||||
MMU_writeToGCControl<ARMCPU_ARM7>( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16));
|
||||
MMU_writeToGCControl<ARMCPU_ARM7>( (T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4521,7 +4368,7 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
|
|||
return;
|
||||
|
||||
case REG_GCDATAIN:
|
||||
slot1_device->write32(ARMCPU_ARM7, REG_GCDATAIN,val);
|
||||
slot1_device->write_GCDATAIN(ARMCPU_ARM7, val);
|
||||
return;
|
||||
}
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val);
|
||||
|
|
|
@ -296,27 +296,60 @@ public:
|
|||
|
||||
};
|
||||
|
||||
enum ECardMode
|
||||
enum eCardMode : u32
|
||||
{
|
||||
CardMode_Normal = 0,
|
||||
CardMode_KEY1,
|
||||
CardMode_KEY2,
|
||||
CardMode_DATA_LOAD
|
||||
//when the GC system is first booted up, the protocol is in raw mode
|
||||
eCardMode_RAW = 0,
|
||||
|
||||
//an intermediate stage during the protocol bootup process. commands are KEY1 encrypted.
|
||||
eCardMode_KEY1,
|
||||
|
||||
//an intermediate stage during the protocol bootup process. commands are KEY1 encrypted, while replies are KEY2 encrypted
|
||||
eCardMode_KEY2,
|
||||
|
||||
//the final stage of the protocol bootup process. "main data load" mode. commands are KEY2 encrypted, and replies are KEY2 encrypted.
|
||||
//optionally, according to some flag we havent designed yet but should probably go in GCBUS_Controller, the whole KEY2 part can be bypassed
|
||||
//(this is typical when skipping the firmware boot process)
|
||||
eCardMode_NORMAL,
|
||||
|
||||
//help fix to 32bit
|
||||
eCardMode_Pad = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
//should rather be known as gamecard bus controller, or somesuch
|
||||
struct nds_dscard
|
||||
//#define GCLOG(...) printf(__VA_ARGS__);
|
||||
#define GCLOG(...)
|
||||
|
||||
struct GC_Command
|
||||
{
|
||||
u8 command[8];
|
||||
u8 bytes[8];
|
||||
void print()
|
||||
{
|
||||
GCLOG("%02X%02X%02X%02X%02X%02X%02X%02X\n",bytes[0],bytes[1],bytes[2],bytes[3],bytes[4],bytes[5],bytes[6],bytes[7]);
|
||||
}
|
||||
void toCryptoBuffer(u32 buf[2])
|
||||
{
|
||||
u8 temp[8] = { bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0] };
|
||||
buf[0] = T1ReadLong(temp,0);
|
||||
buf[1] = T1ReadLong(temp,4);
|
||||
}
|
||||
void fromCryptoBuffer(u32 buf[2])
|
||||
{
|
||||
bytes[7] = (buf[0]>>0)&0xFF;
|
||||
bytes[6] = (buf[0]>>8)&0xFF;
|
||||
bytes[5] = (buf[0]>>16)&0xFF;
|
||||
bytes[4] = (buf[0]>>24)&0xFF;
|
||||
bytes[3] = (buf[1]>>0)&0xFF;
|
||||
bytes[2] = (buf[1]>>8)&0xFF;
|
||||
bytes[1] = (buf[1]>>16)&0xFF;
|
||||
bytes[0] = (buf[1]>>24)&0xFF;
|
||||
}
|
||||
};
|
||||
|
||||
u32 address;
|
||||
//should rather be known as GCBUS controller, or somesuch
|
||||
struct GCBUS_Controller
|
||||
{
|
||||
u32 transfer_count;
|
||||
u32 delay;
|
||||
|
||||
ECardMode mode;
|
||||
|
||||
// NJSD stuff
|
||||
int blocklen;
|
||||
eCardMode mode;
|
||||
};
|
||||
|
||||
#define DUP2(x) x, x
|
||||
|
@ -432,7 +465,7 @@ struct MMU_struct
|
|||
|
||||
fw_memory_chip fw;
|
||||
|
||||
nds_dscard dscard[2];
|
||||
GCBUS_Controller dscard;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ libdesmume_a_SOURCES = \
|
|||
utils/tinyxml/tinyxmlerror.cpp \
|
||||
utils/tinyxml/tinyxmlparser.cpp \
|
||||
addons.cpp addons.h \
|
||||
addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp \
|
||||
addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \
|
||||
cheatSystem.cpp cheatSystem.h \
|
||||
texcache.cpp texcache.h rasterize.cpp rasterize.h \
|
||||
metaspu/metaspu.cpp metaspu/metaspu.h \
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
//int xxctr=0;
|
||||
//#define LOG_ARM9
|
||||
//#define LOG_ARM7
|
||||
//#define dolog (currFrameCounter>15)
|
||||
bool dolog=false;
|
||||
#define dolog (currFrameCounter>30)
|
||||
//bool dolog=false;
|
||||
//#define LOG_TO_FILE
|
||||
//#define LOG_TO_FILE_REGS
|
||||
|
||||
|
|
|
@ -29,18 +29,9 @@ public:
|
|||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
}
|
||||
|
||||
virtual u32 read32(u8 PROCNUM, u32 adr)
|
||||
{
|
||||
//return a chip ID of 0.
|
||||
//if (adr == REG_GCDATAIN && MMU.dscard[PROCNUM].command[0] == 0xB8) return 0;
|
||||
//EDIT - not sure who did this or why, but... but if a card is ejected, there can be no chip ID.
|
||||
//we certainly want it to appear differently from chipId 0, which is something we are faking in other slot-1 devices
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
//pretty much every access to the card should just be ignored and reading HIGH-Z off the GC bus.
|
||||
//so, nothing really to do here
|
||||
//(notably, it results in a 0xFFFFFFFF card ID)
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,231 +1,231 @@
|
|||
/*
|
||||
Copyright (C) 2010-2013 DeSmuME team
|
||||
|
||||
This file 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.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../registers.h"
|
||||
#include "../MMU.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
class Slot1_R4 : public ISlot1Interface
|
||||
{
|
||||
private:
|
||||
EMUFILE *img;
|
||||
u32 write_count;
|
||||
u32 write_enabled;
|
||||
|
||||
public:
|
||||
Slot1_R4()
|
||||
: img(NULL)
|
||||
, write_count(0)
|
||||
, write_enabled(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("R4","Slot1 R4 emulation");
|
||||
return &info;
|
||||
}
|
||||
|
||||
|
||||
//called once when the emulator starts up, or when the device springs into existence
|
||||
virtual bool init()
|
||||
{
|
||||
//strange to do this here but we need to make sure its done at some point
|
||||
srand(time(NULL));
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
img = slot1_GetFatImage();
|
||||
|
||||
if(!img)
|
||||
INFO("slot1 fat not successfully mounted\n");
|
||||
}
|
||||
|
||||
//called when the emulator disconnects the device
|
||||
virtual void disconnect()
|
||||
{
|
||||
img = NULL;
|
||||
}
|
||||
|
||||
//called when the emulator shuts down, or when the device disappears from existence
|
||||
virtual void shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual u32 read32(u8 PROCNUM, u32 adr)
|
||||
{
|
||||
switch(adr)
|
||||
{
|
||||
case REG_GCDATAIN:
|
||||
return read32_GCDATAIN();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void write32(u8 PROCNUM, u32 adr, u32 val)
|
||||
{
|
||||
switch(adr)
|
||||
{
|
||||
case REG_GCROMCTRL:
|
||||
write32_GCROMCTRL(val);
|
||||
break;
|
||||
case REG_GCDATAIN:
|
||||
write32_GCDATAIN(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
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:
|
||||
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));
|
||||
img->fread(&val, 4);
|
||||
//INFO("val %08X\n",val);
|
||||
break;
|
||||
|
||||
default:
|
||||
val = 0;
|
||||
}
|
||||
|
||||
/*INFO("READ CARD command: %02X%02X%02X%02X% 02X%02X%02X%02X RET: %08X ",
|
||||
card.command[0], card.command[1], card.command[2], card.command[3],
|
||||
card.command[4], card.command[5], card.command[6], card.command[7],
|
||||
val);
|
||||
INFO("FROM: %08X LR: %08X\n", NDS_ARM9.instruct_adr, NDS_ARM9.R[14]);*/
|
||||
|
||||
|
||||
return val;
|
||||
} //read32_GCDATAIN
|
||||
|
||||
|
||||
void write32_GCROMCTRL(u32 val)
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[0];
|
||||
|
||||
switch(card.command[0])
|
||||
{
|
||||
case 0xB0:
|
||||
break;
|
||||
case 0xB9:
|
||||
case 0xBA:
|
||||
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
|
||||
img->fseek(card.address,SEEK_SET);
|
||||
break;
|
||||
case 0xBB:
|
||||
write_enabled = 1;
|
||||
write_count = 0x80;
|
||||
case 0xBC:
|
||||
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
|
||||
img->fseek(card.address,SEEK_SET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void write32_GCDATAIN(u32 val)
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[0];
|
||||
//bool log=false;
|
||||
|
||||
memcpy(&card.command[0], &MMU.MMU_MEM[0][0x40][0x1A8], 8);
|
||||
|
||||
//last_write_count = write_count;
|
||||
if(card.command[4])
|
||||
{
|
||||
// transfer is done
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
|
||||
// if needed, throw irq for the end of transfer
|
||||
if(MMU.AUX_SPI_CNT & 0x4000)
|
||||
NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch(card.command[0])
|
||||
{
|
||||
case 0xBB:
|
||||
{
|
||||
if(write_count && write_enabled)
|
||||
{
|
||||
img->fwrite(&val, 4);
|
||||
img->fflush();
|
||||
write_count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(write_count==0)
|
||||
{
|
||||
write_enabled = 0;
|
||||
|
||||
// transfer is done
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
|
||||
// if needed, throw irq for the end of transfer
|
||||
if(MMU.AUX_SPI_CNT & 0x4000)
|
||||
NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE);
|
||||
}
|
||||
|
||||
/*if(log)
|
||||
{
|
||||
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\t", NDS_ARM9.instruct_adr);
|
||||
INFO("VAL: %08X\n", val);
|
||||
}*/
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); }
|
||||
///*
|
||||
// Copyright (C) 2010-2013 DeSmuME team
|
||||
//
|
||||
// This file 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.
|
||||
//
|
||||
// This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
//*/
|
||||
//
|
||||
//#include <time.h>
|
||||
//
|
||||
//#include "../slot1.h"
|
||||
//#include "../registers.h"
|
||||
//#include "../MMU.h"
|
||||
//#include "../NDSSystem.h"
|
||||
//#include "../emufile.h"
|
||||
//
|
||||
//class Slot1_R4 : public ISlot1Interface
|
||||
//{
|
||||
//private:
|
||||
// EMUFILE *img;
|
||||
// u32 write_count;
|
||||
// u32 write_enabled;
|
||||
//
|
||||
//public:
|
||||
// Slot1_R4()
|
||||
// : img(NULL)
|
||||
// , write_count(0)
|
||||
// , write_enabled(0)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// virtual Slot1Info const* info()
|
||||
// {
|
||||
// static Slot1InfoSimple info("R4","Slot1 R4 emulation");
|
||||
// return &info;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// //called once when the emulator starts up, or when the device springs into existence
|
||||
// virtual bool init()
|
||||
// {
|
||||
// //strange to do this here but we need to make sure its done at some point
|
||||
// srand(time(NULL));
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// virtual void connect()
|
||||
// {
|
||||
// img = slot1_GetFatImage();
|
||||
//
|
||||
// if(!img)
|
||||
// INFO("slot1 fat not successfully mounted\n");
|
||||
// }
|
||||
//
|
||||
// //called when the emulator disconnects the device
|
||||
// virtual void disconnect()
|
||||
// {
|
||||
// img = NULL;
|
||||
// }
|
||||
//
|
||||
// //called when the emulator shuts down, or when the device disappears from existence
|
||||
// virtual void shutdown()
|
||||
// {
|
||||
// }
|
||||
//
|
||||
//
|
||||
// virtual u32 read32(u8 PROCNUM, u32 adr)
|
||||
// {
|
||||
// switch(adr)
|
||||
// {
|
||||
// case REG_GCDATAIN:
|
||||
// return read32_GCDATAIN();
|
||||
// default:
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// virtual void write32(u8 PROCNUM, u32 adr, u32 val)
|
||||
// {
|
||||
// switch(adr)
|
||||
// {
|
||||
// case REG_GCROMCTRL:
|
||||
// write32_GCROMCTRL(val);
|
||||
// break;
|
||||
// case REG_GCDATAIN:
|
||||
// write32_GCDATAIN(val);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//private:
|
||||
//
|
||||
// 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:
|
||||
// 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));
|
||||
// img->fread(&val, 4);
|
||||
// //INFO("val %08X\n",val);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// val = 0;
|
||||
// }
|
||||
//
|
||||
// /*INFO("READ CARD command: %02X%02X%02X%02X% 02X%02X%02X%02X RET: %08X ",
|
||||
// card.command[0], card.command[1], card.command[2], card.command[3],
|
||||
// card.command[4], card.command[5], card.command[6], card.command[7],
|
||||
// val);
|
||||
// INFO("FROM: %08X LR: %08X\n", NDS_ARM9.instruct_adr, NDS_ARM9.R[14]);*/
|
||||
//
|
||||
//
|
||||
// return val;
|
||||
// } //read32_GCDATAIN
|
||||
//
|
||||
//
|
||||
// void write32_GCROMCTRL(u32 val)
|
||||
// {
|
||||
// nds_dscard& card = MMU.dscard[0];
|
||||
//
|
||||
// switch(card.command[0])
|
||||
// {
|
||||
// case 0xB0:
|
||||
// break;
|
||||
// case 0xB9:
|
||||
// case 0xBA:
|
||||
// card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
|
||||
// img->fseek(card.address,SEEK_SET);
|
||||
// break;
|
||||
// case 0xBB:
|
||||
// write_enabled = 1;
|
||||
// write_count = 0x80;
|
||||
// case 0xBC:
|
||||
// card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
|
||||
// img->fseek(card.address,SEEK_SET);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void write32_GCDATAIN(u32 val)
|
||||
// {
|
||||
// nds_dscard& card = MMU.dscard[0];
|
||||
// //bool log=false;
|
||||
//
|
||||
// memcpy(&card.command[0], &MMU.MMU_MEM[0][0x40][0x1A8], 8);
|
||||
//
|
||||
// //last_write_count = write_count;
|
||||
// if(card.command[4])
|
||||
// {
|
||||
// // transfer is done
|
||||
// T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
//
|
||||
// // if needed, throw irq for the end of transfer
|
||||
// if(MMU.AUX_SPI_CNT & 0x4000)
|
||||
// NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE);
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// switch(card.command[0])
|
||||
// {
|
||||
// case 0xBB:
|
||||
// {
|
||||
// if(write_count && write_enabled)
|
||||
// {
|
||||
// img->fwrite(&val, 4);
|
||||
// img->fflush();
|
||||
// write_count--;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if(write_count==0)
|
||||
// {
|
||||
// write_enabled = 0;
|
||||
//
|
||||
// // transfer is done
|
||||
// T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
//
|
||||
// // if needed, throw irq for the end of transfer
|
||||
// if(MMU.AUX_SPI_CNT & 0x4000)
|
||||
// NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE);
|
||||
// }
|
||||
//
|
||||
// /*if(log)
|
||||
// {
|
||||
// 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\t", NDS_ARM9.instruct_adr);
|
||||
// INFO("VAL: %08X\n", val);
|
||||
// }*/
|
||||
// }
|
||||
//
|
||||
//};
|
||||
//
|
||||
//ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); }
|
|
@ -39,23 +39,38 @@ public:
|
|||
|
||||
virtual void connect()
|
||||
{
|
||||
//TODO - check game ID in core emulator and select right implementation
|
||||
mSelectedImplementation = slot1_List[NDS_SLOT1_RETAIL_MCROM];
|
||||
|
||||
NDS_SLOT1_TYPE selection = NDS_SLOT1_RETAIL_MCROM;
|
||||
|
||||
//check game ID in core emulator and select right implementation
|
||||
if(!memcmp(gameInfo.header.gameCode,"UORE",4))
|
||||
selection = NDS_SLOT1_RETAIL_NAND;
|
||||
|
||||
mSelectedImplementation = slot1_List[selection];
|
||||
mSelectedImplementation->connect();
|
||||
printf("slot1 auto-selected device type: %s\n",mSelectedImplementation->info()->name());
|
||||
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
if(mSelectedImplementation) mSelectedImplementation->disconnect();
|
||||
mSelectedImplementation = NULL;
|
||||
}
|
||||
|
||||
virtual void write32(u8 PROCNUM, u32 adr, u32 val)
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
mSelectedImplementation->write32(PROCNUM, adr, val);
|
||||
mSelectedImplementation->write_command(PROCNUM, command);
|
||||
}
|
||||
|
||||
virtual u32 read32(u8 PROCNUM, u32 adr)
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
return mSelectedImplementation->read32(PROCNUM, adr);
|
||||
mSelectedImplementation->write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return mSelectedImplementation->read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
|
|
|
@ -21,10 +21,22 @@
|
|||
#include "../NDSSystem.h"
|
||||
#include "slot1comp_mc.h"
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
class Slot1_Retail_MCROM : public ISlot1Interface
|
||||
//quick architecture overview:
|
||||
//MCROM receives GC bus commands from MMU.cpp
|
||||
//those are passed on to the protocol component for parsing
|
||||
//protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly)
|
||||
//MCROM utilizes the rom component for address logic and delivering data
|
||||
|
||||
class Slot1_Retail_MCROM : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
public:
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail MC+ROM","Slot1 Retail MC+ROM (standard) card emulation");
|
||||
|
@ -33,28 +45,9 @@ public:
|
|||
|
||||
virtual void connect()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void write32(u8 PROCNUM, u32 adr, u32 val)
|
||||
{
|
||||
switch(adr)
|
||||
{
|
||||
case REG_GCROMCTRL:
|
||||
write32_GCROMCTRL(PROCNUM, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual u32 read32(u8 PROCNUM, u32 adr)
|
||||
{
|
||||
switch(adr)
|
||||
{
|
||||
case REG_GCDATAIN:
|
||||
return read32_GCDATAIN(PROCNUM);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
|
@ -67,262 +60,30 @@ public:
|
|||
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 read32_GCDATAIN(u8 PROCNUM)
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[PROCNUM];
|
||||
u8 cmd = card.command[0];
|
||||
|
||||
if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2)
|
||||
cmd >>= 4;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case 0x01: // 2nd Get ROM Chip ID - len 4 bytes
|
||||
case 0x90: // 1st Get ROM Chip ID - len 4 bytes
|
||||
case 0xB8: // 3rd Get ROM Chip ID - len 4 bytes
|
||||
{
|
||||
// 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 normally 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)
|
||||
return gameInfo.chipID;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
// Data read
|
||||
case 0x00:
|
||||
case 0xB7:
|
||||
{
|
||||
//it seems that etrian odyssey 3 doesnt work unless we mask this to cart size.
|
||||
//but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision
|
||||
//but there is no test case yet
|
||||
u32 address = card.address & (gameInfo.mask);
|
||||
|
||||
// Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real card
|
||||
if((cmd == 0xB7) && (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);
|
||||
|
||||
address = (0x8000 + (address&0x1FF));
|
||||
}
|
||||
|
||||
//as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms)
|
||||
//we need to protect ourselves by returning 0xFF for things still out of range
|
||||
if(address >= gameInfo.romsize)
|
||||
{
|
||||
DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return T1ReadLong(MMU.CART_ROM, address);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//printf("ARM%c: SLOT1 invalid command %02X (read)\n", PROCNUM?'7':'9', cmd);
|
||||
return 0;
|
||||
} //switch(card.command[0])
|
||||
} //read32_GCDATAIN
|
||||
|
||||
void write32_GCROMCTRL(u8 PROCNUM, u32 val)
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[PROCNUM];
|
||||
|
||||
if (card.mode == CardMode_Normal)
|
||||
{
|
||||
switch(card.command[0])
|
||||
{
|
||||
case 0x00: //Data read (0000000000000000h Get Cartridge Header) - len 200h bytes
|
||||
case 0xB7:
|
||||
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
|
||||
card.transfer_count = 0x200;
|
||||
break;
|
||||
|
||||
case 0x90: // 1st Get ROM Chip ID - len 4 bytes
|
||||
case 0xB8:
|
||||
card.address = 0;
|
||||
card.transfer_count = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
card.address = 0;
|
||||
card.transfer_count = 0;
|
||||
printf("ARM%c: SLOT1 invalid command %02X (write) - CardMode_Normal\n", PROCNUM?'7':'9', card.command[0]);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (card.mode == CardMode_KEY1 || card.mode == CardMode_KEY2)
|
||||
{
|
||||
u8 cmd = (card.command[0] >> 4);
|
||||
switch(cmd)
|
||||
{
|
||||
case 0x01: // 2nd Get ROM Chip ID - len 4 bytes
|
||||
card.address = 0;
|
||||
card.transfer_count = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
card.address = 0;
|
||||
card.transfer_count = 0;
|
||||
printf("ARM%c: SLOT1 invalid command %02X (write) - %s\n", PROCNUM?'7':'9', cmd, (card.mode == CardMode_KEY1)?"CardMode_KEY1":"CardMode_KEY2");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (card.mode == CardMode_DATA_LOAD)
|
||||
{
|
||||
switch(card.command[0])
|
||||
{
|
||||
case 0xB7: // Encrypted Data Read (B7aaaaaaaa000000h) - len 200h bytes
|
||||
card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4];
|
||||
card.transfer_count = 0x200;
|
||||
break;
|
||||
|
||||
case 0xB8: // 3nd Get ROM Chip ID - len 4 bytes
|
||||
card.address = 0;
|
||||
card.transfer_count = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
card.address = 0;
|
||||
card.transfer_count = 0;
|
||||
card.mode = CardMode_KEY1;
|
||||
printf("ARM%c: SLOT1 invalid command %02X (write) - CardMode_DATA_LOAD\n", PROCNUM?'7':'9', card.command[0]);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
protocol.write_command(command);
|
||||
}
|
||||
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
virtual void slot1client_startOperation(eSlot1Operation operation)
|
||||
{
|
||||
rom.start(operation,protocol.address);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
return rom.read();
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_MCROM() { return new Slot1_Retail_MCROM(); }
|
||||
|
||||
// ///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 ---------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -27,9 +27,22 @@
|
|||
#include "../registers.h"
|
||||
#include "../MMU.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
class Slot1_Retail_NAND : public ISlot1Interface
|
||||
//quick architecture overview:
|
||||
//NAND receives GC bus commands from MMU.cpp
|
||||
//those are passed on to the protocol component for parsing
|
||||
//protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly)
|
||||
//NAND utilizes the rom component for address logic and delivering data.
|
||||
//it also processes some commands itself which arent rom-related (the NANDy stuff)
|
||||
|
||||
class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
public:
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
|
@ -39,135 +52,75 @@ public:
|
|||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
}
|
||||
|
||||
virtual u32 read32(u8 PROCNUM, u32 adr)
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
switch(adr)
|
||||
protocol.write_command(command);
|
||||
}
|
||||
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation operation)
|
||||
{
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
case REG_GCDATAIN:
|
||||
return read32_GCDATAIN(PROCNUM);
|
||||
default:
|
||||
return 0;
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_B7_Read:
|
||||
rom.start(operation,protocol.address);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void write32(u8 PROCNUM, u32 adr, u32 val)
|
||||
{
|
||||
switch(adr)
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
case REG_GCROMCTRL:
|
||||
write32_GCROMCTRL(PROCNUM, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void write32_GCROMCTRL(u8 PROCNUM, u32 val)
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[PROCNUM];
|
||||
|
||||
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 = 0x200;
|
||||
break;
|
||||
|
||||
case 0xB8: // Chip ID
|
||||
card.address = 0;
|
||||
card.transfer_count = 4;
|
||||
break;
|
||||
|
||||
// Nand Init
|
||||
case 0x94:
|
||||
card.address = 0;
|
||||
card.transfer_count = 0x200;
|
||||
//GCLOG("NAND 0x94\n");
|
||||
//length = 0x200;
|
||||
break;
|
||||
|
||||
// Nand Error?
|
||||
case 0xD6:
|
||||
card.address = 0;
|
||||
card.transfer_count = 4;
|
||||
//GCLOG("NAND 0xD6\n");
|
||||
//length = 4;
|
||||
break;
|
||||
|
||||
|
||||
// Nand Write? ---- PROGRAM for INTERNAL DATA MOVE/RANDOM DATA INPUT
|
||||
//case 0x8B:
|
||||
case 0x85:
|
||||
card.address = 0;
|
||||
card.transfer_count = 0x200;
|
||||
break;
|
||||
|
||||
default:
|
||||
card.address = 0;
|
||||
card.transfer_count = 0;
|
||||
//GCLOG("NAND 0x85\n");
|
||||
//length = 0x200;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u32 read32_GCDATAIN(u8 PROCNUM)
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
nds_dscard& card = MMU.dscard[PROCNUM];
|
||||
|
||||
switch(card.command[0])
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
//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.
|
||||
|
||||
//note that even if desmume was booting from firmware, and reading this chip ID to store in main memory,
|
||||
//this still works, since it will have read 00 originally and then read 00 to validate.
|
||||
return gameInfo.chipID;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
//it seems that etrian odyssey 3 doesnt work unless we mask this to cart size.
|
||||
//but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision
|
||||
//but there is no test case yet
|
||||
u32 address = card.address & (gameInfo.mask);
|
||||
|
||||
//as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms)
|
||||
//we need to protect ourselves by returning 0xFF for things still out of range
|
||||
if(address >= gameInfo.romsize)
|
||||
{
|
||||
DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return T1ReadLong(MMU.CART_ROM, address);
|
||||
}
|
||||
break;
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_B7_Read:
|
||||
return rom.read();
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
// Nand Init?
|
||||
case 0x94:
|
||||
return 0; //Unsure what to return here so return 0 for now
|
||||
|
@ -177,11 +130,30 @@ private:
|
|||
//0x80 == busy
|
||||
// Made in Ore/WarioWare D.I.Y. need set value to 0x80
|
||||
return 0x80; //0x20 == ready
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
|
||||
{
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_B7_Read:
|
||||
return;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
default:
|
||||
return 0;
|
||||
} //switch(card.command[0])
|
||||
} //read32_GCDATAIN
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
Copyright (C) 2012-2013 DeSmuME team
|
||||
|
||||
This file 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.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
#include "MMU.h"
|
||||
#include "armcpu.h"
|
||||
#include "encrypt.h"
|
||||
#include "utils/decrypt/decrypt.h"
|
||||
|
||||
static _KEY1 key1((const u8*)arm7_key);
|
||||
|
||||
void Slot1Comp_Protocol::reset(ISlot1Comp_Protocol_Client* client)
|
||||
{
|
||||
this->client = client;
|
||||
|
||||
//we have to initialize this to something.. lets use dummy.
|
||||
//(need to clean this up...)
|
||||
memcpy(&command,"\x9F\0\0\0\0\0\0\0",8);
|
||||
operation = eSlot1Operation_9F_Dummy;
|
||||
|
||||
length = 0;
|
||||
delay = 0;
|
||||
mode = eCardMode_RAW;
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_RAW(GC_Command command)
|
||||
{
|
||||
int cmd = command.bytes[0];
|
||||
if(cmd == 0xB7)
|
||||
{
|
||||
//HACK!!!!!!!!!!!!!!!!!!
|
||||
//switch to normal mode. we should do it in the NDSSystem bootup process.
|
||||
//WAY cleaner it will be.
|
||||
mode = eCardMode_NORMAL;
|
||||
//be suer to forward this command to the NORMAL command handler...
|
||||
write_command_NORMAL(command);
|
||||
}
|
||||
if(cmd == 0x9F)
|
||||
{
|
||||
operation = eSlot1Operation_9F_Dummy;
|
||||
delay = 0, length = 0x2000;
|
||||
}
|
||||
if(cmd == 0x90)
|
||||
{
|
||||
operation = eSlot1Operation_90_ChipID;
|
||||
delay = 0, length = 4;
|
||||
//we handle this operation ourselves
|
||||
}
|
||||
if(cmd == 0x3C)
|
||||
{
|
||||
//switch to KEY1
|
||||
delay = 0, length = 0;
|
||||
mode = eCardMode_KEY1;
|
||||
|
||||
//defer initialization of KEY1 until we know we need it, just to save some CPU time.
|
||||
//TODO - some information about these parameters
|
||||
//level == 2
|
||||
//modulo == 8
|
||||
key1.init(gameCode, 2, 0x08);
|
||||
GCLOG("[GC] KEY1 ACTIVATED\n");
|
||||
}
|
||||
if(cmd == 0x00)
|
||||
{
|
||||
operation = eSlot1Operation_00_ReadHeader_Unencrypted;
|
||||
client->slot1client_startOperation(operation);
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_KEY1(GC_Command command)
|
||||
{
|
||||
//decrypt the KEY1-format command
|
||||
u32 temp[2];
|
||||
command.toCryptoBuffer(temp);
|
||||
key1.decrypt(temp);
|
||||
command.fromCryptoBuffer(temp);
|
||||
GCLOG("[GC] (key1-decrypted):"); command.print();
|
||||
|
||||
//and process it:
|
||||
int cmd = command.bytes[0]&0xF0;
|
||||
switch(cmd&0xF0)
|
||||
{
|
||||
case 0x10:
|
||||
operation = eSlot1Operation_1x_ChipID;
|
||||
delay = 0x910, length = 4;
|
||||
//we handle this operation ourselves
|
||||
break;
|
||||
case 0x20:
|
||||
delay = 0x910, length = 0x11A8;
|
||||
break;
|
||||
case 0x30:
|
||||
break;
|
||||
case 0x40:
|
||||
//switch to KEY2
|
||||
delay = 0x910, length = 0;
|
||||
//well.. not really... yet.
|
||||
GCLOG("[GC] KEY2 ACTIVATED\n");
|
||||
break;
|
||||
case 0x60:
|
||||
//KEY2 disable? any info?
|
||||
break;
|
||||
case 0xA0:
|
||||
delay = 0x910, length = 0;
|
||||
mode = eCardMode_NORMAL;
|
||||
GCLOG("[GC] NORMAL MODE ACTIVATED\n");
|
||||
break;
|
||||
case 0xB0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_NORMAL(GC_Command command)
|
||||
{
|
||||
switch(command.bytes[0])
|
||||
{
|
||||
case 0xB7:
|
||||
{
|
||||
operation = eSlot1Operation_B7_Read;
|
||||
|
||||
//TODO - more endian-safe way of doing this
|
||||
u64 cmd64 = bswap64(*(u64*)command.bytes);
|
||||
address = (u32)((cmd64 >> 24));
|
||||
length = 0x200;
|
||||
|
||||
client->slot1client_startOperation(operation);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB8:
|
||||
operation = eSlot1Operation_B8_ChipID;
|
||||
delay = 0, length = 4;
|
||||
//we handle this operation ourselves
|
||||
break;
|
||||
|
||||
default:
|
||||
operation = eSlot1Operation_Unknown;
|
||||
client->slot1client_startOperation(operation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command(GC_Command command)
|
||||
{
|
||||
this->command = command;
|
||||
|
||||
//unrecognized commands will do something depending on the current state of the card
|
||||
delay = 0;
|
||||
length = 0;
|
||||
address = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case eCardMode_RAW:
|
||||
write_command_RAW(command);
|
||||
break;
|
||||
|
||||
case eCardMode_KEY1:
|
||||
write_command_KEY1(command);
|
||||
break;
|
||||
|
||||
case eCardMode_NORMAL:
|
||||
write_command_NORMAL(command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_Unknown:
|
||||
client->slot1client_write_GCDATAIN(operation,val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_B7_Read:
|
||||
return client->slot1client_read_GCDATAIN(operation);
|
||||
|
||||
case eSlot1Operation_Unknown:
|
||||
return client->slot1client_read_GCDATAIN(operation);
|
||||
|
||||
case eSlot1Operation_90_ChipID:
|
||||
case eSlot1Operation_1x_ChipID:
|
||||
case eSlot1Operation_B8_ChipID:
|
||||
// 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 normally 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 to detect card ejects)
|
||||
return chipId;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright (C) 2013 DeSmuME team
|
||||
|
||||
This file 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.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard protocol.
|
||||
//this largely means the complex boot-up process.
|
||||
//i think there's no reason why proprietary cards couldn't speak any protocol they wish, as long as they didn't mind being unbootable.
|
||||
//TODO - could this be refactored into a base class? that's probably more reasonable. but we've gone with this modular mix-in architecture so... not yet.
|
||||
|
||||
#ifndef _SLOT1COMP_PROTOCOL_H
|
||||
#define _SLOT1COMP_PROTOCOL_H
|
||||
|
||||
#include "MMU.h"
|
||||
|
||||
enum eSlot1Operation
|
||||
{
|
||||
//----------
|
||||
//RAW mode operations
|
||||
//before encrypted communications can be established, some values from the rom header must be read.
|
||||
//this is the only way to read the header, actually, since the only reading commands available to games (after KEY2 mode is set) are
|
||||
eSlot1Operation_00_ReadHeader_Unencrypted,
|
||||
//it's not clear why this exists
|
||||
eSlot1Operation_9F_Dummy,
|
||||
eSlot1Operation_90_ChipID,
|
||||
//----------
|
||||
|
||||
//----------
|
||||
//KEY2 mode operations
|
||||
eSlot1Operation_1x_ChipID,
|
||||
//----------
|
||||
|
||||
//----------
|
||||
//NORMAL mode operations
|
||||
//the main rom data reading command
|
||||
eSlot1Operation_B7_Read,
|
||||
eSlot1Operation_B8_ChipID,
|
||||
//----------
|
||||
|
||||
eSlot1Operation_Unknown
|
||||
};
|
||||
|
||||
class ISlot1Comp_Protocol_Client
|
||||
{
|
||||
public:
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) { }
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) = 0;
|
||||
virtual void slot1client_startOperation(eSlot1Operation operation) {}
|
||||
};
|
||||
|
||||
|
||||
class Slot1Comp_Protocol
|
||||
{
|
||||
public:
|
||||
|
||||
//set some kind of protocol/hardware reset state
|
||||
void reset(ISlot1Comp_Protocol_Client* client);
|
||||
|
||||
//signals from the GC bus
|
||||
void write_command(GC_Command command);
|
||||
void write_GCDATAIN(u8 PROCNUM, u32 val);
|
||||
u32 read_GCDATAIN(u8 PROCNUM);
|
||||
|
||||
//helpers for write_command()
|
||||
void write_command_RAW(GC_Command command);
|
||||
void write_command_KEY1(GC_Command command);
|
||||
void write_command_NORMAL(GC_Command command);
|
||||
|
||||
//operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here
|
||||
ISlot1Comp_Protocol_Client* client;
|
||||
|
||||
//the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode
|
||||
eCardMode mode;
|
||||
|
||||
//the current operational state
|
||||
eSlot1Operation operation;
|
||||
|
||||
//the command we're currently crunching on
|
||||
GC_Command command;
|
||||
|
||||
//most operations are defined in terms of returning a series of bytes
|
||||
//the meaning of these varies by operation. they are provided publicly as a service to clients
|
||||
u32 address;
|
||||
s32 length, delay; //the expected length and delay of this state
|
||||
|
||||
//chipId which should be returned by the various chipId commands
|
||||
u32 chipId;
|
||||
|
||||
//gameCode used by the protocol KEY1 crypto
|
||||
u32 gameCode;
|
||||
};
|
||||
|
||||
#endif //_SLOT1COMP_PROTOCOL_H
|
|
@ -15,3 +15,69 @@
|
|||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_rom.h"
|
||||
#include "MMU.h"
|
||||
#include "NDSSystem.h"
|
||||
|
||||
|
||||
void Slot1Comp_Rom::start(eSlot1Operation operation, u32 addr)
|
||||
{
|
||||
this->operation = operation;
|
||||
this->address = addr;
|
||||
}
|
||||
|
||||
u32 Slot1Comp_Rom::read()
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
{
|
||||
u32 ret = T1ReadLong(MMU.CART_ROM, address);
|
||||
address = (address + 4) & 0xFFF;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case eSlot1Operation_B7_Read:
|
||||
{
|
||||
//is this legitimate? need some way to verify.
|
||||
//if(length == 0)
|
||||
// return 0xFFFFFFFF;
|
||||
//length -= 4;
|
||||
|
||||
//TODO - check about non-4-byte aligned addresses
|
||||
|
||||
//OBSOLETED?
|
||||
////it seems that etrian odyssey 3 doesnt work unless we mask this to cart size.
|
||||
////but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision
|
||||
////but there is no test case yet
|
||||
//at any rate, this is good for safety's sake.
|
||||
address &= gameInfo.mask;
|
||||
|
||||
//"Can be used only for addresses 8000h and up, smaller addresses will be silently redirected to address `8000h+(addr AND 1FFh)`"
|
||||
if(address < 0x8000)
|
||||
address = (0x8000 + (address&0x1FF));
|
||||
|
||||
//as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms)
|
||||
//we need to protect ourselves by returning 0xFF for things still out of range
|
||||
if(address+4 >= gameInfo.romsize)
|
||||
{
|
||||
DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
//actually read from the ROM provider
|
||||
u32 ret = T1ReadLong(MMU.CART_ROM, address);
|
||||
|
||||
//"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)"
|
||||
address = (address&~0xFFF) + ((address+4)&0xFFF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
} //switch(operation)
|
||||
} //Slot1Comp_Rom::read()
|
||||
|
|
|
@ -16,6 +16,18 @@
|
|||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard ROMs
|
||||
//this is largely done by accessing the rom resource in the cor eemulator
|
||||
//this is largely done by accessing the rom provided in the core emulator
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
|
||||
class Slot1Comp_Rom
|
||||
{
|
||||
public:
|
||||
void start(eSlot1Operation operation, u32 addr);
|
||||
u32 read();
|
||||
private:
|
||||
u32 address;
|
||||
eSlot1Operation operation;
|
||||
};
|
||||
|
||||
//(TBD)
|
|
@ -19,6 +19,11 @@
|
|||
#include "MMU.h"
|
||||
#include "encrypt.h"
|
||||
|
||||
//TODO - a lot of redundant code (maybe?) with utils/decrypt.cpp
|
||||
//we should try unifying all that.
|
||||
|
||||
//TODO - endian unsafeness in here... dont like the way these take u32. maybe it makes sense and the user is genuinely supposed to present data in units of u32
|
||||
|
||||
//================================================================================== KEY1
|
||||
#define DWNUM(i) ((i) >> 2)
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
struct _KEY1
|
||||
{
|
||||
_KEY1(u8 *inKeyBufPtr)
|
||||
_KEY1(const u8 *inKeyBufPtr)
|
||||
{
|
||||
if (keyBuf) delete keyBuf;
|
||||
keyBuf = new u32 [0x412];
|
||||
|
@ -42,7 +42,7 @@ struct _KEY1
|
|||
|
||||
u32 *keyBuf;
|
||||
u32 keyCode[3];
|
||||
u8 *keyBufPtr;
|
||||
const u8 *keyBufPtr;
|
||||
|
||||
void init(u32 idcode, u8 level, u8 modulo);
|
||||
void applyKeycode(u8 modulo);
|
||||
|
|
|
@ -241,8 +241,10 @@ void rtcInit()
|
|||
|
||||
u16 rtcRead()
|
||||
{
|
||||
//ZEROMUS HACK! MAKE SOMETHING PREDICTABLE FOR FIRMWARE BOOT TESTS!
|
||||
//INFO("MMU Read RTC 0x%02X (%03i)\n", rtc._REG, rtc.bitsCount);
|
||||
return (rtc._REG);
|
||||
//return (rtc._REG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtcWrite(u16 val)
|
||||
|
|
|
@ -242,10 +242,8 @@ SFORMAT SF_MMU[]={
|
|||
{ "BUWR", 4, 1, &MMU.fw.writeable_buffer},
|
||||
//end memory chips
|
||||
|
||||
{ "MC0A", 4, 1, &MMU.dscard[0].address},
|
||||
{ "MC0T", 4, 1, &MMU.dscard[0].transfer_count},
|
||||
{ "MC1A", 4, 1, &MMU.dscard[1].address},
|
||||
{ "MC1T", 4, 1, &MMU.dscard[1].transfer_count},
|
||||
{ "GCTC", 4, 1, &MMU.dscard.transfer_count},
|
||||
{ "GCMO", 4, 1, &MMU.dscard.mode},
|
||||
//{ "MCHT", 4, 1, &MMU.CheckTimers},
|
||||
//{ "MCHD", 4, 1, &MMU.CheckDMAs},
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ Since GCROMCTRL[26:24] can't represent 'data block size' of 1 or 2, it is assume
|
|||
...so, any 8/16bit accesses to GCDATAIN would transfer a whole 32bit unit and then just return the requested portion
|
||||
*/
|
||||
|
||||
//TODO - create a Slot1_TurboRom which we can select when booting from fakebios/nonfirmware and which would provide a useful service to people porting to tighter platforms by bypassing largely useless cruft
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "types.h"
|
||||
|
@ -74,7 +76,7 @@ EMUFILE* slot1_GetFatImage()
|
|||
|
||||
//------------
|
||||
|
||||
ISlot1Interface* slot1_List[NDS_SLOT1_COUNT];
|
||||
ISlot1Interface* slot1_List[NDS_SLOT1_COUNT] = {0};
|
||||
|
||||
ISlot1Interface* slot1_device = NULL;
|
||||
NDS_SLOT1_TYPE slot1_device_type = NDS_SLOT1_RETAIL_AUTO; //default for frontends that dont even configure this
|
||||
|
@ -95,7 +97,7 @@ void slot1_Init()
|
|||
extern TISlot1InterfaceConstructor construct_Slot1_Retail_MCROM;
|
||||
slot1_List[NDS_SLOT1_NONE] = construct_Slot1_None();
|
||||
slot1_List[NDS_SLOT1_RETAIL_AUTO] = construct_Slot1_Retail_Auto();
|
||||
slot1_List[NDS_SLOT1_R4] = construct_Slot1_R4();
|
||||
slot1_List[NDS_SLOT1_R4] = construct_Slot1_None(); //HACK!!! R4 IS BROKEN RIGHT NOW
|
||||
slot1_List[NDS_SLOT1_RETAIL_NAND] = construct_Slot1_Retail_NAND();
|
||||
slot1_List[NDS_SLOT1_RETAIL_MCROM] = construct_Slot1_Retail_MCROM();
|
||||
}
|
||||
|
@ -104,7 +106,8 @@ void slot1_Shutdown()
|
|||
{
|
||||
for(int i=0;i<ARRAY_SIZE(slot1_List);i++)
|
||||
{
|
||||
slot1_List[i]->shutdown();
|
||||
if(slot1_List[i])
|
||||
slot1_List[i]->shutdown();
|
||||
delete slot1_List[i];
|
||||
}
|
||||
}
|
||||
|
@ -159,4 +162,119 @@ bool slot1_Change(NDS_SLOT1_TYPE changeToType)
|
|||
NDS_SLOT1_TYPE slot1_GetCurrentType()
|
||||
{
|
||||
return slot1_device_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// --- Ninja SD commands notes -------------------------------------
|
||||
// ///writetoGCControl:
|
||||
|
||||
// // 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 ---------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
#include "MMU.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
|
@ -64,15 +65,14 @@ public:
|
|||
//called when the emulator shuts down, or when the device disappears from existence
|
||||
virtual void shutdown() { }
|
||||
|
||||
//called when the emulator write to the slot (TODO - refactors necessary)
|
||||
void write08(u8 PROCNUM, u32 adr, u8 val) { printf("WARNING: 8bit write to slot-1\n"); }
|
||||
void write16(u8 PROCNUM, u32 adr, u16 val) { printf("WARNING: 16bit write to slot-1\n"); }
|
||||
virtual void write32(u8 PROCNUM, u32 adr, u32 val) { }
|
||||
//called then the cpu begins a new command/block on the GC bus
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command) { }
|
||||
|
||||
//called when the emulator reads from the slot (TODO - refactors necessary)
|
||||
u8 read08(u8 PROCNUM, u32 adr) { printf("WARNING: 8bit read from slot-1\n"); return 0xFF; }
|
||||
u16 read16(u8 PROCNUM, u32 adr) { printf("WARNING: 16bit read from slot-1\n"); return 0xFFFF; }
|
||||
virtual u32 read32(u8 PROCNUM, u32 adr) { return 0xFFFFFFFF; }
|
||||
//called when the cpu writes to the GC bus
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { }
|
||||
|
||||
//called when the cpu reads from the GC bus
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM) { return 0xFFFFFFFF; }
|
||||
|
||||
//transfers a byte to the slot-1 device via auxspi, and returns the incoming byte
|
||||
//cpu is provided for diagnostic purposes only.. the slot-1 device wouldn't know which CPU it is.
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "header.h"
|
||||
#include "decrypt.h"
|
||||
|
||||
const unsigned char encr_data[] =
|
||||
//encr_data
|
||||
const unsigned char arm7_key[] =
|
||||
{
|
||||
0x99,0xD5,0x20,0x5F,0x57,0x44,0xF5,0xB9,0x6E,0x19,0xA4,0xD9,0x9E,0x6A,0x5A,0x94,
|
||||
0xD8,0xAE,0xF1,0xEB,0x41,0x75,0xE2,0x3A,0x93,0x82,0xD0,0x32,0x33,0xEE,0x31,0xD5,
|
||||
|
@ -396,7 +397,7 @@ static void init2(u32 *magic, u32 a[3])
|
|||
|
||||
static void init1(u32 cardheader_gamecode)
|
||||
{
|
||||
memcpy(card_hash, &encr_data, 4*(1024 + 18));
|
||||
memcpy(card_hash, &arm7_key, 4*(1024 + 18));
|
||||
arg2[0] = *(u32 *)&cardheader_gamecode;
|
||||
arg2[1] = (*(u32 *)&cardheader_gamecode) >> 1;
|
||||
arg2[2] = (*(u32 *)&cardheader_gamecode) << 1;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#ifndef _DECRYPT_H_
|
||||
#define _DECRYPT_H_
|
||||
|
||||
extern const unsigned char arm7_key[];
|
||||
|
||||
//decrypts the secure area of a rom (or does nothing if it is already decrypted)
|
||||
bool DecryptSecureArea(u8 *romdata, long romlen);
|
||||
|
||||
|
|
|
@ -2223,6 +2223,14 @@
|
|||
RelativePath="..\addons\slot1comp_mc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\addons\slot1comp_protocol.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\addons\slot1comp_protocol.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\addons\slot1comp_rom.cpp"
|
||||
>
|
||||
|
|
|
@ -1029,6 +1029,14 @@
|
|||
RelativePath="..\addons\slot1comp_mc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\addons\slot1comp_protocol.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\addons\slot1comp_protocol.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\addons\slot1comp_rom.cpp"
|
||||
>
|
||||
|
|
|
@ -371,6 +371,7 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="..\addons.cpp" />
|
||||
<ClCompile Include="..\addons\slot1comp_mc.cpp" />
|
||||
<ClCompile Include="..\addons\slot1comp_protocol.cpp" />
|
||||
<ClCompile Include="..\addons\slot1comp_rom.cpp" />
|
||||
<ClCompile Include="..\addons\slot1_retail_auto.cpp" />
|
||||
<ClCompile Include="..\addons\slot1_retail_mcrom.cpp" />
|
||||
|
@ -653,6 +654,7 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="..\addons.h" />
|
||||
<ClInclude Include="..\addons\slot1comp_mc.h" />
|
||||
<ClInclude Include="..\addons\slot1comp_protocol.h" />
|
||||
<ClInclude Include="..\addons\slot1comp_rom.h" />
|
||||
<ClInclude Include="..\armcpu.h" />
|
||||
<ClInclude Include="..\arm_jit.h" />
|
||||
|
|
|
@ -795,6 +795,9 @@
|
|||
<ClCompile Include="..\utils\advanscene.cpp">
|
||||
<Filter>Core\utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\addons\slot1comp_protocol.cpp">
|
||||
<Filter>Core\addons</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\addons.h">
|
||||
|
@ -1533,6 +1536,9 @@
|
|||
<ClInclude Include="..\utils\advanscene.h">
|
||||
<Filter>Core\utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\addons\slot1comp_protocol.h">
|
||||
<Filter>Core\addons</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\instruction_tabdef.inc">
|
||||
|
|
|
@ -382,6 +382,7 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="..\addons.cpp" />
|
||||
<ClCompile Include="..\addons\slot1comp_mc.cpp" />
|
||||
<ClCompile Include="..\addons\slot1comp_protocol.cpp" />
|
||||
<ClCompile Include="..\addons\slot1comp_rom.cpp" />
|
||||
<ClCompile Include="..\addons\slot1_retail_auto.cpp" />
|
||||
<ClCompile Include="..\addons\slot1_retail_mcrom.cpp" />
|
||||
|
@ -664,6 +665,7 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="..\addons.h" />
|
||||
<ClInclude Include="..\addons\slot1comp_mc.h" />
|
||||
<ClInclude Include="..\addons\slot1comp_protocol.h" />
|
||||
<ClInclude Include="..\addons\slot1comp_rom.h" />
|
||||
<ClInclude Include="..\armcpu.h" />
|
||||
<ClInclude Include="..\arm_jit.h" />
|
||||
|
|
|
@ -787,6 +787,9 @@
|
|||
<ClCompile Include="..\utils\advanscene.cpp">
|
||||
<Filter>Core\utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\addons\slot1comp_protocol.cpp">
|
||||
<Filter>Core\addons</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\addons.h">
|
||||
|
@ -1395,6 +1398,9 @@
|
|||
<ClInclude Include="..\utils\advanscene.h">
|
||||
<Filter>Core\utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\addons\slot1comp_protocol.h">
|
||||
<Filter>Core\addons</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\instruction_tabdef.inc">
|
||||
|
|
|
@ -3544,7 +3544,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
|
|||
if (gShowConsole)
|
||||
{
|
||||
OpenConsole(); // Init debug console
|
||||
ConsoleAlwaysTop(gConsoleTopmost);
|
||||
//ConsoleAlwaysTop(gConsoleTopmost);
|
||||
}
|
||||
|
||||
//--------------------------------
|
||||
|
@ -6082,7 +6082,7 @@ DOKEYDOWN:
|
|||
case IDM_CONSOLE_ALWAYS_ON_TOP:
|
||||
{
|
||||
gConsoleTopmost = !gConsoleTopmost;
|
||||
ConsoleAlwaysTop(gConsoleTopmost);
|
||||
//ConsoleAlwaysTop(gConsoleTopmost);
|
||||
WritePrivateProfileBool("Console", "Always On Top", gConsoleTopmost, IniName);
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue