massive slot-1 reorganization and code cleanup

This commit is contained in:
zeromus 2013-08-28 06:48:05 +00:00
parent b464ea0461
commit e0d02ddda2
28 changed files with 1080 additions and 903 deletions

View File

@ -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)
@ -1315,188 +1310,77 @@ 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++;
nds_dscard& card = MMU.dscard[PROCNUM];
GCBUS_Controller& card = MMU.dscard;
memcpy(&card.command[0], &MMU.MMU_MEM[PROCNUM][0x40][0x1A8], 8);
//....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];
card.blocklen = 0;
//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);
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)
//pluck out the command registers into a more convenient format
GC_Command rawcmd = *(GC_Command*)&MMU.MMU_MEM[PROCNUM][0x40][0x1A8];
//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)
{
#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);
#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)
{
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);

View File

@ -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;
};

View File

@ -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 \

View File

@ -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

View File

@ -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)
};

View File

@ -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(); }

View File

@ -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)

View File

@ -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 ---------------------------------

View File

@ -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
};

View File

@ -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;
}

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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},

View File

@ -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];
}
}
@ -160,3 +163,118 @@ 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 ---------------------------------

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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"
>

View File

@ -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"
>

View File

@ -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" />

View File

@ -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">

View File

@ -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" />

View File

@ -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">

View File

@ -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;