/* Copyright (C) 2010-2011 DeSmuME team
This file is part of DeSmuME
DeSmuME 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.
DeSmuME 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 DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../slot1.h"
#include "../registers.h"
#include "../MMU.h"
#include "../NDSSystem.h"
static void info(char *info) { strcpy(info, "Slot1 Retail card emulation"); }
static void config() {}
static bool init() { return true; }
static void reset() {}
static void close() {}
static void write08(uint8_t, uint32_t, uint8_t) {}
static void write16(uint8_t, uint32_t, uint16_t) {}
static void write32_GCROMCTRL(uint8_t PROCNUM, uint32_t)
{
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 = 0x80;
break;
case 0xB8: // Chip ID
card.address = 0;
card.transfer_count = 1;
break;
default:
card.address = 0;
card.transfer_count = 0;
}
}
static void write32(uint8_t PROCNUM, uint32_t adr, uint32_t val)
{
switch (adr)
{
case REG_GCROMCTRL:
write32_GCROMCTRL(PROCNUM, val);
}
}
static uint8_t read08(uint8_t, uint32_t)
{
return 0xFF;
}
static uint16_t read16(uint8_t, uint32_t)
{
return 0xFFFF;
}
static uint32_t read32_GCDATAIN(uint8_t PROCNUM)
{
nds_dscard &card = MMU.dscard[PROCNUM];
switch (card.command[0])
{
// 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.
// staff of kings verifies this (it also uses the arm7 IRQ 20)
if (nds.cardEjected) // TODO - handle this with ejected card slot1 device (and verify using this case)
return 0xFFFFFFFF;
else
return 0;
}
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
uint32_t address = card.address & (gameInfo.mask);
// Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart
if((card.command[0] == 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:
return 0;
} //switch(card.command[0])
} //read32_GCDATAIN
static uint32_t read32(uint8_t PROCNUM, uint32_t adr)
{
switch(adr)
{
case REG_GCDATAIN:
return read32_GCDATAIN(PROCNUM);
default:
return 0;
}
}
SLOT1INTERFACE slot1Retail =
{
"Retail",
init,
reset,
close,
config,
write08,
write16,
write32,
read08,
read16,
read32,
info
};
// ///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 ---------------------------------