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