Fixed writes to GCDATAIN.
Added proper NAND save emulation.
This commit is contained in:
parent
81c063bec9
commit
eb1f462016
|
@ -1354,6 +1354,13 @@ void FASTCALL MMU_writeToGCControl(u32 val)
|
|||
{
|
||||
GCLOG("[GC] command:"); rawcmd.print();
|
||||
slot1_device->write_command(PROCNUM, rawcmd);
|
||||
|
||||
/*INFO("WRITE: %02X%02X%02X%02X%02X%02X%02X%02X ",
|
||||
rawcmd.bytes[0], rawcmd.bytes[1], rawcmd.bytes[2], rawcmd.bytes[3],
|
||||
rawcmd.bytes[4], rawcmd.bytes[5], rawcmd.bytes[6], rawcmd.bytes[7]);
|
||||
INFO("FROM: %08X ", (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr);
|
||||
INFO("1A4: %08X ", val);
|
||||
INFO("SIZE: %08X\n", blocksize);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1398,15 +1405,29 @@ u32 MMU_readFromGC()
|
|||
|
||||
//update transfer counter and complete the transfer if necessary
|
||||
card.transfer_count -= 4;
|
||||
if(!card.transfer_count)
|
||||
if(card.transfer_count <= 0)
|
||||
{
|
||||
MMU_GC_endTransfer(0);
|
||||
MMU_GC_endTransfer(1);
|
||||
MMU_GC_endTransfer(PROCNUM);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template<int PROCNUM>
|
||||
void MMU_writeToGC(u32 val)
|
||||
{
|
||||
GCBUS_Controller& card = MMU.dscard[PROCNUM];
|
||||
|
||||
slot1_device->write_GCDATAIN(PROCNUM,val);
|
||||
|
||||
//update transfer counter and complete the transfer if necessary
|
||||
card.transfer_count -= 4;
|
||||
if(card.transfer_count <= 0)
|
||||
{
|
||||
MMU_GC_endTransfer(PROCNUM);
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================== REG_SPIxxx
|
||||
static void CalculateTouchPressure(int pressurePercent, u16 &z1, u16& z2)
|
||||
{
|
||||
|
@ -3989,7 +4010,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->write_GCDATAIN(ARMCPU_ARM9 ,val);
|
||||
MMU_writeToGC<ARMCPU_ARM9>(val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4747,7 +4768,7 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
|
|||
return;
|
||||
|
||||
case REG_GCDATAIN:
|
||||
slot1_device->write_GCDATAIN(ARMCPU_ARM7, val);
|
||||
MMU_writeToGC<ARMCPU_ARM7>(val);
|
||||
return;
|
||||
}
|
||||
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val);
|
||||
|
|
|
@ -350,7 +350,7 @@ struct GC_Command
|
|||
//should rather be known as GCBUS controller, or somesuch
|
||||
struct GCBUS_Controller
|
||||
{
|
||||
u32 transfer_count;
|
||||
int transfer_count;
|
||||
eCardMode mode; //probably only one of these
|
||||
};
|
||||
|
||||
|
|
|
@ -33,16 +33,22 @@
|
|||
//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)
|
||||
//protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesn't 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)
|
||||
//it also processes some commands itself which aren't rom-related (the NANDy stuff)
|
||||
|
||||
class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
u32 subAdr;
|
||||
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
u32 mode;
|
||||
u32 handle_save;
|
||||
u32 save_adr;
|
||||
|
||||
public:
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
|
@ -55,6 +61,13 @@ public:
|
|||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
|
||||
handle_save = 0;
|
||||
|
||||
NDS_header * _header = NDS_getROMHeader();
|
||||
subAdr = (_header->unknown5[0xE] | _header->unknown5[0xF]<<8) << 17;
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
|
@ -73,6 +86,8 @@ public:
|
|||
|
||||
virtual void slot1client_startOperation(eSlot1Operation operation)
|
||||
{
|
||||
protocol.address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
|
@ -87,23 +102,33 @@ public:
|
|||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
//Nand Write Page
|
||||
case 0x81:
|
||||
break;
|
||||
|
||||
// Nand Init
|
||||
case 0x94:
|
||||
//GCLOG("NAND 0x94\n");
|
||||
//length = 0x200;
|
||||
mode = cmd;
|
||||
break;
|
||||
|
||||
// Nand Error?
|
||||
case 0xD6:
|
||||
//GCLOG("NAND 0xD6\n");
|
||||
//length = 4;
|
||||
break;
|
||||
|
||||
// Nand Write? ---- PROGRAM for INTERNAL DATA MOVE/RANDOM DATA INPUT
|
||||
//case 0x8B:
|
||||
case 0x85:
|
||||
//GCLOG("NAND 0x85\n");
|
||||
//length = 0x200;
|
||||
case 0x84: //Write disable
|
||||
case 0x85: //Write enable
|
||||
mode = cmd;
|
||||
break;
|
||||
case 0x8B:
|
||||
mode = cmd;
|
||||
handle_save = 0;
|
||||
break;
|
||||
|
||||
case 0xB2: //Set save position
|
||||
mode = cmd;
|
||||
save_adr = protocol.address & gameInfo.mask;
|
||||
save_adr -= subAdr;
|
||||
handle_save = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -115,26 +140,68 @@ public:
|
|||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
case eSlot1Operation_B7_Read:
|
||||
//case eSlot1Operation_B7_Read:
|
||||
return rom.read();
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
int val = 0;
|
||||
switch(cmd)
|
||||
{
|
||||
// Nand Init?
|
||||
case 0x94:
|
||||
return 0; //Unsure what to return here so return 0 for now
|
||||
val = 0;
|
||||
mode = 0;
|
||||
break;
|
||||
|
||||
//Rom/Save Read
|
||||
case 0xB7:
|
||||
{
|
||||
if(handle_save)
|
||||
{
|
||||
MMU_new.backupDevice.ensure(save_adr+4,0);
|
||||
val = MMU_new.backupDevice.data[save_adr+3]<<24 | MMU_new.backupDevice.data[save_adr+2]<<16 | MMU_new.backupDevice.data[save_adr+1]<<8| MMU_new.backupDevice.data[save_adr+0]<<0;
|
||||
|
||||
MMU_new.backupDevice.setLazyFlushPending();
|
||||
|
||||
save_adr += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = rom.read();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Nand Status?
|
||||
case 0xD6:
|
||||
//0x80 == busy
|
||||
// Made in Ore/WarioWare D.I.Y. need set value to 0x80
|
||||
return 0x80; //0x20 == ready
|
||||
//0x40 == ??
|
||||
//0x20 == ready?
|
||||
//0x10 == write enabled?
|
||||
switch (mode)
|
||||
{
|
||||
case 0x84: //Write disable
|
||||
val = 0x20202020;
|
||||
break;
|
||||
case 0x85: //Write enable
|
||||
val = 0x20202020 | 0x10101010;
|
||||
break;
|
||||
case 0x8B:
|
||||
val = 0x60606060 | 0x10101010;
|
||||
break;
|
||||
case 0xB2: //Set save position
|
||||
val = 0x20202020;
|
||||
break;
|
||||
default:
|
||||
val = 0x60606060; //0x20 == ready
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
|
||||
|
@ -150,8 +217,19 @@ public:
|
|||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
u32 value = val;
|
||||
u32 adr = save_adr;
|
||||
switch(cmd)
|
||||
{
|
||||
case 0x81: //Nand Write
|
||||
MMU_new.backupDevice.ensure(adr+4,0);
|
||||
MMU_new.backupDevice.data[adr+0] = (val >> 0) & 0xFF;
|
||||
MMU_new.backupDevice.data[adr+1] = (val >> 8) & 0xFF;
|
||||
MMU_new.backupDevice.data[adr+2] = (val >> 16) & 0xFF;
|
||||
MMU_new.backupDevice.data[adr+3] = (val >> 24) & 0xFF;
|
||||
MMU_new.backupDevice.setFlushPending();
|
||||
save_adr += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -464,20 +464,30 @@ u8 BackupDevice::data_command(u8 val, int cpu)
|
|||
|
||||
//guarantees that the data buffer has room enough for the specified number of bytes
|
||||
void BackupDevice::ensure(u32 addr)
|
||||
{
|
||||
ensure(addr,kUninitializedSaveDataValue);
|
||||
}
|
||||
|
||||
void BackupDevice::ensure(u32 addr, u8 val)
|
||||
{
|
||||
u32 size = data.size();
|
||||
if(size<addr)
|
||||
{
|
||||
resize(addr);
|
||||
resize(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
void BackupDevice::resize(u32 size)
|
||||
{
|
||||
resize(size,kUninitializedSaveDataValue);
|
||||
}
|
||||
|
||||
void BackupDevice::resize(u32 size, u8 val)
|
||||
{
|
||||
size_t old_size = data.size();
|
||||
data.resize(size);
|
||||
for(u32 i=old_size;i<size;i++)
|
||||
data[i] = kUninitializedSaveDataValue;
|
||||
data[i] = val;
|
||||
}
|
||||
|
||||
u32 BackupDevice::addr_size_for_old_save_size(int bupmem_size)
|
||||
|
|
|
@ -111,6 +111,12 @@ public:
|
|||
void lazy_flush();
|
||||
void flush();
|
||||
|
||||
void setFlushPending() { flushPending = true; }
|
||||
void setLazyFlushPending() { lazyFlushPending = true; }
|
||||
|
||||
void ensure(u32 addr);
|
||||
void ensure(u32 addr, u8 val);
|
||||
|
||||
struct {
|
||||
u32 size,padSize,type,addr_size,mem_size;
|
||||
} info;
|
||||
|
@ -144,12 +150,11 @@ private:
|
|||
|
||||
void loadfile();
|
||||
bool _loadfile(const char *fname);
|
||||
void ensure(u32 addr);
|
||||
|
||||
bool flushPending, lazyFlushPending;
|
||||
|
||||
private:
|
||||
void resize(u32 size);
|
||||
void resize(u32 size, u8 val);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue