diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index f4f526d65..dd7ce435c 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -1279,7 +1279,7 @@ bool DSI_TSC::load_state(EMUFILE* is) return true; } -static void FASTCALL MMU_endTransfer(u32 PROCNUM) +void MMU_GC_endTransfer(u32 PROCNUM) { u32 val = T1ReadLong(MMU.MMU_MEM[0][0x40], 0x1A4) & 0x7F7FFFFF; T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4, val); @@ -1367,7 +1367,7 @@ void FASTCALL MMU_writeToGCControl(u32 val) //if there was nothing to be done here, go ahead and flag it as done if(card.transfer_count == 0) { - MMU_endTransfer(PROCNUM); + MMU_GC_endTransfer(PROCNUM); return; } @@ -1399,7 +1399,7 @@ u32 MMU_readFromGC() //update transfer counter and complete the transfer if necessary card.transfer_count -= 4; if(!card.transfer_count) - MMU_endTransfer(PROCNUM); + MMU_GC_endTransfer(PROCNUM); return val; } diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index 255ecd337..2abe6cbaa 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -319,6 +319,8 @@ enum eCardMode : u32 //#define GCLOG(...) printf(__VA_ARGS__); #define GCLOG(...) +void MMU_GC_endTransfer(u32 PROCNUM); + struct GC_Command { u8 bytes[8]; diff --git a/desmume/src/addons/slot1_r4.cpp b/desmume/src/addons/slot1_r4.cpp index 60cd8e2ce..c1eeb662d 100644 --- a/desmume/src/addons/slot1_r4.cpp +++ b/desmume/src/addons/slot1_r4.cpp @@ -1,231 +1,236 @@ -///* -// 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 . -//*/ -// -//#include -// -//#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(); } \ No newline at end of file +/* + 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 . +*/ + +#include + +#include "../slot1.h" +#include "../registers.h" +#include "../MMU.h" +#include "../NDSSystem.h" +#include "../emufile.h" +#include "slot1comp_protocol.h" + +class Slot1_R4 : public ISlot1Interface, public ISlot1Comp_Protocol_Client +{ +private: + EMUFILE *img; + Slot1Comp_Protocol protocol; + 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"); + + protocol.reset(this); + protocol.chipId = 0xFC2; + protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0); + } + + //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 void write_command(u8 PROCNUM, GC_Command command) + { + 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) + { + if(operation != eSlot1Operation_Unknown) + return; + + u32 address; + int cmd = protocol.command.bytes[0]; + switch(cmd) + { + case 0xB0: + break; + case 0xB9: + case 0xBA: + address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4]; + img->fseek(address,SEEK_SET); + break; + case 0xBB: + write_enabled = 1; + write_count = 0x80; + //passthrough on purpose? + case 0xBC: + address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4]; + img->fseek(address,SEEK_SET); + break; + } + } + + virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) + { + if(operation != eSlot1Operation_Unknown) + return 0; + + u32 val; + int cmd = protocol.command.bytes[0]; + switch(cmd) + { + 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; + break; + } + + return val; + } + + void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) + { + if(operation != eSlot1Operation_Unknown) + return; + + int cmd = protocol.command.bytes[0]; + switch(cmd) + { + case 0xBB: + { + if(write_count && write_enabled) + { + img->fwrite(&val, 4); + img->fflush(); + write_count--; + } + break; + } + default: + break; + } + } + + void write32_GCDATAIN(u32 val) + { + //bool log = false; + + //last_write_count = write_count; + + //can someone tell me ... what the hell is this doing, anyway? + //seems odd to use card.command[4] for this... isnt it part of the address? + if(protocol.command.bytes[4]) + { + // transfer is done + //are you SURE this is logical? there doesnt seem to be any way for the card to signal that + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); + + MMU_GC_endTransfer(0); + + return; + } + + int cmd = protocol.command.bytes[0]; + switch(cmd) + { + 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 + + //are you SURE this is logical? there doesnt seem to be any way for the card to signal that + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); + + MMU_GC_endTransfer(0); + } + + /*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(); } \ No newline at end of file diff --git a/desmume/src/addons/slot1_retail_mcrom.cpp b/desmume/src/addons/slot1_retail_mcrom.cpp index 1a2392a7e..7f1119af6 100644 --- a/desmume/src/addons/slot1_retail_mcrom.cpp +++ b/desmume/src/addons/slot1_retail_mcrom.cpp @@ -64,7 +64,6 @@ public: { protocol.write_command(command); } - virtual void write_GCDATAIN(u8 PROCNUM, u32 val) { protocol.write_GCDATAIN(PROCNUM, val); @@ -73,6 +72,7 @@ public: { return protocol.read_GCDATAIN(PROCNUM); } + virtual void slot1client_startOperation(eSlot1Operation operation) { rom.start(operation,protocol.address); diff --git a/desmume/src/addons/slot1comp_protocol.h b/desmume/src/addons/slot1comp_protocol.h index 06228a612..001260037 100644 --- a/desmume/src/addons/slot1comp_protocol.h +++ b/desmume/src/addons/slot1comp_protocol.h @@ -55,9 +55,9 @@ enum eSlot1Operation 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) {} + virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) = 0; + virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val) {} }; diff --git a/desmume/src/slot1.cpp b/desmume/src/slot1.cpp index bde8a8f76..2aafb73f1 100644 --- a/desmume/src/slot1.cpp +++ b/desmume/src/slot1.cpp @@ -97,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_None(); //HACK!!! R4 IS BROKEN RIGHT NOW + slot1_List[NDS_SLOT1_R4] = construct_Slot1_R4(); slot1_List[NDS_SLOT1_RETAIL_NAND] = construct_Slot1_Retail_NAND(); slot1_List[NDS_SLOT1_RETAIL_MCROM] = construct_Slot1_Retail_MCROM(); }