/***************************************************************************** ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/SlotManager.c,v $ ** ** $Revision: 1.8 $ ** ** $Date: 2008-03-30 18:38:42 $ ** ** More info: http://www.bluemsx.com ** ** Copyright (C) 2003-2006 Daniel Vik ** ** This program 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 program 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 this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** ****************************************************************************** */ #include "SlotManager.h" #include "SaveState.h" #include "Led.h" #include "IoPort.h" #include #include #include typedef struct { UInt8* pageData; int readEnable; int writeEnable; } RamSlotState; typedef struct { int subslotted; UInt8 state; UInt8 substate; UInt8 sslReg; } PrimarySlotState; typedef struct { UInt16 startpage; UInt16 pages; UInt8* pageData; int writeEnable; int readEnable; SlotRead read; SlotRead peek; SlotWrite write; SlotEject eject; void* ref; } Slot; static RamSlotState ramslot[8]; static PrimarySlotState pslot[4]; static Slot slotTable[4][4][8]; static Slot slotAddr0; static UInt8 emptyRAM[0x2000]; static Int32 initialized; void slotMapRamPage(int slot, int sslot, int page) { ramslot[page].readEnable = slotTable[slot][sslot][page].readEnable; ramslot[page].writeEnable = slotTable[slot][sslot][page].writeEnable; ramslot[page].pageData = slotTable[slot][sslot][page].pageData; } void slotSetRamSlot(int slot, int psl) { int ssl; pslot[slot].state = psl; pslot[slot].substate = (pslot[psl].sslReg >> (slot * 2)) & 3; ssl = pslot[psl].subslotted ? pslot[slot].substate : 0; slotMapRamPage(psl, ssl, 2 * slot); slotMapRamPage(psl, ssl, 2 * slot + 1); } int slotGetRamSlot(int page) { int i; for (i = 0; i < 4; i++) { if (pslot[i].state == page) { return i; } } return 0; } void slotMapPage(int slot, int sslot, int page, UInt8* pageData, int readEnable, int writeEnable) { if (!initialized) { return; } slotTable[slot][sslot][page].readEnable = readEnable; slotTable[slot][sslot][page].writeEnable = writeEnable; if (pageData != NULL) { slotTable[slot][sslot][page].pageData = pageData; } #if 0 if (pslot[page >> 1].state == slot && (!pslot[slot].subslotted || sslot == 2 || pslot[page >> 1].substate == sslot)) { slotMapRamPage(slot, sslot, page); } #else if (pslot[page >> 1].state == slot && (!pslot[slot].subslotted || pslot[page >> 1].substate == sslot)) { slotMapRamPage(slot, sslot, page); } #endif } void slotUpdatePage(int slot, int sslot, int page, UInt8* pageData, int readEnable, int writeEnable) { if (!initialized) { return; } slotMapPage(slot, sslot, page, pageData, readEnable, writeEnable); return; slotTable[slot][sslot][page].readEnable = readEnable; slotTable[slot][sslot][page].writeEnable = writeEnable; if (pageData != NULL) { slotTable[slot][sslot][page].pageData = pageData; } } void slotUnmapPage(int slot, int sslot, int page) { if (!initialized) { return; } slotTable[slot][sslot][page].readEnable = 0; slotTable[slot][sslot][page].writeEnable = 1; slotTable[slot][sslot][page].pageData = emptyRAM; if (pslot[page >> 1].state == slot && (!pslot[slot].subslotted || pslot[page >> 1].substate == sslot)) { slotMapRamPage(slot, sslot, page); } } void slotRegisterWrite0(SlotWrite writeCb, void* ref) { if (!initialized) { return; } slotAddr0.read = NULL; slotAddr0.write = writeCb; slotAddr0.eject = NULL; slotAddr0.ref = ref; } void slotUnregisterWrite0() { if (!initialized) { return; } memset(&slotAddr0, 0, sizeof(Slot)); } void slotRegister(int slot, int sslot, int startpage, int pages, SlotRead readCb, SlotRead peekCb, SlotWrite writeCb, SlotEject ejectCb, void* ref) { Slot* slotInfo; if (!initialized) { return; } slotInfo = &slotTable[slot][sslot][startpage]; slotInfo->pages = pages; while (pages--) { slotInfo->startpage = startpage; slotInfo->read = readCb; slotInfo->peek = peekCb; slotInfo->write = writeCb; slotInfo->eject = ejectCb; slotInfo->ref = ref; slotInfo++; } } void slotUnregister(int slot, int sslot, int startpage) { Slot* slotInfo; int pages; if (!initialized) { return; } slotInfo = &slotTable[slot][sslot][startpage]; pages = slotInfo->pages; while (pages--) { memset(slotInfo, 0, sizeof(Slot)); slotUnmapPage(slot, sslot, startpage + pages); slotInfo++; } } void slotRemove(int slot, int sslot) { int page; if (!initialized) { return; } for (page = 0; page < 8; page++) { Slot* slotInfo = &slotTable[slot][sslot][page]; if (slotInfo->eject != NULL) { slotInfo->eject(slotInfo->ref); } } } void slotSetSubslotted(int slot, int subslotted) { if (!initialized) { return; } pslot[slot].subslotted = subslotted; } void slotManagerReset() { int page; if (!initialized) { return; } for (page = 0; page < 4; page++) { pslot[page].state = 0; pslot[page].substate = 0; slotMapRamPage(0, 0, 2 * page); slotMapRamPage(0, 0, 2 * page + 1); } } void slotManagerCreate() { int slot; int sslot; int page; memset(emptyRAM, 0xff, 0x2000); memset(ramslot, 0, sizeof(ramslot)); memset(pslot, 0, sizeof(pslot)); memset(slotTable, 0, sizeof(slotTable)); memset(&slotAddr0, 0, sizeof(slotAddr0)); for (slot = 0; slot < 4; slot++) { for (sslot = 0; sslot < 4; sslot++) { for (page = 0; page < 8; page++) { slotUnmapPage(slot, sslot, page); } } } initialized = 1; } void slotManagerDestroy() { initialized = 0; } UInt8 slotPeek(void* ref, UInt16 address) { Slot* slotInfo; int psl; int ssl; if (!initialized) { return 0xff; } if (address == 0xffff) { UInt8 sslReg = pslot[3].state; if (pslot[sslReg].subslotted) { return ~pslot[sslReg].sslReg; } } if (ramslot[address >> 13].readEnable) { return ramslot[address >> 13].pageData[address & 0x1fff]; } psl = pslot[address >> 14].state; ssl = pslot[psl].subslotted ? pslot[address >> 14].substate : 0; slotInfo = &slotTable[psl][ssl][address >> 13]; if (slotInfo->peek != NULL) { address -= slotInfo->startpage << 13; return slotInfo->peek(slotInfo->ref, address); } return 0xff; } UInt8 slotRead(void* ref, UInt16 address) { Slot* slotInfo; int psl; int ssl; if (!initialized) { return 0xff; } if (address == 0xffff) { UInt8 sslReg = pslot[3].state; if (pslot[sslReg].subslotted) { return ~pslot[sslReg].sslReg; } } if (ramslot[address >> 13].readEnable) { return ramslot[address >> 13].pageData[address & 0x1fff]; } psl = pslot[address >> 14].state; ssl = pslot[psl].subslotted ? pslot[address >> 14].substate : 0; slotInfo = &slotTable[psl][ssl][address >> 13]; if (slotInfo->read != NULL) { address -= slotInfo->startpage << 13; return slotInfo->read(slotInfo->ref, address); } return 0xff; } void slotWrite(void* ref, UInt16 address, UInt8 value) { Slot* slotInfo; int psl; int ssl; int page; if (!initialized) { return; } if (address == 0xffff) { UInt8 pslReg = pslot[3].state; if (pslot[pslReg].subslotted) { // printf("SW: %d %d %d %d\n", (value>>0)&3, (value>>2)&3, (value>>4)&3, (value>>6)&3); pslot[pslReg].sslReg = value; for (page = 0; page < 4; page++) { if(pslot[page].state == pslReg) { pslot[page].substate = value & 3; slotMapRamPage(pslReg, value & 3, 2 * page); slotMapRamPage(pslReg, value & 3, 2 * page + 1); } value >>= 2; } return; } } if (address == 0) { if (slotAddr0.write != NULL) { slotAddr0.write(slotAddr0.ref, address, value); return; } } if (ramslot[address >> 13].writeEnable) { ramslot[address >> 13].pageData[address & 0x1FFF] = value; return; } psl = pslot[address >> 14].state; ssl = pslot[psl].subslotted ? pslot[address >> 14].substate : 0; slotInfo = &slotTable[psl][ssl][address >> 13]; if (slotInfo->write != NULL) { address -= slotInfo->startpage << 13; slotInfo->write(slotInfo->ref, address, value); } } void slotSaveState() { SaveState* state; char tag[32]; int i; if (!initialized) { return; } state = saveStateOpenForWrite("slotManager"); for (i = 0; i < 4; i++) { sprintf(tag, "subslotted%d", i); saveStateSet(state, tag, pslot[i].subslotted); sprintf(tag, "state%d", i); saveStateSet(state, tag, pslot[i].state); sprintf(tag, "substate%d", i); saveStateSet(state, tag, pslot[i].substate); sprintf(tag, "sslReg%d", i); saveStateSet(state, tag, pslot[i].sslReg); } saveStateClose(state); } void slotLoadState() { SaveState* state; char tag[32]; int page; int i; if (!initialized) { return; } state = saveStateOpenForRead("slotManager"); for (i = 0; i < 4; i++) { sprintf(tag, "subslotted%d", i); pslot[i].subslotted = saveStateGet(state, tag, 0); sprintf(tag, "state%d", i); pslot[i].state = (UInt8)saveStateGet(state, tag, 0); sprintf(tag, "substate%d", i); pslot[i].substate = (UInt8)saveStateGet(state, tag, 0); sprintf(tag, "sslReg%d", i); pslot[i].sslReg = (UInt8)saveStateGet(state, tag, 0); } saveStateClose(state); for (page = 0; page < 4; page++) { int psl = pslot[page].state; int ssl = pslot[psl].subslotted ? pslot[page].substate : 0; slotMapRamPage(psl, ssl, 2 * page); slotMapRamPage(psl, ssl, 2 * page + 1); } }