From 83cf32e9a9d34ece87423997c2355ff9abba6f4e Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 12:53:39 -0400 Subject: [PATCH 01/12] Add files via upload --- libgambatte/include/gambatte.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index 43e56d5fb9..2265ffa6d9 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -60,7 +60,8 @@ public: * @param flags ORed combination of LoadFlags. * @return 0 on success, negative value on failure. */ - int load(const char *romfiledata, unsigned romfilelength, std::uint32_t now, unsigned flags = 0); + bool use_bios; + int load(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, std::uint32_t now, unsigned flags = 0); /** Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer, * or until a video frame has been drawn. From 6e5eaba1556aebace876728b75c2088a2169806c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 12:55:10 -0400 Subject: [PATCH 02/12] Add files via upload --- libgambatte/src/mem/cartridge.cpp | 1430 +++++++++++++++-------------- libgambatte/src/mem/cartridge.h | 7 +- libgambatte/src/mem/memptrs.cpp | 308 ++++--- libgambatte/src/mem/memptrs.h | 185 ++-- 4 files changed, 990 insertions(+), 940 deletions(-) diff --git a/libgambatte/src/mem/cartridge.cpp b/libgambatte/src/mem/cartridge.cpp index b8b642f4c4..7539be22bf 100644 --- a/libgambatte/src/mem/cartridge.cpp +++ b/libgambatte/src/mem/cartridge.cpp @@ -1,152 +1,152 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * 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 version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "cartridge.h" -#include "../savestate.h" -#include -#include -#include - -namespace gambatte { - -namespace { - -static unsigned toMulti64Rombank(const unsigned rombank) { - return (rombank >> 1 & 0x30) | (rombank & 0xF); -} - -class DefaultMbc : public Mbc { -public: - virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const { - return (addr< 0x4000) == (bank == 0); - } +/*************************************************************************** + * Copyright (C) 2007-2010 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "cartridge.h" +#include "../savestate.h" +#include +#include +#include + +namespace gambatte { + +namespace { + +static unsigned toMulti64Rombank(const unsigned rombank) { + return (rombank >> 1 & 0x30) | (rombank & 0xF); +} + +class DefaultMbc : public Mbc { +public: + virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const { + return (addr< 0x4000) == (bank == 0); + } virtual void SyncState(NewState *ns, bool isReader) { - } -}; - -class Mbc0 : public DefaultMbc { - MemPtrs &memptrs; - bool enableRam; - -public: - explicit Mbc0(MemPtrs &memptrs) - : memptrs(memptrs), - enableRam(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - if (P < 0x2000) { - enableRam = (data & 0xF) == 0xA; - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.enableRam = enableRam; - } - - virtual void loadState(const SaveState::Mem &ss) { - enableRam = ss.enableRam; - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); - } - + } +}; + +class Mbc0 : public DefaultMbc { + MemPtrs &memptrs; + bool enableRam; + +public: + explicit Mbc0(MemPtrs &memptrs) + : memptrs(memptrs), + enableRam(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + if (P < 0x2000) { + enableRam = (data & 0xF) == 0xA; + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.enableRam = enableRam; + } + + virtual void loadState(const SaveState::Mem &ss) { + enableRam = ss.enableRam; + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); + } + virtual void SyncState(NewState *ns, bool isReader) { NSS(enableRam); } -}; - -static inline unsigned rambanks(const MemPtrs &memptrs) { - return static_cast(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000; -} - -static inline unsigned rombanks(const MemPtrs &memptrs) { - return static_cast(memptrs.romdataend() - memptrs.romdata() ) / 0x4000; -} - -class Mbc1 : public DefaultMbc { - MemPtrs &memptrs; - unsigned char rombank; - unsigned char rambank; - bool enableRam; - bool rambankMode; - - static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; } - void setRambank() const { memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, rambank & (rambanks(memptrs) - 1)); } - void setRombank() const { memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); } - -public: - explicit Mbc1(MemPtrs &memptrs) - : memptrs(memptrs), - rombank(1), - rambank(0), - enableRam(false), - rambankMode(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - switch (P >> 13 & 3) { - case 0: - enableRam = (data & 0xF) == 0xA; - setRambank(); - break; - case 1: - rombank = rambankMode ? data & 0x1F : (rombank & 0x60) | (data & 0x1F); - setRombank(); - break; - case 2: - if (rambankMode) { - rambank = data & 3; - setRambank(); - } else { - rombank = (data << 5 & 0x60) | (rombank & 0x1F); - setRombank(); - } - - break; - case 3: - // Pretty sure this should take effect immediately, but I have a policy not to change old behavior - // unless I have something (eg. a verified test or a game) that justifies it. - rambankMode = data & 1; - break; - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.rombank = rombank; - ss.rambank = rambank; - ss.enableRam = enableRam; - ss.rambankMode = rambankMode; - } - - virtual void loadState(const SaveState::Mem &ss) { - rombank = ss.rombank; - rambank = ss.rambank; - enableRam = ss.enableRam; - rambankMode = ss.rambankMode; - setRambank(); - setRombank(); - } - +}; + +static inline unsigned rambanks(const MemPtrs &memptrs) { + return static_cast(memptrs.rambankdataend() - memptrs.rambankdata()) / 0x2000; +} + +static inline unsigned rombanks(const MemPtrs &memptrs) { + return static_cast(memptrs.romdataend() - memptrs.romdata() ) / 0x4000; +} + +class Mbc1 : public DefaultMbc { + MemPtrs &memptrs; + unsigned char rombank; + unsigned char rambank; + bool enableRam; + bool rambankMode; + + static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; } + void setRambank() const { memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, rambank & (rambanks(memptrs) - 1)); } + void setRombank() const { memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); } + +public: + explicit Mbc1(MemPtrs &memptrs) + : memptrs(memptrs), + rombank(1), + rambank(0), + enableRam(false), + rambankMode(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + switch (P >> 13 & 3) { + case 0: + enableRam = (data & 0xF) == 0xA; + setRambank(); + break; + case 1: + rombank = rambankMode ? data & 0x1F : (rombank & 0x60) | (data & 0x1F); + setRombank(); + break; + case 2: + if (rambankMode) { + rambank = data & 3; + setRambank(); + } else { + rombank = (data << 5 & 0x60) | (rombank & 0x1F); + setRombank(); + } + + break; + case 3: + // Pretty sure this should take effect immediately, but I have a policy not to change old behavior + // unless I have something (eg. a verified test or a game) that justifies it. + rambankMode = data & 1; + break; + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.rombank = rombank; + ss.rambank = rambank; + ss.enableRam = enableRam; + ss.rambankMode = rambankMode; + } + + virtual void loadState(const SaveState::Mem &ss) { + rombank = ss.rombank; + rambank = ss.rambank; + enableRam = ss.enableRam; + rambankMode = ss.rambankMode; + setRambank(); + setRombank(); + } + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); @@ -154,267 +154,267 @@ public: NSS(enableRam); NSS(rambankMode); } -}; - -class Mbc1Multi64 : public Mbc { - MemPtrs &memptrs; - unsigned char rombank; - bool enableRam; - bool rombank0Mode; - - static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; } - - void setRombank() const { - if (rombank0Mode) { - const unsigned rb = toMulti64Rombank(rombank); - memptrs.setRombank0(rb & 0x30); - memptrs.setRombank(adjustedRombank(rb)); - } else { - memptrs.setRombank0(0); - memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); - } - } - -public: - explicit Mbc1Multi64(MemPtrs &memptrs) - : memptrs(memptrs), - rombank(1), - enableRam(false), - rombank0Mode(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - switch (P >> 13 & 3) { - case 0: - enableRam = (data & 0xF) == 0xA; - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); - break; - case 1: - rombank = (rombank & 0x60) | (data & 0x1F); - memptrs.setRombank(adjustedRombank(rombank0Mode ? toMulti64Rombank(rombank) : rombank & (rombanks(memptrs) - 1))); - break; - case 2: - rombank = (data << 5 & 0x60) | (rombank & 0x1F); - setRombank(); - break; - case 3: - rombank0Mode = data & 1; - setRombank(); - break; - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.rombank = rombank; - ss.enableRam = enableRam; - ss.rambankMode = rombank0Mode; - } - - virtual void loadState(const SaveState::Mem &ss) { - rombank = ss.rombank; - enableRam = ss.enableRam; - rombank0Mode = ss.rambankMode; - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); - setRombank(); - } - - virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const { - return (addr < 0x4000) == ((bank & 0xF) == 0); - } - +}; + +class Mbc1Multi64 : public Mbc { + MemPtrs &memptrs; + unsigned char rombank; + bool enableRam; + bool rombank0Mode; + + static unsigned adjustedRombank(unsigned bank) { return bank & 0x1F ? bank : bank | 1; } + + void setRombank() const { + if (rombank0Mode) { + const unsigned rb = toMulti64Rombank(rombank); + memptrs.setRombank0(rb & 0x30); + memptrs.setRombank(adjustedRombank(rb)); + } else { + memptrs.setRombank0(0); + memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); + } + } + +public: + explicit Mbc1Multi64(MemPtrs &memptrs) + : memptrs(memptrs), + rombank(1), + enableRam(false), + rombank0Mode(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + switch (P >> 13 & 3) { + case 0: + enableRam = (data & 0xF) == 0xA; + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); + break; + case 1: + rombank = (rombank & 0x60) | (data & 0x1F); + memptrs.setRombank(adjustedRombank(rombank0Mode ? toMulti64Rombank(rombank) : rombank & (rombanks(memptrs) - 1))); + break; + case 2: + rombank = (data << 5 & 0x60) | (rombank & 0x1F); + setRombank(); + break; + case 3: + rombank0Mode = data & 1; + setRombank(); + break; + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.rombank = rombank; + ss.enableRam = enableRam; + ss.rambankMode = rombank0Mode; + } + + virtual void loadState(const SaveState::Mem &ss) { + rombank = ss.rombank; + enableRam = ss.enableRam; + rombank0Mode = ss.rambankMode; + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); + setRombank(); + } + + virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned addr, unsigned bank) const { + return (addr < 0x4000) == ((bank & 0xF) == 0); + } + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(enableRam); NSS(rombank0Mode); } -}; - -class Mbc2 : public DefaultMbc { - MemPtrs &memptrs; - unsigned char rombank; - bool enableRam; - -public: - explicit Mbc2(MemPtrs &memptrs) - : memptrs(memptrs), - rombank(1), - enableRam(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - switch (P & 0x6100) { - case 0x0000: - enableRam = (data & 0xF) == 0xA; - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); - break; - case 0x2100: - rombank = data & 0xF; - memptrs.setRombank(rombank & (rombanks(memptrs) - 1)); - break; - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.rombank = rombank; - ss.enableRam = enableRam; - } - - virtual void loadState(const SaveState::Mem &ss) { - rombank = ss.rombank; - enableRam = ss.enableRam; - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); - memptrs.setRombank(rombank & (rombanks(memptrs) - 1)); - } - +}; + +class Mbc2 : public DefaultMbc { + MemPtrs &memptrs; + unsigned char rombank; + bool enableRam; + +public: + explicit Mbc2(MemPtrs &memptrs) + : memptrs(memptrs), + rombank(1), + enableRam(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + switch (P & 0x6100) { + case 0x0000: + enableRam = (data & 0xF) == 0xA; + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); + break; + case 0x2100: + rombank = data & 0xF; + memptrs.setRombank(rombank & (rombanks(memptrs) - 1)); + break; + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.rombank = rombank; + ss.enableRam = enableRam; + } + + virtual void loadState(const SaveState::Mem &ss) { + rombank = ss.rombank; + enableRam = ss.enableRam; + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, 0); + memptrs.setRombank(rombank & (rombanks(memptrs) - 1)); + } + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(enableRam); } -}; - -class Mbc3 : public DefaultMbc { - MemPtrs &memptrs; - Rtc *const rtc; - unsigned char rombank; - unsigned char rambank; - bool enableRam; - - static unsigned adjustedRombank(unsigned bank) { return bank & 0x7F ? bank : bank | 1; } - void setRambank() const { - unsigned flags = enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0; - - if (rtc) { - rtc->set(enableRam, rambank); - - if (rtc->getActive()) - flags |= MemPtrs::RTC_EN; - } - - memptrs.setRambank(flags, rambank & (rambanks(memptrs) - 1)); - } - // we adjust the rombank before masking with size? this seems correct, as how would the mbc - // know that high rom address outputs were not connected - void setRombank() const { memptrs.setRombank(adjustedRombank(rombank) & (rombanks(memptrs) - 1)); } - -public: - Mbc3(MemPtrs &memptrs, Rtc *const rtc) - : memptrs(memptrs), - rtc(rtc), - rombank(1), - rambank(0), - enableRam(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - switch (P >> 13 & 3) { - case 0: - enableRam = (data & 0xF) == 0xA; - setRambank(); - break; - case 1: - rombank = data & 0x7F; - setRombank(); - break; - case 2: - rambank = data; - setRambank(); - break; - case 3: - if (rtc) - rtc->latch(data); - - break; - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.rombank = rombank; - ss.rambank = rambank; - ss.enableRam = enableRam; - } - - virtual void loadState(const SaveState::Mem &ss) { - rombank = ss.rombank; - rambank = ss.rambank; - enableRam = ss.enableRam; - setRambank(); - setRombank(); - } - +}; + +class Mbc3 : public DefaultMbc { + MemPtrs &memptrs; + Rtc *const rtc; + unsigned char rombank; + unsigned char rambank; + bool enableRam; + + static unsigned adjustedRombank(unsigned bank) { return bank & 0x7F ? bank : bank | 1; } + void setRambank() const { + unsigned flags = enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0; + + if (rtc) { + rtc->set(enableRam, rambank); + + if (rtc->getActive()) + flags |= MemPtrs::RTC_EN; + } + + memptrs.setRambank(flags, rambank & (rambanks(memptrs) - 1)); + } + // we adjust the rombank before masking with size? this seems correct, as how would the mbc + // know that high rom address outputs were not connected + void setRombank() const { memptrs.setRombank(adjustedRombank(rombank) & (rombanks(memptrs) - 1)); } + +public: + Mbc3(MemPtrs &memptrs, Rtc *const rtc) + : memptrs(memptrs), + rtc(rtc), + rombank(1), + rambank(0), + enableRam(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + switch (P >> 13 & 3) { + case 0: + enableRam = (data & 0xF) == 0xA; + setRambank(); + break; + case 1: + rombank = data & 0x7F; + setRombank(); + break; + case 2: + rambank = data; + setRambank(); + break; + case 3: + if (rtc) + rtc->latch(data); + + break; + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.rombank = rombank; + ss.rambank = rambank; + ss.enableRam = enableRam; + } + + virtual void loadState(const SaveState::Mem &ss) { + rombank = ss.rombank; + rambank = ss.rambank; + enableRam = ss.enableRam; + setRambank(); + setRombank(); + } + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(rambank); NSS(enableRam); } -}; - -class HuC1 : public DefaultMbc { - MemPtrs &memptrs; - unsigned char rombank; - unsigned char rambank; - bool enableRam; - bool rambankMode; - - void setRambank() const { - memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : MemPtrs::READ_EN, - rambankMode ? rambank & (rambanks(memptrs) - 1) : 0); - } - - void setRombank() const { memptrs.setRombank((rambankMode ? rombank : rambank << 6 | rombank) & (rombanks(memptrs) - 1)); } - -public: - explicit HuC1(MemPtrs &memptrs) - : memptrs(memptrs), - rombank(1), - rambank(0), - enableRam(false), - rambankMode(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - switch (P >> 13 & 3) { - case 0: - enableRam = (data & 0xF) == 0xA; - setRambank(); - break; - case 1: - rombank = data & 0x3F; - setRombank(); - break; - case 2: - rambank = data & 3; - rambankMode ? setRambank() : setRombank(); - break; - case 3: - rambankMode = data & 1; - setRambank(); - setRombank(); - break; - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.rombank = rombank; - ss.rambank = rambank; - ss.enableRam = enableRam; - ss.rambankMode = rambankMode; - } - - virtual void loadState(const SaveState::Mem &ss) { - rombank = ss.rombank; - rambank = ss.rambank; - enableRam = ss.enableRam; - rambankMode = ss.rambankMode; - setRambank(); - setRombank(); - } +}; + +class HuC1 : public DefaultMbc { + MemPtrs &memptrs; + unsigned char rombank; + unsigned char rambank; + bool enableRam; + bool rambankMode; + + void setRambank() const { + memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : MemPtrs::READ_EN, + rambankMode ? rambank & (rambanks(memptrs) - 1) : 0); + } + + void setRombank() const { memptrs.setRombank((rambankMode ? rombank : rambank << 6 | rombank) & (rombanks(memptrs) - 1)); } + +public: + explicit HuC1(MemPtrs &memptrs) + : memptrs(memptrs), + rombank(1), + rambank(0), + enableRam(false), + rambankMode(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + switch (P >> 13 & 3) { + case 0: + enableRam = (data & 0xF) == 0xA; + setRambank(); + break; + case 1: + rombank = data & 0x3F; + setRombank(); + break; + case 2: + rambank = data & 3; + rambankMode ? setRambank() : setRombank(); + break; + case 3: + rambankMode = data & 1; + setRambank(); + setRombank(); + break; + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.rombank = rombank; + ss.rambank = rambank; + ss.enableRam = enableRam; + ss.rambankMode = rambankMode; + } + + virtual void loadState(const SaveState::Mem &ss) { + rombank = ss.rombank; + rambank = ss.rambank; + enableRam = ss.enableRam; + rambankMode = ss.rambankMode; + setRambank(); + setRombank(); + } virtual void SyncState(NewState *ns, bool isReader) { @@ -423,327 +423,361 @@ public: NSS(enableRam); NSS(rambankMode); } -}; - -class Mbc5 : public DefaultMbc { - MemPtrs &memptrs; - unsigned short rombank; - unsigned char rambank; - bool enableRam; - - static unsigned adjustedRombank(const unsigned bank) { return bank; } - void setRambank() const { memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, rambank & (rambanks(memptrs) - 1)); } - void setRombank() const { memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); } - -public: - explicit Mbc5(MemPtrs &memptrs) - : memptrs(memptrs), - rombank(1), - rambank(0), - enableRam(false) - { - } - - virtual void romWrite(const unsigned P, const unsigned data) { - switch (P >> 13 & 3) { - case 0: - enableRam = (data & 0xF) == 0xA; - setRambank(); - break; - case 1: - rombank = P < 0x3000 ? (rombank & 0x100) | data - : (data << 8 & 0x100) | (rombank & 0xFF); - setRombank(); - break; - case 2: - rambank = data & 0xF; - setRambank(); - break; - case 3: - break; - } - } - - virtual void saveState(SaveState::Mem &ss) const { - ss.rombank = rombank; - ss.rambank = rambank; - ss.enableRam = enableRam; - } - - virtual void loadState(const SaveState::Mem &ss) { - rombank = ss.rombank; - rambank = ss.rambank; - enableRam = ss.enableRam; - setRambank(); - setRombank(); - } - +}; + +class Mbc5 : public DefaultMbc { + MemPtrs &memptrs; + unsigned short rombank; + unsigned char rambank; + bool enableRam; + + static unsigned adjustedRombank(const unsigned bank) { return bank; } + void setRambank() const { memptrs.setRambank(enableRam ? MemPtrs::READ_EN | MemPtrs::WRITE_EN : 0, rambank & (rambanks(memptrs) - 1)); } + void setRombank() const { memptrs.setRombank(adjustedRombank(rombank & (rombanks(memptrs) - 1))); } + +public: + explicit Mbc5(MemPtrs &memptrs) + : memptrs(memptrs), + rombank(1), + rambank(0), + enableRam(false) + { + } + + virtual void romWrite(const unsigned P, const unsigned data) { + switch (P >> 13 & 3) { + case 0: + enableRam = (data & 0xF) == 0xA; + setRambank(); + break; + case 1: + rombank = P < 0x3000 ? (rombank & 0x100) | data + : (data << 8 & 0x100) | (rombank & 0xFF); + setRombank(); + break; + case 2: + rambank = data & 0xF; + setRambank(); + break; + case 3: + break; + } + } + + virtual void saveState(SaveState::Mem &ss) const { + ss.rombank = rombank; + ss.rambank = rambank; + ss.enableRam = enableRam; + } + + virtual void loadState(const SaveState::Mem &ss) { + rombank = ss.rombank; + rambank = ss.rambank; + enableRam = ss.enableRam; + setRambank(); + setRombank(); + } + virtual void SyncState(NewState *ns, bool isReader) { NSS(rombank); NSS(rambank); NSS(enableRam); } -}; - -static bool hasRtc(const unsigned headerByte0x147) { - switch (headerByte0x147) { - case 0x0F: - case 0x10: return true; - default: return false; - } -} - -} - -void Cartridge::setStatePtrs(SaveState &state) { - state.mem.vram.set(memptrs.vramdata(), memptrs.vramdataend() - memptrs.vramdata()); - state.mem.sram.set(memptrs.rambankdata(), memptrs.rambankdataend() - memptrs.rambankdata()); - state.mem.wram.set(memptrs.wramdata(0), memptrs.wramdataend() - memptrs.wramdata(0)); -} - -void Cartridge::loadState(const SaveState &state) { - rtc.loadState(state); - mbc->loadState(state.mem); -} - -static void enforce8bit(unsigned char *data, unsigned long sz) { - if (static_cast(0x100)) - while (sz--) - *data++ &= 0xFF; -} - -static unsigned pow2ceil(unsigned n) { - --n; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - ++n; - - return n; -} - -int Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, const bool forceDmg, const bool multicartCompat) { - //const std::auto_ptr rom(newFileInstance(romfile)); - - //if (rom->fail()) - // return -1; - - unsigned rambanks = 1; - unsigned rombanks = 2; - bool cgb = false; - enum Cartridgetype { PLAIN, MBC1, MBC2, MBC3, MBC5, HUC1 } type = PLAIN; - - { - unsigned char header[0x150]; - //rom->read(reinterpret_cast(header), sizeof header); - if (romfilelength >= sizeof header) - std::memcpy(header, romfiledata, sizeof header); - else - return -1; - - switch (header[0x0147]) { - case 0x00: std::puts("Plain ROM loaded."); type = PLAIN; break; - case 0x01: std::puts("MBC1 ROM loaded."); type = MBC1; break; - case 0x02: std::puts("MBC1 ROM+RAM loaded."); type = MBC1; break; - case 0x03: std::puts("MBC1 ROM+RAM+BATTERY loaded."); type = MBC1; break; - case 0x05: std::puts("MBC2 ROM loaded."); type = MBC2; break; - case 0x06: std::puts("MBC2 ROM+BATTERY loaded."); type = MBC2; break; - case 0x08: std::puts("Plain ROM with additional RAM loaded."); type = PLAIN; break; - case 0x09: std::puts("Plain ROM with additional RAM and Battery loaded."); type = PLAIN; break; - case 0x0B: std::puts("MM01 ROM not supported."); return -1; - case 0x0C: std::puts("MM01 ROM not supported."); return -1; - case 0x0D: std::puts("MM01 ROM not supported."); return -1; - case 0x0F: std::puts("MBC3 ROM+TIMER+BATTERY loaded."); type = MBC3; break; - case 0x10: std::puts("MBC3 ROM+TIMER+RAM+BATTERY loaded."); type = MBC3; break; - case 0x11: std::puts("MBC3 ROM loaded."); type = MBC3; break; - case 0x12: std::puts("MBC3 ROM+RAM loaded."); type = MBC3; break; - case 0x13: std::puts("MBC3 ROM+RAM+BATTERY loaded."); type = MBC3; break; - case 0x15: std::puts("MBC4 ROM not supported."); return -1; - case 0x16: std::puts("MBC4 ROM not supported."); return -1; - case 0x17: std::puts("MBC4 ROM not supported."); return -1; - case 0x19: std::puts("MBC5 ROM loaded."); type = MBC5; break; - case 0x1A: std::puts("MBC5 ROM+RAM loaded."); type = MBC5; break; - case 0x1B: std::puts("MBC5 ROM+RAM+BATTERY loaded."); type = MBC5; break; - case 0x1C: std::puts("MBC5+RUMBLE ROM not supported."); type = MBC5; break; - case 0x1D: std::puts("MBC5+RUMBLE+RAM ROM not suported."); type = MBC5; break; - case 0x1E: std::puts("MBC5+RUMBLE+RAM+BATTERY ROM not supported."); type = MBC5; break; - case 0xFC: std::puts("Pocket Camera ROM not supported."); return -1; - case 0xFD: std::puts("Bandai TAMA5 ROM not supported."); return -1; - case 0xFE: std::puts("HuC3 ROM not supported."); return -1; - case 0xFF: std::puts("HuC1 ROM+RAM+BATTERY loaded."); type = HUC1; break; - default: std::puts("Wrong data-format, corrupt or unsupported ROM."); return -1; - } - - /*switch (header[0x0148]) { - case 0x00: rombanks = 2; break; - case 0x01: rombanks = 4; break; - case 0x02: rombanks = 8; break; - case 0x03: rombanks = 16; break; - case 0x04: rombanks = 32; break; - case 0x05: rombanks = 64; break; - case 0x06: rombanks = 128; break; - case 0x07: rombanks = 256; break; - case 0x08: rombanks = 512; break; - case 0x52: rombanks = 72; break; - case 0x53: rombanks = 80; break; - case 0x54: rombanks = 96; break; - default: return -1; - } - - std::printf("rombanks: %u\n", rombanks);*/ - - switch (header[0x0149]) { - case 0x00: /*std::puts("No RAM");*/ rambanks = type == MBC2; break; - case 0x01: /*std::puts("2kB RAM");*/ /*rambankrom=1; break;*/ - case 0x02: /*std::puts("8kB RAM");*/ - rambanks = 1; - break; - case 0x03: /*std::puts("32kB RAM");*/ - rambanks = 4; - break; - case 0x04: /*std::puts("128kB RAM");*/ - rambanks = 16; - break; - case 0x05: /*std::puts("undocumented kB RAM");*/ - rambanks = 16; - break; - default: /*std::puts("Wrong data-format, corrupt or unsupported ROM loaded.");*/ - rambanks = 16; - break; - } - - cgb = header[0x0143] >> 7 & (1 ^ forceDmg); - std::printf("cgb: %d\n", cgb); - } - - std::printf("rambanks: %u\n", rambanks); - - const std::size_t filesize = romfilelength; //rom->size(); - rombanks = std::max(pow2ceil(filesize / 0x4000), 2u); - std::printf("rombanks: %u\n", static_cast(filesize / 0x4000)); - - mbc.reset(); - memptrs.reset(rombanks, rambanks, cgb ? 8 : 2); - rtc.set(false, 0); - - //rom->rewind(); - //rom->read(reinterpret_cast(memptrs.romdata()), (filesize / 0x4000) * 0x4000ul); - std::memcpy(memptrs.romdata(), romfiledata, (filesize / 0x4000) * 0x4000ul); - std::memset(memptrs.romdata() + (filesize / 0x4000) * 0x4000ul, 0xFF, (rombanks - filesize / 0x4000) * 0x4000ul); - enforce8bit(memptrs.romdata(), rombanks * 0x4000ul); - - //if (rom->fail()) - // return -1; - - switch (type) { - case PLAIN: mbc.reset(new Mbc0(memptrs)); break; - case MBC1: - if (!rambanks && rombanks == 64 && multicartCompat) { - std::puts("Multi-ROM \"MBC1\" presumed"); - mbc.reset(new Mbc1Multi64(memptrs)); - } else - mbc.reset(new Mbc1(memptrs)); - - break; - case MBC2: mbc.reset(new Mbc2(memptrs)); break; - case MBC3: mbc.reset(new Mbc3(memptrs, hasRtc(memptrs.romdata()[0x147]) ? &rtc : 0)); break; - case MBC5: mbc.reset(new Mbc5(memptrs)); break; - case HUC1: mbc.reset(new HuC1(memptrs)); break; - } - - return 0; -} - -static bool hasBattery(const unsigned char headerByte0x147) { - switch (headerByte0x147) { - case 0x03: - case 0x06: - case 0x09: - case 0x0F: - case 0x10: - case 0x13: - case 0x1B: - case 0x1E: - case 0xFF: return true; - default: return false; - } -} - -void Cartridge::loadSavedata(const char *data) { - if (hasBattery(memptrs.romdata()[0x147])) { - int length = memptrs.rambankdataend() - memptrs.rambankdata(); - std::memcpy(memptrs.rambankdata(), data, length); - data += length; - enforce8bit(memptrs.rambankdata(), length); - } - - if (hasRtc(memptrs.romdata()[0x147])) { - unsigned long basetime; - std::memcpy(&basetime, data, 4); - rtc.setBaseTime(basetime); - } -} - -int Cartridge::saveSavedataLength() { - int ret = 0; - if (hasBattery(memptrs.romdata()[0x147])) { - ret = memptrs.rambankdataend() - memptrs.rambankdata(); - } - if (hasRtc(memptrs.romdata()[0x147])) { - ret += 4; - } - return ret; -} - -void Cartridge::saveSavedata(char *dest) { - if (hasBattery(memptrs.romdata()[0x147])) { - int length = memptrs.rambankdataend() - memptrs.rambankdata(); - std::memcpy(dest, memptrs.rambankdata(), length); - dest += length; - } - - if (hasRtc(memptrs.romdata()[0x147])) { - const unsigned long basetime = rtc.getBaseTime(); - std::memcpy(dest, &basetime, 4); - } -} - -bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) const { - if (!data || !length) - return false; - - switch (which) - { - case 0: - *data = memptrs.vramdata(); - *length = memptrs.vramdataend() - memptrs.vramdata(); - return true; - case 1: - *data = memptrs.romdata(); - *length = memptrs.romdataend() - memptrs.romdata(); - return true; - case 2: - *data = memptrs.wramdata(0); - *length = memptrs.wramdataend() - memptrs.wramdata(0); - return true; - case 3: - *data = memptrs.rambankdata(); - *length = memptrs.rambankdataend() - memptrs.rambankdata(); - return true; - - default: - return false; - } - return false; -} - +}; + +static bool hasRtc(const unsigned headerByte0x147) { + switch (headerByte0x147) { + case 0x0F: + case 0x10: return true; + default: return false; + } +} + +} + +void Cartridge::setStatePtrs(SaveState &state) { + state.mem.vram.set(memptrs.vramdata(), memptrs.vramdataend() - memptrs.vramdata()); + state.mem.sram.set(memptrs.rambankdata(), memptrs.rambankdataend() - memptrs.rambankdata()); + state.mem.wram.set(memptrs.wramdata(0), memptrs.wramdataend() - memptrs.wramdata(0)); +} + +void Cartridge::loadState(const SaveState &state) { + rtc.loadState(state); + mbc->loadState(state.mem); +} + +static void enforce8bit(unsigned char *data, unsigned long sz) { + if (static_cast(0x100)) + while (sz--) + *data++ &= 0xFF; +} + +static unsigned pow2ceil(unsigned n) { + --n; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + ++n; + + return n; +} + +void Cartridge::bios_remap(int setting) { + // disable the BIOS if writing 1 or 0x22 (GBC) + if (setting == 1 || setting == 0x11) { + std::memcpy(memptrs.romdata(), memptrs.notbiosdata_, loc_bios_length); + } + + // we'll also use it to reset to BIOS on reset + if (setting == 0) { + std::memcpy(memptrs.romdata(), memptrs.biosdata_, loc_bios_length); + } +} + +int Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, const bool forceDmg, const bool multicartCompat) { + //const std::auto_ptr rom(newFileInstance(romfile)); + + //if (rom->fail()) + // return -1; + + unsigned rambanks = 1; + unsigned rombanks = 2; + bool cgb = false; + enum Cartridgetype { PLAIN, MBC1, MBC2, MBC3, MBC5, HUC1 } type = PLAIN; + + { + unsigned char header[0x150]; + //rom->read(reinterpret_cast(header), sizeof header); + if (romfilelength >= sizeof header) + std::memcpy(header, romfiledata, sizeof header); + else + return -1; + + switch (header[0x0147]) { + case 0x00: std::puts("Plain ROM loaded."); type = PLAIN; break; + case 0x01: std::puts("MBC1 ROM loaded."); type = MBC1; break; + case 0x02: std::puts("MBC1 ROM+RAM loaded."); type = MBC1; break; + case 0x03: std::puts("MBC1 ROM+RAM+BATTERY loaded."); type = MBC1; break; + case 0x05: std::puts("MBC2 ROM loaded."); type = MBC2; break; + case 0x06: std::puts("MBC2 ROM+BATTERY loaded."); type = MBC2; break; + case 0x08: std::puts("Plain ROM with additional RAM loaded."); type = PLAIN; break; + case 0x09: std::puts("Plain ROM with additional RAM and Battery loaded."); type = PLAIN; break; + case 0x0B: std::puts("MM01 ROM not supported."); return -1; + case 0x0C: std::puts("MM01 ROM not supported."); return -1; + case 0x0D: std::puts("MM01 ROM not supported."); return -1; + case 0x0F: std::puts("MBC3 ROM+TIMER+BATTERY loaded."); type = MBC3; break; + case 0x10: std::puts("MBC3 ROM+TIMER+RAM+BATTERY loaded."); type = MBC3; break; + case 0x11: std::puts("MBC3 ROM loaded."); type = MBC3; break; + case 0x12: std::puts("MBC3 ROM+RAM loaded."); type = MBC3; break; + case 0x13: std::puts("MBC3 ROM+RAM+BATTERY loaded."); type = MBC3; break; + case 0x15: std::puts("MBC4 ROM not supported."); return -1; + case 0x16: std::puts("MBC4 ROM not supported."); return -1; + case 0x17: std::puts("MBC4 ROM not supported."); return -1; + case 0x19: std::puts("MBC5 ROM loaded."); type = MBC5; break; + case 0x1A: std::puts("MBC5 ROM+RAM loaded."); type = MBC5; break; + case 0x1B: std::puts("MBC5 ROM+RAM+BATTERY loaded."); type = MBC5; break; + case 0x1C: std::puts("MBC5+RUMBLE ROM not supported."); type = MBC5; break; + case 0x1D: std::puts("MBC5+RUMBLE+RAM ROM not suported."); type = MBC5; break; + case 0x1E: std::puts("MBC5+RUMBLE+RAM+BATTERY ROM not supported."); type = MBC5; break; + case 0xFC: std::puts("Pocket Camera ROM not supported."); return -1; + case 0xFD: std::puts("Bandai TAMA5 ROM not supported."); return -1; + case 0xFE: std::puts("HuC3 ROM not supported."); return -1; + case 0xFF: std::puts("HuC1 ROM+RAM+BATTERY loaded."); type = HUC1; break; + default: std::puts("Wrong data-format, corrupt or unsupported ROM."); return -1; + } + + /*switch (header[0x0148]) { + case 0x00: rombanks = 2; break; + case 0x01: rombanks = 4; break; + case 0x02: rombanks = 8; break; + case 0x03: rombanks = 16; break; + case 0x04: rombanks = 32; break; + case 0x05: rombanks = 64; break; + case 0x06: rombanks = 128; break; + case 0x07: rombanks = 256; break; + case 0x08: rombanks = 512; break; + case 0x52: rombanks = 72; break; + case 0x53: rombanks = 80; break; + case 0x54: rombanks = 96; break; + default: return -1; + } + + std::printf("rombanks: %u\n", rombanks);*/ + + switch (header[0x0149]) { + case 0x00: /*std::puts("No RAM");*/ rambanks = type == MBC2; break; + case 0x01: /*std::puts("2kB RAM");*/ /*rambankrom=1; break;*/ + case 0x02: /*std::puts("8kB RAM");*/ + rambanks = 1; + break; + case 0x03: /*std::puts("32kB RAM");*/ + rambanks = 4; + break; + case 0x04: /*std::puts("128kB RAM");*/ + rambanks = 16; + break; + case 0x05: /*std::puts("undocumented kB RAM");*/ + rambanks = 16; + break; + default: /*std::puts("Wrong data-format, corrupt or unsupported ROM loaded.");*/ + rambanks = 16; + break; + } + + cgb = header[0x0143] >> 7 & (1 ^ forceDmg); + std::printf("cgb: %d\n", cgb); + } + + std::printf("rambanks: %u\n", rambanks); + + const std::size_t filesize = romfilelength; //rom->size(); + rombanks = std::fmax(pow2ceil(filesize / 0x4000), 2u); + std::printf("rombanks: %u\n", static_cast(filesize / 0x4000)); + + mbc.reset(); + + use_bios = biosfilelength > 0 ? true : false; + loc_bios_length = biosfilelength; + + memptrs.reset(rombanks, rambanks, cgb ? 8 : 2); + rtc.set(false, 0); + + //rom->rewind(); + //rom->read(reinterpret_cast(memptrs.romdata()), (filesize / 0x4000) * 0x4000ul); + + std::memcpy(memptrs.romdata(), romfiledata, (filesize / 0x4000) * 0x4000ul); + std::memset(memptrs.romdata() + (filesize / 0x4000) * 0x4000ul, 0xFF, (rombanks - filesize / 0x4000) * 0x4000ul); + enforce8bit(memptrs.romdata(), rombanks * 0x4000ul); + + //we want to copy in the bios data only if it exists + if (use_bios) { + memptrs.biosdata_ = new unsigned char[biosfilelength]; + memptrs.notbiosdata_ = new unsigned char[biosfilelength]; + + std::memcpy(memptrs.biosdata_, biosfiledata, biosfilelength); + std::memcpy(memptrs.notbiosdata_, romfiledata, biosfilelength); + + //if using GBC, the header is not overwritten by the BIOS + if (biosfilelength > 256) { + std::memcpy(memptrs.biosdata_ + 256, memptrs.notbiosdata_ + 256, 256); + } + + + std::memcpy(memptrs.romdata(), memptrs.biosdata_, biosfilelength); + } + + //if (rom->fail()) + // return -1; + + switch (type) { + case PLAIN: mbc.reset(new Mbc0(memptrs)); break; + case MBC1: + if (!rambanks && rombanks == 64 && multicartCompat) { + std::puts("Multi-ROM \"MBC1\" presumed"); + mbc.reset(new Mbc1Multi64(memptrs)); + } else + mbc.reset(new Mbc1(memptrs)); + + break; + case MBC2: mbc.reset(new Mbc2(memptrs)); break; + case MBC3: mbc.reset(new Mbc3(memptrs, hasRtc(memptrs.romdata()[0x147]) ? &rtc : 0)); break; + case MBC5: mbc.reset(new Mbc5(memptrs)); break; + case HUC1: mbc.reset(new HuC1(memptrs)); break; + } + + return 0; +} + +static bool hasBattery(const unsigned char headerByte0x147) { + switch (headerByte0x147) { + case 0x03: + case 0x06: + case 0x09: + case 0x0F: + case 0x10: + case 0x13: + case 0x1B: + case 0x1E: + case 0xFF: return true; + default: return false; + } +} + +void Cartridge::loadSavedata(const char *data) { + if (hasBattery(memptrs.romdata()[0x147])) { + int length = memptrs.rambankdataend() - memptrs.rambankdata(); + std::memcpy(memptrs.rambankdata(), data, length); + data += length; + enforce8bit(memptrs.rambankdata(), length); + } + + if (hasRtc(memptrs.romdata()[0x147])) { + unsigned long basetime; + std::memcpy(&basetime, data, 4); + rtc.setBaseTime(basetime); + } +} + +int Cartridge::saveSavedataLength() { + int ret = 0; + if (hasBattery(memptrs.romdata()[0x147])) { + ret = memptrs.rambankdataend() - memptrs.rambankdata(); + } + if (hasRtc(memptrs.romdata()[0x147])) { + ret += 4; + } + return ret; +} + +void Cartridge::saveSavedata(char *dest) { + if (hasBattery(memptrs.romdata()[0x147])) { + int length = memptrs.rambankdataend() - memptrs.rambankdata(); + std::memcpy(dest, memptrs.rambankdata(), length); + dest += length; + } + + if (hasRtc(memptrs.romdata()[0x147])) { + const unsigned long basetime = rtc.getBaseTime(); + std::memcpy(dest, &basetime, 4); + } +} + +bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) const { + if (!data || !length) + return false; + + switch (which) + { + case 0: + *data = memptrs.vramdata(); + *length = memptrs.vramdataend() - memptrs.vramdata(); + return true; + case 1: + *data = memptrs.romdata(); + *length = memptrs.romdataend() - memptrs.romdata(); + return true; + case 2: + *data = memptrs.wramdata(0); + *length = memptrs.wramdataend() - memptrs.wramdata(0); + return true; + case 3: + *data = memptrs.rambankdata(); + *length = memptrs.rambankdataend() - memptrs.rambankdata(); + return true; + + default: + return false; + } + return false; +} + SYNCFUNC(Cartridge) { SSS(memptrs); SSS(rtc); TSS(mbc); } - -} + +} diff --git a/libgambatte/src/mem/cartridge.h b/libgambatte/src/mem/cartridge.h index 54f694df31..51c73d1ece 100644 --- a/libgambatte/src/mem/cartridge.h +++ b/libgambatte/src/mem/cartridge.h @@ -66,6 +66,9 @@ class Cartridge { public: void setStatePtrs(SaveState &); void loadState(const SaveState &); + + bool use_bios; + unsigned loc_bios_length; bool loaded() const { return mbc.get(); } @@ -97,13 +100,15 @@ public: bool getMemoryArea(int which, unsigned char **data, int *length) const; - int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat); + int loadROM(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, bool forceDmg, bool multicartCompat); const char * romTitle() const { return reinterpret_cast(memptrs.romdata() + 0x134); } void setRTCCallback(std::uint32_t (*callback)()) { rtc.setRTCCallback(callback); } + void bios_remap(int setting); + templatevoid SyncState(NewState *ns); }; diff --git a/libgambatte/src/mem/memptrs.cpp b/libgambatte/src/mem/memptrs.cpp index 6e8b2fe644..425b9b4e61 100644 --- a/libgambatte/src/mem/memptrs.cpp +++ b/libgambatte/src/mem/memptrs.cpp @@ -1,151 +1,159 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * 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 version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "memptrs.h" -#include -#include - -namespace gambatte { - -MemPtrs::MemPtrs() -: rmem_(), wmem_(), romdata_(), wramdata_(), vrambankptr_(0), rsrambankptr_(0), - wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF), - memchunk_len(0) -{ -} - -MemPtrs::~MemPtrs() { - delete []memchunk_; -} - -void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) { - delete []memchunk_; - memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000; - memchunk_ = new unsigned char[memchunk_len]; - - romdata_[0] = romdata(); - rambankdata_ = romdata_[0] + rombanks * 0x4000ul + 0x4000; - wramdata_[0] = rambankdata_ + rambanks * 0x2000ul; - wramdataend_ = wramdata_[0] + wrambanks * 0x1000ul; - - std::memset(rdisabledRamw(), 0xFF, 0x2000); - - oamDmaSrc_ = OAM_DMA_SRC_OFF; - rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; - rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000; - rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000; - setRombank(1); - setRambank(0, 0); - setVrambank(0); - setWrambank(1); - - // we save only the ram areas - memchunk_saveoffs = vramdata() - memchunk_; - memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs; -} - -void MemPtrs::setRombank0(const unsigned bank) { - romdata_[0] = romdata() + bank * 0x4000ul; - rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; - disconnectOamDmaAreas(); -} - -void MemPtrs::setRombank(const unsigned bank) { - romdata_[1] = romdata() + bank * 0x4000ul - 0x4000; - rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1]; - disconnectOamDmaAreas(); -} - -void MemPtrs::setRambank(const unsigned flags, const unsigned rambank) { - unsigned char *const srambankptr = flags & RTC_EN - ? 0 - : (rambankdata() != rambankdataend() - ? rambankdata_ + rambank * 0x2000ul - 0xA000 : wdisabledRam() - 0xA000); - - rsrambankptr_ = (flags & READ_EN) && srambankptr != wdisabledRam() - 0xA000 ? srambankptr : rdisabledRamw() - 0xA000; - wsrambankptr_ = flags & WRITE_EN ? srambankptr : wdisabledRam() - 0xA000; - rmem_[0xB] = rmem_[0xA] = rsrambankptr_; - wmem_[0xB] = wmem_[0xA] = wsrambankptr_; - disconnectOamDmaAreas(); -} - -void MemPtrs::setWrambank(const unsigned bank) { - wramdata_[1] = wramdata_[0] + ((bank & 0x07) ? (bank & 0x07) : 1) * 0x1000; - rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000; - disconnectOamDmaAreas(); -} - -void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) { - rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; - rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1]; - rmem_[0xB] = rmem_[0xA] = rsrambankptr_; - wmem_[0xB] = wmem_[0xA] = wsrambankptr_; - rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000; - rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000; - rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000; - - oamDmaSrc_ = oamDmaSrc; - disconnectOamDmaAreas(); -} - -void MemPtrs::disconnectOamDmaAreas() { - if (isCgb(*this)) { - switch (oamDmaSrc_) { - case OAM_DMA_SRC_ROM: // fall through - case OAM_DMA_SRC_SRAM: - case OAM_DMA_SRC_INVALID: - std::fill(rmem_, rmem_ + 8, static_cast(0)); - rmem_[0xB] = rmem_[0xA] = 0; - wmem_[0xB] = wmem_[0xA] = 0; - break; - case OAM_DMA_SRC_VRAM: - break; - case OAM_DMA_SRC_WRAM: - rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0; - wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0; - break; - case OAM_DMA_SRC_OFF: - break; - } - } else { - switch (oamDmaSrc_) { - case OAM_DMA_SRC_ROM: // fall through - case OAM_DMA_SRC_SRAM: - case OAM_DMA_SRC_WRAM: - case OAM_DMA_SRC_INVALID: - std::fill(rmem_, rmem_ + 8, static_cast(0)); - rmem_[0xB] = rmem_[0xA] = 0; - wmem_[0xB] = wmem_[0xA] = 0; - rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0; - wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0; - break; - case OAM_DMA_SRC_VRAM: - break; - case OAM_DMA_SRC_OFF: - break; - } - } -} - -// all pointers here are relative to memchunk_ -#define MSS(a) RSS(a,memchunk_) -#define MSL(a) RSL(a,memchunk_) - +/*************************************************************************** + * Copyright (C) 2007-2010 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "memptrs.h" +#include +#include + +namespace gambatte { + +MemPtrs::MemPtrs() +: rmem_(), wmem_(), romdata_(), wramdata_(), vrambankptr_(0), rsrambankptr_(0), + wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF), + memchunk_len(0) +{ +} + +MemPtrs::~MemPtrs() { + delete []memchunk_; +} + +void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) { + delete []memchunk_; + delete []biosdata_; + delete []notbiosdata_; + + memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000; + memchunk_ = new unsigned char[memchunk_len]; + + romdata_[0] = romdata(); + + rambankdata_ = romdata_[0] + rombanks * 0x4000ul + 0x4000; + wramdata_[0] = rambankdata_ + rambanks * 0x2000ul; + wramdataend_ = wramdata_[0] + wrambanks * 0x1000ul; + + std::memset(rdisabledRamw(), 0xFF, 0x2000); + + oamDmaSrc_ = OAM_DMA_SRC_OFF; + rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; + rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000; + rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000; + setRombank(1); + setRambank(0, 0); + setVrambank(0); + setWrambank(1); + + // we save only the ram areas + memchunk_saveoffs = vramdata() - memchunk_; + memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs; +} + +void MemPtrs::setRombank0(const unsigned bank) { + + romdata_[0] = romdata() + bank * 0x4000ul; + + rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; + disconnectOamDmaAreas(); +} + +void MemPtrs::setRombank(const unsigned bank) { + + romdata_[1] = romdata() + bank * 0x4000ul - 0x4000; + + rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1]; + disconnectOamDmaAreas(); +} + +void MemPtrs::setRambank(const unsigned flags, const unsigned rambank) { + unsigned char *const srambankptr = flags & RTC_EN + ? 0 + : (rambankdata() != rambankdataend() + ? rambankdata_ + rambank * 0x2000ul - 0xA000 : wdisabledRam() - 0xA000); + + rsrambankptr_ = (flags & READ_EN) && srambankptr != wdisabledRam() - 0xA000 ? srambankptr : rdisabledRamw() - 0xA000; + wsrambankptr_ = flags & WRITE_EN ? srambankptr : wdisabledRam() - 0xA000; + rmem_[0xB] = rmem_[0xA] = rsrambankptr_; + wmem_[0xB] = wmem_[0xA] = wsrambankptr_; + disconnectOamDmaAreas(); +} + +void MemPtrs::setWrambank(const unsigned bank) { + wramdata_[1] = wramdata_[0] + ((bank & 0x07) ? (bank & 0x07) : 1) * 0x1000; + rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000; + disconnectOamDmaAreas(); +} + +void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) { + rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; + rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1]; + rmem_[0xB] = rmem_[0xA] = rsrambankptr_; + wmem_[0xB] = wmem_[0xA] = wsrambankptr_; + rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000; + rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000; + rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000; + + oamDmaSrc_ = oamDmaSrc; + disconnectOamDmaAreas(); +} + +void MemPtrs::disconnectOamDmaAreas() { + if (isCgb(*this)) { + switch (oamDmaSrc_) { + case OAM_DMA_SRC_ROM: // fall through + case OAM_DMA_SRC_SRAM: + case OAM_DMA_SRC_INVALID: + std::fill(rmem_, rmem_ + 8, static_cast(0)); + rmem_[0xB] = rmem_[0xA] = 0; + wmem_[0xB] = wmem_[0xA] = 0; + break; + case OAM_DMA_SRC_VRAM: + break; + case OAM_DMA_SRC_WRAM: + rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0; + wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0; + break; + case OAM_DMA_SRC_OFF: + break; + } + } else { + switch (oamDmaSrc_) { + case OAM_DMA_SRC_ROM: // fall through + case OAM_DMA_SRC_SRAM: + case OAM_DMA_SRC_WRAM: + case OAM_DMA_SRC_INVALID: + std::fill(rmem_, rmem_ + 8, static_cast(0)); + rmem_[0xB] = rmem_[0xA] = 0; + wmem_[0xB] = wmem_[0xA] = 0; + rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0; + wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0; + break; + case OAM_DMA_SRC_VRAM: + break; + case OAM_DMA_SRC_OFF: + break; + } + } +} + +// all pointers here are relative to memchunk_ +#define MSS(a) RSS(a,memchunk_) +#define MSL(a) RSL(a,memchunk_) + SYNCFUNC(MemPtrs) { /* @@ -216,5 +224,5 @@ SYNCFUNC(MemPtrs) MSS(wramdataend_); NSS(oamDmaSrc_); } - -} + +} diff --git a/libgambatte/src/mem/memptrs.h b/libgambatte/src/mem/memptrs.h index af21c02a15..ec63dd4a8b 100644 --- a/libgambatte/src/mem/memptrs.h +++ b/libgambatte/src/mem/memptrs.h @@ -1,93 +1,96 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * 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 version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MEMPTRS_H -#define MEMPTRS_H - +/*************************************************************************** + * Copyright (C) 2007-2010 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MEMPTRS_H +#define MEMPTRS_H + #include "newstate.h" - -namespace gambatte { - -enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM, - OAM_DMA_SRC_WRAM, OAM_DMA_SRC_INVALID, OAM_DMA_SRC_OFF }; - -class MemPtrs { - const unsigned char *rmem_[0x10]; - unsigned char *wmem_[0x10]; - - unsigned char *romdata_[2]; - unsigned char *wramdata_[2]; - unsigned char *vrambankptr_; - unsigned char *rsrambankptr_; - unsigned char *wsrambankptr_; - unsigned char *memchunk_; - unsigned char *rambankdata_; - unsigned char *wramdataend_; - - OamDmaSrc oamDmaSrc_; - - int memchunk_len; - int memchunk_saveoffs; - int memchunk_savelen; - - MemPtrs(const MemPtrs &); - MemPtrs & operator=(const MemPtrs &); - void disconnectOamDmaAreas(); - unsigned char * rdisabledRamw() const { return wramdataend_ ; } - unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; } -public: - enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 }; - - MemPtrs(); - ~MemPtrs(); - void reset(unsigned rombanks, unsigned rambanks, unsigned wrambanks); - - const unsigned char * rmem(unsigned area) const { return rmem_[area]; } - unsigned char * wmem(unsigned area) const { return wmem_[area]; } - unsigned char * vramdata() const { return rambankdata_ - 0x4000; } - unsigned char * vramdataend() const { return rambankdata_; } - unsigned char * romdata() const { return memchunk_ + 0x4000; } - unsigned char * romdata(unsigned area) const { return romdata_[area]; } - unsigned char * romdataend() const { return rambankdata_ - 0x4000; } - unsigned char * wramdata(unsigned area) const { return wramdata_[area]; } - unsigned char * wramdataend() const { return wramdataend_; } - unsigned char * rambankdata() const { return rambankdata_; } - unsigned char * rambankdataend() const { return wramdata_[0]; } - const unsigned char * rdisabledRam() const { return rdisabledRamw(); } - const unsigned char * rsrambankptr() const { return rsrambankptr_; } - unsigned char * wsrambankptr() const { return wsrambankptr_; } - unsigned char * vrambankptr() const { return vrambankptr_; } - OamDmaSrc oamDmaSrc() const { return oamDmaSrc_; } - - void setRombank0(unsigned bank); - void setRombank(unsigned bank); - void setRambank(unsigned ramFlags, unsigned rambank); - void setVrambank(unsigned bank) { vrambankptr_ = vramdata() + bank * 0x2000ul - 0x8000; } - void setWrambank(unsigned bank); - void setOamDmaSrc(OamDmaSrc oamDmaSrc); - + +namespace gambatte { + +enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM, + OAM_DMA_SRC_WRAM, OAM_DMA_SRC_INVALID, OAM_DMA_SRC_OFF }; + +class MemPtrs { + const unsigned char *rmem_[0x10]; + unsigned char *wmem_[0x10]; + + unsigned char *romdata_[2]; + unsigned char *wramdata_[2]; + unsigned char *vrambankptr_; + unsigned char *rsrambankptr_; + unsigned char *wsrambankptr_; + unsigned char *memchunk_; + unsigned char *rambankdata_; + unsigned char *wramdataend_; + + OamDmaSrc oamDmaSrc_; + + int memchunk_len; + int memchunk_saveoffs; + int memchunk_savelen; + + MemPtrs(const MemPtrs &); + MemPtrs & operator=(const MemPtrs &); + void disconnectOamDmaAreas(); + unsigned char * rdisabledRamw() const { return wramdataend_ ; } + unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; } +public: + unsigned char *biosdata_; + unsigned char *notbiosdata_; + + enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 }; + + MemPtrs(); + ~MemPtrs(); + void reset(unsigned rombanks, unsigned rambanks, unsigned wrambanks); + + const unsigned char * rmem(unsigned area) const { return rmem_[area]; } + unsigned char * wmem(unsigned area) const { return wmem_[area]; } + unsigned char * vramdata() const { return rambankdata_ - 0x4000; } + unsigned char * vramdataend() const { return rambankdata_; } + unsigned char * romdata() const { return memchunk_ + 0x4000;} + unsigned char * romdata(unsigned area) const { return romdata_[area]; } + unsigned char * romdataend() const { return rambankdata_ - 0x4000; } + unsigned char * wramdata(unsigned area) const { return wramdata_[area]; } + unsigned char * wramdataend() const { return wramdataend_; } + unsigned char * rambankdata() const { return rambankdata_; } + unsigned char * rambankdataend() const { return wramdata_[0]; } + const unsigned char * rdisabledRam() const { return rdisabledRamw(); } + const unsigned char * rsrambankptr() const { return rsrambankptr_; } + unsigned char * wsrambankptr() const { return wsrambankptr_; } + unsigned char * vrambankptr() const { return vrambankptr_; } + OamDmaSrc oamDmaSrc() const { return oamDmaSrc_; } + + void setRombank0(unsigned bank); + void setRombank(unsigned bank); + void setRambank(unsigned ramFlags, unsigned rambank); + void setVrambank(unsigned bank) { vrambankptr_ = vramdata() + bank * 0x2000ul - 0x8000; } + void setWrambank(unsigned bank); + void setOamDmaSrc(OamDmaSrc oamDmaSrc); + templatevoid SyncState(NewState *ns); -}; - -inline bool isCgb(const MemPtrs &memptrs) { - return memptrs.wramdataend() - memptrs.wramdata(0) == 0x8000; -} - -} - -#endif +}; + +inline bool isCgb(const MemPtrs &memptrs) { + return memptrs.wramdataend() - memptrs.wramdata(0) == 0x8000; +} + +} + +#endif From e65393ec5750b6561394628d93dda49e0f64a417 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 12:56:18 -0400 Subject: [PATCH 03/12] Add files via upload --- libgambatte/src/cinterface.cpp | 4 +- libgambatte/src/cpu.h | 264 ++-- libgambatte/src/gambatte.cpp | 17 +- libgambatte/src/initstate.cpp | 56 +- libgambatte/src/initstate.h | 2 +- libgambatte/src/memory.cpp | 2141 ++++++++++++++++---------------- libgambatte/src/memory.h | 584 ++++----- libgambatte/src/savestate.h | 2 +- 8 files changed, 1557 insertions(+), 1513 deletions(-) diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp index c224fdf725..6549307c85 100644 --- a/libgambatte/src/cinterface.cpp +++ b/libgambatte/src/cinterface.cpp @@ -29,9 +29,9 @@ GBEXPORT void gambatte_destroy(GB *g) delete g; } -GBEXPORT int gambatte_load(GB *g, const char *romfiledata, unsigned romfilelength, long long now, unsigned flags) +GBEXPORT int gambatte_load(GB *g, const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, long long now, unsigned flags) { - int ret = g->load(romfiledata, romfilelength, now, flags); + int ret = g->load(romfiledata, romfilelength, biosfiledata, biosfilelength, now, flags); return ret; } diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index 02fabe979e..1310257e86 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -1,132 +1,136 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * 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 version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CPU_H -#define CPU_H - -#include "memory.h" +/*************************************************************************** + * Copyright (C) 2007 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef CPU_H +#define CPU_H + +#include "memory.h" #include "newstate.h" - -namespace gambatte { - -class CPU { - Memory memory; - - unsigned long cycleCounter_; - - unsigned short PC; - unsigned short SP; - - unsigned HF1, HF2, ZF, CF; - - unsigned char A, B, C, D, E, /*F,*/ H, L; - - bool skip; - - void process(unsigned long cycles); - - void (*tracecallback)(void *); - -public: - - CPU(); -// void halt(); - -// unsigned interrupt(unsigned address, unsigned cycleCounter); - - long runFor(unsigned long cycles); - void setStatePtrs(SaveState &state); - void loadState(const SaveState &state); - void setLayers(unsigned mask) { memory.setLayers(mask); } - - void loadSavedata(const char *data) { memory.loadSavedata(data); } - int saveSavedataLength() {return memory.saveSavedataLength(); } - void saveSavedata(char *dest) { memory.saveSavedata(dest); } - - bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); } - - void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { - memory.setVideoBuffer(videoBuf, pitch); - } - - void setInputGetter(unsigned (*getInput)()) { - memory.setInputGetter(getInput); - } - - void setReadCallback(void (*callback)(unsigned)) { - memory.setReadCallback(callback); - } - - void setWriteCallback(void (*callback)(unsigned)) { - memory.setWriteCallback(callback); - } - - void setExecCallback(void (*callback)(unsigned)) { - memory.setExecCallback(callback); - } - - void setCDCallback(CDCallback cdc) { - memory.setCDCallback(cdc); - } - - void setTraceCallback(void (*callback)(void *)) { - tracecallback = callback; - } - - void setScanlineCallback(void (*callback)(), int sl) { - memory.setScanlineCallback(callback, sl); - } - - void setRTCCallback(std::uint32_t (*callback)()) { - memory.setRTCCallback(callback); - } - - int load(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) { - return memory.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat); - } - - bool loaded() const { return memory.loaded(); } - const char * romTitle() const { return memory.romTitle(); } - - void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); } - unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); } - - bool isCgb() const { return memory.isCgb(); } - - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) { - memory.setDmgPaletteColor(palNum, colorNum, rgb32); - } - - void setCgbPalette(unsigned *lut) { - memory.setCgbPalette(lut); - } - - //unsigned char ExternalRead(unsigned short addr) { return memory.read(addr, cycleCounter_); } - unsigned char ExternalRead(unsigned short addr) { return memory.peek(addr); } - void ExternalWrite(unsigned short addr, unsigned char val) { memory.write_nocb(addr, val, cycleCounter_); } - - int LinkStatus(int which) { return memory.LinkStatus(which); } - - void GetRegs(int *dest); - + +namespace gambatte { + +class CPU { + Memory memory; + + unsigned long cycleCounter_; + + unsigned short PC; + unsigned short SP; + + unsigned HF1, HF2, ZF, CF; + + unsigned char A, B, C, D, E, /*F,*/ H, L; + + bool skip; + + void process(unsigned long cycles); + + void (*tracecallback)(void *); + +public: + + CPU(); +// void halt(); + +// unsigned interrupt(unsigned address, unsigned cycleCounter); + + long runFor(unsigned long cycles); + void setStatePtrs(SaveState &state); + void loadState(const SaveState &state); + void setLayers(unsigned mask) { memory.setLayers(mask); } + + void loadSavedata(const char *data) { memory.loadSavedata(data); } + int saveSavedataLength() {return memory.saveSavedataLength(); } + void saveSavedata(char *dest) { memory.saveSavedata(dest); } + + bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); } + + void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { + memory.setVideoBuffer(videoBuf, pitch); + } + + void setInputGetter(unsigned (*getInput)()) { + memory.setInputGetter(getInput); + } + + void setReadCallback(void (*callback)(unsigned)) { + memory.setReadCallback(callback); + } + + void setWriteCallback(void (*callback)(unsigned)) { + memory.setWriteCallback(callback); + } + + void setExecCallback(void (*callback)(unsigned)) { + memory.setExecCallback(callback); + } + + void setCDCallback(CDCallback cdc) { + memory.setCDCallback(cdc); + } + + void setTraceCallback(void (*callback)(void *)) { + tracecallback = callback; + } + + void setScanlineCallback(void (*callback)(), int sl) { + memory.setScanlineCallback(callback, sl); + } + + void setRTCCallback(std::uint32_t (*callback)()) { + memory.setRTCCallback(callback); + } + + void reset_bios(int setting) { + memory.bios_reset(setting); + } + + int load(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, bool forceDmg, bool multicartCompat) { + return memory.loadROM(romfiledata, romfilelength, biosfiledata, biosfilelength, forceDmg, multicartCompat); + } + + bool loaded() const { return memory.loaded(); } + const char * romTitle() const { return memory.romTitle(); } + + void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); } + unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); } + + bool isCgb() const { return memory.isCgb(); } + + void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) { + memory.setDmgPaletteColor(palNum, colorNum, rgb32); + } + + void setCgbPalette(unsigned *lut) { + memory.setCgbPalette(lut); + } + + //unsigned char ExternalRead(unsigned short addr) { return memory.read(addr, cycleCounter_); } + unsigned char ExternalRead(unsigned short addr) { return memory.peek(addr); } + void ExternalWrite(unsigned short addr, unsigned char val) { memory.write_nocb(addr, val, cycleCounter_); } + + int LinkStatus(int which) { return memory.LinkStatus(which); } + + void GetRegs(int *dest); + templatevoid SyncState(NewState *ns); -}; - -} - -#endif +}; + +} + +#endif diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index d56632d8f5..9a4fa62bf2 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -94,7 +94,15 @@ void GB::reset(const std::uint32_t now) { SaveState state; p_->cpu.setStatePtrs(state); - setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode, now); + if (use_bios) + { + p_->cpu.reset_bios(0); + } + else + { + + } + setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode, now, use_bios); p_->cpu.loadState(state); if (length > 0) { @@ -136,16 +144,17 @@ void GB::setRTCCallback(std::uint32_t (*callback)()) { p_->cpu.setRTCCallback(callback); } -int GB::load(const char *romfiledata, unsigned romfilelength, const std::uint32_t now, const unsigned flags) { +int GB::load(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, const std::uint32_t now, const unsigned flags) { //if (p_->cpu.loaded()) // p_->cpu.saveSavedata(); - const int failed = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT); + const int failed = p_->cpu.load(romfiledata, romfilelength, biosfiledata, biosfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT); + use_bios = biosfilelength > 0 ? true : false; if (!failed) { SaveState state; p_->cpu.setStatePtrs(state); - setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode = flags & GBA_CGB, now); + setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode = flags & GBA_CGB, now, use_bios); p_->cpu.loadState(state); //p_->cpu.loadSavedata(); } diff --git a/libgambatte/src/initstate.cpp b/libgambatte/src/initstate.cpp index 6430061789..e2e1892a76 100644 --- a/libgambatte/src/initstate.cpp +++ b/libgambatte/src/initstate.cpp @@ -1146,7 +1146,7 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) { } // anon namespace -void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode, const std::uint32_t now) { +void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode, const std::uint32_t now, bool boot_bios) { static const unsigned char cgbObjpDump[0x40] = { 0x00, 0x00, 0xF2, 0xAB, 0x61, 0xC2, 0xD9, 0xBA, @@ -1166,22 +1166,47 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM 0x83, 0x40, 0x0B, 0x77 }; - state.cpu.cycleCounter = cgb ? 0x102A0 : 0x102A0 + 0x8D2C; - state.cpu.PC = 0x100; - state.cpu.SP = 0xFFFE; - state.cpu.A = cgb * 0x10 | 0x01; - state.cpu.B = cgb & gbaCgbMode; - state.cpu.C = 0x13; - state.cpu.D = 0x00; - state.cpu.E = 0xD8; - state.cpu.F = 0xB0; - state.cpu.H = 0x01; - state.cpu.L = 0x4D; - state.cpu.skip = false; + if (boot_bios) + { + state.cpu.PC = 0x00; + state.cpu.SP = 0xFFFF; + state.cpu.A = 0; + state.cpu.B = 0; + state.cpu.C = 0x0; + state.cpu.D = 0x0; + state.cpu.E = 0x0; + state.cpu.F = 0x0; + state.cpu.H = 0x0; + state.cpu.L = 0x0; + state.cpu.skip = false; + state.cpu.cycleCounter = 0; + state.mem.ioamhram.ptr[0x140] = 0x00; + state.mem.ioamhram.ptr[0x104] = 0x00; + + } + else + { + state.cpu.PC = 0x100; + state.cpu.SP = 0xFFFE; + state.cpu.A = cgb * 0x10 | 0x01; + state.cpu.B = cgb & gbaCgbMode; + state.cpu.C = 0x13; + state.cpu.D = 0x00; + state.cpu.E = 0xD8; + state.cpu.F = 0xB0; + state.cpu.H = 0x01; + state.cpu.L = 0x4D; + state.cpu.skip = false; + setInitialVram(state.mem.vram.ptr, cgb); + state.cpu.cycleCounter = cgb ? 0x102A0 : 0x102A0 + 0x8D2C; + state.mem.ioamhram.ptr[0x140] = 0x91; + state.mem.ioamhram.ptr[0x104] = 0x1C; + + } std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.getSz()); - setInitialVram(state.mem.vram.ptr, cgb); + if (cgb) { setInitialCgbWram(state.mem.wram.ptr); @@ -1191,8 +1216,6 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM setInitialDmgIoamhram(state.mem.ioamhram.ptr); } - state.mem.ioamhram.ptr[0x104] = 0x1C; - state.mem.ioamhram.ptr[0x140] = 0x91; state.mem.ioamhram.ptr[0x144] = 0x00; state.mem.divLastUpdate = 0; @@ -1258,7 +1281,6 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM state.ppu.oldWy = state.mem.ioamhram.get()[0x14A]; state.ppu.pendingLcdstatIrq = false; - state.spu.cycleCounter = 0x1000 | (state.cpu.cycleCounter >> 1 & 0xFFF); // spu.cycleCounter >> 12 & 7 represents the frame sequencer position. state.spu.ch1.sweep.counter = SoundUnit::COUNTER_DISABLED; diff --git a/libgambatte/src/initstate.h b/libgambatte/src/initstate.h index 8d8ed5aaf6..ec56fae045 100644 --- a/libgambatte/src/initstate.h +++ b/libgambatte/src/initstate.h @@ -22,7 +22,7 @@ #include namespace gambatte { -void setInitState(struct SaveState &state, bool cgb, bool gbaCgbMode, std::uint32_t now); +void setInitState(struct SaveState &state, bool cgb, bool gbaCgbMode, std::uint32_t now, bool boot_bios); } #endif diff --git a/libgambatte/src/memory.cpp b/libgambatte/src/memory.cpp index 4bae856679..79d9820e16 100644 --- a/libgambatte/src/memory.cpp +++ b/libgambatte/src/memory.cpp @@ -1,361 +1,361 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * 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 version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "memory.h" -#include "video.h" -#include "sound.h" -#include "savestate.h" -#include - -namespace gambatte { - -Memory::Memory(const Interrupter &interrupter_in) -: readCallback(0), - writeCallback(0), - execCallback(0), - cdCallback(0), - getInput(0), - divLastUpdate(0), - lastOamDmaUpdate(DISABLED_TIME), - display(ioamhram, 0, VideoInterruptRequester(&intreq)), - interrupter(interrupter_in), - dmaSource(0), - dmaDestination(0), - oamDmaPos(0xFE), - serialCnt(0), - blanklcd(false), - LINKCABLE(false), - linkClockTrigger(false) -{ - intreq.setEventTime(144*456ul); - intreq.setEventTime(0); -} - -void Memory::setStatePtrs(SaveState &state) { - state.mem.ioamhram.set(ioamhram, sizeof ioamhram); - - cart.setStatePtrs(state); - display.setStatePtrs(state); - sound.setStatePtrs(state); -} - - -static inline int serialCntFrom(const unsigned long cyclesUntilDone, const bool cgbFast) { - return cgbFast ? (cyclesUntilDone + 0xF) >> 4 : (cyclesUntilDone + 0x1FF) >> 9; -} - -void Memory::loadState(const SaveState &state) { - sound.loadState(state); - display.loadState(state, state.mem.oamDmaPos < 0xA0 ? cart.rdisabledRam() : ioamhram); - tima.loadState(state, TimaInterruptRequester(intreq)); - cart.loadState(state); - intreq.loadState(state); - - divLastUpdate = state.mem.divLastUpdate; - intreq.setEventTime(state.mem.nextSerialtime > state.cpu.cycleCounter ? state.mem.nextSerialtime : state.cpu.cycleCounter); - intreq.setEventTime(state.mem.unhaltTime); - lastOamDmaUpdate = state.mem.lastOamDmaUpdate; - dmaSource = state.mem.dmaSource; - dmaDestination = state.mem.dmaDestination; - oamDmaPos = state.mem.oamDmaPos; - serialCnt = intreq.eventTime(SERIAL) != DISABLED_TIME - ? serialCntFrom(intreq.eventTime(SERIAL) - state.cpu.cycleCounter, ioamhram[0x102] & isCgb() * 2) - : 8; - - cart.setVrambank(ioamhram[0x14F] & isCgb()); - cart.setOamDmaSrc(OAM_DMA_SRC_OFF); - cart.setWrambank(isCgb() && (ioamhram[0x170] & 0x07) ? ioamhram[0x170] & 0x07 : 1); - - if (lastOamDmaUpdate != DISABLED_TIME) { - oamDmaInitSetup(); - - const unsigned oamEventPos = oamDmaPos < 0xA0 ? 0xA0 : 0x100; - - intreq.setEventTime(lastOamDmaUpdate + (oamEventPos - oamDmaPos) * 4); - } - - intreq.setEventTime((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : state.cpu.cycleCounter); - blanklcd = false; - - if (!isCgb()) - std::memset(cart.vramdata() + 0x2000, 0, 0x2000); -} - -void Memory::setEndtime(const unsigned long cycleCounter, const unsigned long inc) { - if (intreq.eventTime(BLIT) <= cycleCounter) - intreq.setEventTime(intreq.eventTime(BLIT) + (70224 << isDoubleSpeed())); - - intreq.setEventTime(cycleCounter + (inc << isDoubleSpeed())); -} - -void Memory::updateSerial(const unsigned long cc) { - if (!LINKCABLE) { - if (intreq.eventTime(SERIAL) != DISABLED_TIME) { - if (intreq.eventTime(SERIAL) <= cc) { - ioamhram[0x101] = (((ioamhram[0x101] + 1) << serialCnt) - 1) & 0xFF; - ioamhram[0x102] &= 0x7F; - intreq.setEventTime(DISABLED_TIME); - intreq.flagIrq(8); - } else { - const int targetCnt = serialCntFrom(intreq.eventTime(SERIAL) - cc, ioamhram[0x102] & isCgb() * 2); - ioamhram[0x101] = (((ioamhram[0x101] + 1) << (serialCnt - targetCnt)) - 1) & 0xFF; - serialCnt = targetCnt; - } - } - } - else { - if (intreq.eventTime(SERIAL) != DISABLED_TIME) { - if (intreq.eventTime(SERIAL) <= cc) { - linkClockTrigger = true; - intreq.setEventTime(DISABLED_TIME); - } - } - } -} - -void Memory::updateTimaIrq(const unsigned long cc) { - while (intreq.eventTime(TIMA) <= cc) - tima.doIrqEvent(TimaInterruptRequester(intreq)); -} - -void Memory::updateIrqs(const unsigned long cc) { - updateSerial(cc); - updateTimaIrq(cc); - display.update(cc); -} - -unsigned long Memory::event(unsigned long cycleCounter) { - if (lastOamDmaUpdate != DISABLED_TIME) - updateOamDma(cycleCounter); - - switch (intreq.minEventId()) { - case UNHALT: - intreq.unhalt(); - intreq.setEventTime(DISABLED_TIME); - break; - case END: - intreq.setEventTime(DISABLED_TIME - 1); - - while (cycleCounter >= intreq.minEventTime() && intreq.eventTime(END) != DISABLED_TIME) - cycleCounter = event(cycleCounter); - - intreq.setEventTime(DISABLED_TIME); - - break; - case BLIT: - { - const bool lcden = ioamhram[0x140] >> 7 & 1; - unsigned long blitTime = intreq.eventTime(BLIT); - - if (lcden | blanklcd) { - display.updateScreen(blanklcd, cycleCounter); - intreq.setEventTime(DISABLED_TIME); - intreq.setEventTime(DISABLED_TIME); - - while (cycleCounter >= intreq.minEventTime()) - cycleCounter = event(cycleCounter); - } else - blitTime += 70224 << isDoubleSpeed(); - - blanklcd = lcden ^ 1; - intreq.setEventTime(blitTime); - } - break; - case SERIAL: - updateSerial(cycleCounter); - break; - case OAM: - intreq.setEventTime(lastOamDmaUpdate == DISABLED_TIME ? - static_cast(DISABLED_TIME) : intreq.eventTime(OAM) + 0xA0 * 4); - break; - case DMA: - { - const bool doubleSpeed = isDoubleSpeed(); - unsigned dmaSrc = dmaSource; - unsigned dmaDest = dmaDestination; - unsigned dmaLength = ((ioamhram[0x155] & 0x7F) + 0x1) * 0x10; - unsigned length = hdmaReqFlagged(intreq) ? 0x10 : dmaLength; - - ackDmaReq(&intreq); - - if ((static_cast(dmaDest) + length) & 0x10000) { - length = 0x10000 - dmaDest; - ioamhram[0x155] |= 0x80; - } - - dmaLength -= length; - - if (!(ioamhram[0x140] & 0x80)) - dmaLength = 0; - - { - unsigned long lOamDmaUpdate = lastOamDmaUpdate; - lastOamDmaUpdate = DISABLED_TIME; - - while (length--) { - const unsigned src = dmaSrc++ & 0xFFFF; - const unsigned data = ((src & 0xE000) == 0x8000 || src > 0xFDFF) ? 0xFF : read(src, cycleCounter); - - cycleCounter += 2 << doubleSpeed; - - if (cycleCounter - 3 > lOamDmaUpdate) { - oamDmaPos = (oamDmaPos + 1) & 0xFF; - lOamDmaUpdate += 4; - - if (oamDmaPos < 0xA0) { - if (oamDmaPos == 0) - startOamDma(lOamDmaUpdate - 1); - - ioamhram[src & 0xFF] = data; - } else if (oamDmaPos == 0xA0) { - endOamDma(lOamDmaUpdate - 1); - lOamDmaUpdate = DISABLED_TIME; - } - } - - nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cycleCounter); - } - - lastOamDmaUpdate = lOamDmaUpdate; - } - - cycleCounter += 4; - - dmaSource = dmaSrc; - dmaDestination = dmaDest; - ioamhram[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram[0x155] & 0x80); - - if ((ioamhram[0x155] & 0x80) && display.hdmaIsEnabled()) { - if (lastOamDmaUpdate != DISABLED_TIME) - updateOamDma(cycleCounter); - - display.disableHdma(cycleCounter); - } - } - - break; - case TIMA: - tima.doIrqEvent(TimaInterruptRequester(intreq)); - break; - case VIDEO: - display.update(cycleCounter); - break; - case INTERRUPTS: - if (halted()) { - if (isCgb()) - cycleCounter += 4; - - intreq.unhalt(); - intreq.setEventTime(DISABLED_TIME); - } - - if (ime()) { - unsigned address; - const unsigned pendingIrqs = intreq.pendingIrqs(); - const unsigned n = pendingIrqs & -pendingIrqs; - - if (n < 8) { - static const unsigned char lut[] = { 0x40, 0x48, 0x48, 0x50 }; - address = lut[n-1]; - } else - address = 0x50 + n; - - intreq.ackIrq(n); - cycleCounter = interrupter.interrupt(address, cycleCounter, *this); - } - - break; - } - - return cycleCounter; -} - -unsigned long Memory::stop(unsigned long cycleCounter) { - cycleCounter += 4 << isDoubleSpeed(); - - if (ioamhram[0x14D] & isCgb()) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - - display.speedChange(cycleCounter); - ioamhram[0x14D] ^= 0x81; - - intreq.setEventTime((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : cycleCounter + (70224 << isDoubleSpeed())); - - if (intreq.eventTime(END) > cycleCounter) { - intreq.setEventTime(cycleCounter + (isDoubleSpeed() ? - (intreq.eventTime(END) - cycleCounter) << 1 : (intreq.eventTime(END) - cycleCounter) >> 1)); - } - // when switching speed, it seems that the CPU spontaneously restarts soon? - // otherwise, the cpu should be allowed to stay halted as long as needed - // so only execute this line when switching speed - intreq.setEventTime(cycleCounter + 0x20000 + isDoubleSpeed() * 8); - } - - intreq.halt(); - - return cycleCounter; -} - -static void decCycles(unsigned long &counter, const unsigned long dec) { - if (counter != DISABLED_TIME) - counter -= dec; -} - -void Memory::decEventCycles(const MemEventId eventId, const unsigned long dec) { - if (intreq.eventTime(eventId) != DISABLED_TIME) - intreq.setEventTime(eventId, intreq.eventTime(eventId) - dec); -} - -unsigned long Memory::resetCounters(unsigned long cycleCounter) { - if (lastOamDmaUpdate != DISABLED_TIME) - updateOamDma(cycleCounter); - - updateIrqs(cycleCounter); - - const unsigned long oldCC = cycleCounter; - - { - const unsigned long divinc = (cycleCounter - divLastUpdate) >> 8; - ioamhram[0x104] = (ioamhram[0x104] + divinc) & 0xFF; - divLastUpdate += divinc << 8; - } - - const unsigned long dec = cycleCounter < 0x10000 ? 0 : (cycleCounter & ~0x7FFFul) - 0x8000; - - decCycles(divLastUpdate, dec); - decCycles(lastOamDmaUpdate, dec); - decEventCycles(SERIAL, dec); - decEventCycles(OAM, dec); - decEventCycles(BLIT, dec); - decEventCycles(END, dec); - decEventCycles(UNHALT, dec); - - cycleCounter -= dec; - - intreq.resetCc(oldCC, cycleCounter); - tima.resetCc(oldCC, cycleCounter, TimaInterruptRequester(intreq)); - display.resetCc(oldCC, cycleCounter); - sound.resetCounter(cycleCounter, oldCC, isDoubleSpeed()); - - return cycleCounter; -} - -void Memory::updateInput() { +/*************************************************************************** + * Copyright (C) 2007 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "memory.h" +#include "video.h" +#include "sound.h" +#include "savestate.h" +#include + +namespace gambatte { + +Memory::Memory(const Interrupter &interrupter_in) +: readCallback(0), + writeCallback(0), + execCallback(0), + cdCallback(0), + getInput(0), + divLastUpdate(0), + lastOamDmaUpdate(DISABLED_TIME), + display(ioamhram, 0, VideoInterruptRequester(&intreq)), + interrupter(interrupter_in), + dmaSource(0), + dmaDestination(0), + oamDmaPos(0xFE), + serialCnt(0), + blanklcd(false), + LINKCABLE(false), + linkClockTrigger(false) +{ + intreq.setEventTime(144*456ul); + intreq.setEventTime(0); +} + +void Memory::setStatePtrs(SaveState &state) { + state.mem.ioamhram.set(ioamhram, sizeof ioamhram); + + cart.setStatePtrs(state); + display.setStatePtrs(state); + sound.setStatePtrs(state); +} + + +static inline int serialCntFrom(const unsigned long cyclesUntilDone, const bool cgbFast) { + return cgbFast ? (cyclesUntilDone + 0xF) >> 4 : (cyclesUntilDone + 0x1FF) >> 9; +} + +void Memory::loadState(const SaveState &state) { + sound.loadState(state); + display.loadState(state, state.mem.oamDmaPos < 0xA0 ? cart.rdisabledRam() : ioamhram); + tima.loadState(state, TimaInterruptRequester(intreq)); + cart.loadState(state); + intreq.loadState(state); + + divLastUpdate = state.mem.divLastUpdate; + intreq.setEventTime(state.mem.nextSerialtime > state.cpu.cycleCounter ? state.mem.nextSerialtime : state.cpu.cycleCounter); + intreq.setEventTime(state.mem.unhaltTime); + lastOamDmaUpdate = state.mem.lastOamDmaUpdate; + dmaSource = state.mem.dmaSource; + dmaDestination = state.mem.dmaDestination; + oamDmaPos = state.mem.oamDmaPos; + serialCnt = intreq.eventTime(SERIAL) != DISABLED_TIME + ? serialCntFrom(intreq.eventTime(SERIAL) - state.cpu.cycleCounter, ioamhram[0x102] & isCgb() * 2) + : 8; + + cart.setVrambank(ioamhram[0x14F] & isCgb()); + cart.setOamDmaSrc(OAM_DMA_SRC_OFF); + cart.setWrambank(isCgb() && (ioamhram[0x170] & 0x07) ? ioamhram[0x170] & 0x07 : 1); + + if (lastOamDmaUpdate != DISABLED_TIME) { + oamDmaInitSetup(); + + const unsigned oamEventPos = oamDmaPos < 0xA0 ? 0xA0 : 0x100; + + intreq.setEventTime(lastOamDmaUpdate + (oamEventPos - oamDmaPos) * 4); + } + + intreq.setEventTime((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : state.cpu.cycleCounter); + blanklcd = false; + + if (!isCgb()) + std::memset(cart.vramdata() + 0x2000, 0, 0x2000); +} + +void Memory::setEndtime(const unsigned long cycleCounter, const unsigned long inc) { + if (intreq.eventTime(BLIT) <= cycleCounter) + intreq.setEventTime(intreq.eventTime(BLIT) + (70224 << isDoubleSpeed())); + + intreq.setEventTime(cycleCounter + (inc << isDoubleSpeed())); +} + +void Memory::updateSerial(const unsigned long cc) { + if (!LINKCABLE) { + if (intreq.eventTime(SERIAL) != DISABLED_TIME) { + if (intreq.eventTime(SERIAL) <= cc) { + ioamhram[0x101] = (((ioamhram[0x101] + 1) << serialCnt) - 1) & 0xFF; + ioamhram[0x102] &= 0x7F; + intreq.setEventTime(DISABLED_TIME); + intreq.flagIrq(8); + } else { + const int targetCnt = serialCntFrom(intreq.eventTime(SERIAL) - cc, ioamhram[0x102] & isCgb() * 2); + ioamhram[0x101] = (((ioamhram[0x101] + 1) << (serialCnt - targetCnt)) - 1) & 0xFF; + serialCnt = targetCnt; + } + } + } + else { + if (intreq.eventTime(SERIAL) != DISABLED_TIME) { + if (intreq.eventTime(SERIAL) <= cc) { + linkClockTrigger = true; + intreq.setEventTime(DISABLED_TIME); + } + } + } +} + +void Memory::updateTimaIrq(const unsigned long cc) { + while (intreq.eventTime(TIMA) <= cc) + tima.doIrqEvent(TimaInterruptRequester(intreq)); +} + +void Memory::updateIrqs(const unsigned long cc) { + updateSerial(cc); + updateTimaIrq(cc); + display.update(cc); +} + +unsigned long Memory::event(unsigned long cycleCounter) { + if (lastOamDmaUpdate != DISABLED_TIME) + updateOamDma(cycleCounter); + + switch (intreq.minEventId()) { + case UNHALT: + intreq.unhalt(); + intreq.setEventTime(DISABLED_TIME); + break; + case END: + intreq.setEventTime(DISABLED_TIME - 1); + + while (cycleCounter >= intreq.minEventTime() && intreq.eventTime(END) != DISABLED_TIME) + cycleCounter = event(cycleCounter); + + intreq.setEventTime(DISABLED_TIME); + + break; + case BLIT: + { + const bool lcden = ioamhram[0x140] >> 7 & 1; + unsigned long blitTime = intreq.eventTime(BLIT); + + if (lcden | blanklcd) { + display.updateScreen(blanklcd, cycleCounter); + intreq.setEventTime(DISABLED_TIME); + intreq.setEventTime(DISABLED_TIME); + + while (cycleCounter >= intreq.minEventTime()) + cycleCounter = event(cycleCounter); + } else + blitTime += 70224 << isDoubleSpeed(); + + blanklcd = lcden ^ 1; + intreq.setEventTime(blitTime); + } + break; + case SERIAL: + updateSerial(cycleCounter); + break; + case OAM: + intreq.setEventTime(lastOamDmaUpdate == DISABLED_TIME ? + static_cast(DISABLED_TIME) : intreq.eventTime(OAM) + 0xA0 * 4); + break; + case DMA: + { + const bool doubleSpeed = isDoubleSpeed(); + unsigned dmaSrc = dmaSource; + unsigned dmaDest = dmaDestination; + unsigned dmaLength = ((ioamhram[0x155] & 0x7F) + 0x1) * 0x10; + unsigned length = hdmaReqFlagged(intreq) ? 0x10 : dmaLength; + + ackDmaReq(&intreq); + + if ((static_cast(dmaDest) + length) & 0x10000) { + length = 0x10000 - dmaDest; + ioamhram[0x155] |= 0x80; + } + + dmaLength -= length; + + if (!(ioamhram[0x140] & 0x80)) + dmaLength = 0; + + { + unsigned long lOamDmaUpdate = lastOamDmaUpdate; + lastOamDmaUpdate = DISABLED_TIME; + + while (length--) { + const unsigned src = dmaSrc++ & 0xFFFF; + const unsigned data = ((src & 0xE000) == 0x8000 || src > 0xFDFF) ? 0xFF : read(src, cycleCounter); + + cycleCounter += 2 << doubleSpeed; + + if (cycleCounter - 3 > lOamDmaUpdate) { + oamDmaPos = (oamDmaPos + 1) & 0xFF; + lOamDmaUpdate += 4; + + if (oamDmaPos < 0xA0) { + if (oamDmaPos == 0) + startOamDma(lOamDmaUpdate - 1); + + ioamhram[src & 0xFF] = data; + } else if (oamDmaPos == 0xA0) { + endOamDma(lOamDmaUpdate - 1); + lOamDmaUpdate = DISABLED_TIME; + } + } + + nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cycleCounter); + } + + lastOamDmaUpdate = lOamDmaUpdate; + } + + cycleCounter += 4; + + dmaSource = dmaSrc; + dmaDestination = dmaDest; + ioamhram[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram[0x155] & 0x80); + + if ((ioamhram[0x155] & 0x80) && display.hdmaIsEnabled()) { + if (lastOamDmaUpdate != DISABLED_TIME) + updateOamDma(cycleCounter); + + display.disableHdma(cycleCounter); + } + } + + break; + case TIMA: + tima.doIrqEvent(TimaInterruptRequester(intreq)); + break; + case VIDEO: + display.update(cycleCounter); + break; + case INTERRUPTS: + if (halted()) { + if (isCgb()) + cycleCounter += 4; + + intreq.unhalt(); + intreq.setEventTime(DISABLED_TIME); + } + + if (ime()) { + unsigned address; + const unsigned pendingIrqs = intreq.pendingIrqs(); + const unsigned n = pendingIrqs & -pendingIrqs; + + if (n < 8) { + static const unsigned char lut[] = { 0x40, 0x48, 0x48, 0x50 }; + address = lut[n-1]; + } else + address = 0x50 + n; + + intreq.ackIrq(n); + cycleCounter = interrupter.interrupt(address, cycleCounter, *this); + } + + break; + } + + return cycleCounter; +} + +unsigned long Memory::stop(unsigned long cycleCounter) { + cycleCounter += 4 << isDoubleSpeed(); + + if (ioamhram[0x14D] & isCgb()) { + sound.generate_samples(cycleCounter, isDoubleSpeed()); + + display.speedChange(cycleCounter); + ioamhram[0x14D] ^= 0x81; + + intreq.setEventTime((ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : cycleCounter + (70224 << isDoubleSpeed())); + + if (intreq.eventTime(END) > cycleCounter) { + intreq.setEventTime(cycleCounter + (isDoubleSpeed() ? + (intreq.eventTime(END) - cycleCounter) << 1 : (intreq.eventTime(END) - cycleCounter) >> 1)); + } + // when switching speed, it seems that the CPU spontaneously restarts soon? + // otherwise, the cpu should be allowed to stay halted as long as needed + // so only execute this line when switching speed + intreq.setEventTime(cycleCounter + 0x20000 + isDoubleSpeed() * 8); + } + + intreq.halt(); + + return cycleCounter; +} + +static void decCycles(unsigned long &counter, const unsigned long dec) { + if (counter != DISABLED_TIME) + counter -= dec; +} + +void Memory::decEventCycles(const MemEventId eventId, const unsigned long dec) { + if (intreq.eventTime(eventId) != DISABLED_TIME) + intreq.setEventTime(eventId, intreq.eventTime(eventId) - dec); +} + +unsigned long Memory::resetCounters(unsigned long cycleCounter) { + if (lastOamDmaUpdate != DISABLED_TIME) + updateOamDma(cycleCounter); + + updateIrqs(cycleCounter); + + const unsigned long oldCC = cycleCounter; + + { + const unsigned long divinc = (cycleCounter - divLastUpdate) >> 8; + ioamhram[0x104] = (ioamhram[0x104] + divinc) & 0xFF; + divLastUpdate += divinc << 8; + } + + const unsigned long dec = cycleCounter < 0x10000 ? 0 : (cycleCounter & ~0x7FFFul) - 0x8000; + + decCycles(divLastUpdate, dec); + decCycles(lastOamDmaUpdate, dec); + decEventCycles(SERIAL, dec); + decEventCycles(OAM, dec); + decEventCycles(BLIT, dec); + decEventCycles(END, dec); + decEventCycles(UNHALT, dec); + + cycleCounter -= dec; + + intreq.resetCc(oldCC, cycleCounter); + tima.resetCc(oldCC, cycleCounter, TimaInterruptRequester(intreq)); + display.resetCc(oldCC, cycleCounter); + sound.resetCounter(cycleCounter, oldCC, isDoubleSpeed()); + + return cycleCounter; +} + +void Memory::updateInput() { unsigned state = 0xF; if ((ioamhram[0x100] & 0x30) != 0x30 && getInput) { @@ -371,720 +371,725 @@ void Memory::updateInput() { if (state != 0xF && (ioamhram[0x100] & 0xF) == 0xF) intreq.flagIrq(0x10); - ioamhram[0x100] = (ioamhram[0x100] & -0x10u) | state; -} - -void Memory::updateOamDma(const unsigned long cycleCounter) { - const unsigned char *const oamDmaSrc = oamDmaSrcPtr(); - unsigned cycles = (cycleCounter - lastOamDmaUpdate) >> 2; - - while (cycles--) { - oamDmaPos = (oamDmaPos + 1) & 0xFF; - lastOamDmaUpdate += 4; - - if (oamDmaPos < 0xA0) { - if (oamDmaPos == 0) - startOamDma(lastOamDmaUpdate - 1); - - ioamhram[oamDmaPos] = oamDmaSrc ? oamDmaSrc[oamDmaPos] : cart.rtcRead(); - } else if (oamDmaPos == 0xA0) { - endOamDma(lastOamDmaUpdate - 1); - lastOamDmaUpdate = DISABLED_TIME; - break; - } - } -} - -void Memory::oamDmaInitSetup() { - if (ioamhram[0x146] < 0xA0) { - cart.setOamDmaSrc(ioamhram[0x146] < 0x80 ? OAM_DMA_SRC_ROM : OAM_DMA_SRC_VRAM); - } else if (ioamhram[0x146] < 0xFE - isCgb() * 0x1E) { - cart.setOamDmaSrc(ioamhram[0x146] < 0xC0 ? OAM_DMA_SRC_SRAM : OAM_DMA_SRC_WRAM); - } else - cart.setOamDmaSrc(OAM_DMA_SRC_INVALID); -} - -static const unsigned char * oamDmaSrcZero() { - static unsigned char zeroMem[0xA0]; - return zeroMem; -} - -const unsigned char * Memory::oamDmaSrcPtr() const { - switch (cart.oamDmaSrc()) { - case OAM_DMA_SRC_ROM: return cart.romdata(ioamhram[0x146] >> 6) + (ioamhram[0x146] << 8); - case OAM_DMA_SRC_SRAM: return cart.rsrambankptr() ? cart.rsrambankptr() + (ioamhram[0x146] << 8) : 0; - case OAM_DMA_SRC_VRAM: return cart.vrambankptr() + (ioamhram[0x146] << 8); - case OAM_DMA_SRC_WRAM: return cart.wramdata(ioamhram[0x146] >> 4 & 1) + (ioamhram[0x146] << 8 & 0xFFF); - case OAM_DMA_SRC_INVALID: - case OAM_DMA_SRC_OFF: break; - } - - return ioamhram[0x146] == 0xFF && !isCgb() ? oamDmaSrcZero() : cart.rdisabledRam(); -} - -void Memory::startOamDma(const unsigned long cycleCounter) { - display.oamChange(cart.rdisabledRam(), cycleCounter); -} - -void Memory::endOamDma(const unsigned long cycleCounter) { - oamDmaPos = 0xFE; - cart.setOamDmaSrc(OAM_DMA_SRC_OFF); - display.oamChange(ioamhram, cycleCounter); -} - -unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleCounter) { - if (lastOamDmaUpdate != DISABLED_TIME) - updateOamDma(cycleCounter); - - switch (P & 0x7F) { - case 0x00: - updateInput(); - break; - case 0x01: - case 0x02: - updateSerial(cycleCounter); - break; - case 0x04: - { - const unsigned long divcycles = (cycleCounter - divLastUpdate) >> 8; - ioamhram[0x104] = (ioamhram[0x104] + divcycles) & 0xFF; - divLastUpdate += divcycles << 8; - } - - break; - case 0x05: - ioamhram[0x105] = tima.tima(cycleCounter); - break; - case 0x0F: - updateIrqs(cycleCounter); - ioamhram[0x10F] = intreq.ifreg(); - break; - case 0x26: - if (ioamhram[0x126] & 0x80) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - ioamhram[0x126] = 0xF0 | sound.getStatus(); - } else - ioamhram[0x126] = 0x70; - - break; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - sound.generate_samples(cycleCounter, isDoubleSpeed()); - return sound.waveRamRead(P & 0xF); - case 0x41: - return ioamhram[0x141] | display.getStat(ioamhram[0x145], cycleCounter); - case 0x44: - return display.getLyReg(cycleCounter/*+4*/); - case 0x69: - return display.cgbBgColorRead(ioamhram[0x168] & 0x3F, cycleCounter); - case 0x6B: - return display.cgbSpColorRead(ioamhram[0x16A] & 0x3F, cycleCounter); - default: break; - } - - return ioamhram[P - 0xFE00]; -} - -static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned addr, const bool cgb) { - struct Area { unsigned short areaUpper, exceptAreaLower, exceptAreaWidth, pad; }; - - static const Area cgbAreas[] = { - { 0xC000, 0x8000, 0x2000, 0 }, - { 0xC000, 0x8000, 0x2000, 0 }, - { 0xA000, 0x0000, 0x8000, 0 }, - { 0xFE00, 0x0000, 0xC000, 0 }, - { 0xC000, 0x8000, 0x2000, 0 }, - { 0x0000, 0x0000, 0x0000, 0 } - }; - - static const Area dmgAreas[] = { - { 0xFE00, 0x8000, 0x2000, 0 }, - { 0xFE00, 0x8000, 0x2000, 0 }, - { 0xA000, 0x0000, 0x8000, 0 }, - { 0xFE00, 0x8000, 0x2000, 0 }, - { 0xFE00, 0x8000, 0x2000, 0 }, - { 0x0000, 0x0000, 0x0000, 0 } - }; - - const Area *const a = cgb ? cgbAreas : dmgAreas; - - return addr < a[oamDmaSrc].areaUpper && addr - a[oamDmaSrc].exceptAreaLower >= a[oamDmaSrc].exceptAreaWidth; -} - -unsigned Memory::nontrivial_read(const unsigned P, const unsigned long cycleCounter) { - if (P < 0xFF80) { - if (lastOamDmaUpdate != DISABLED_TIME) { - updateOamDma(cycleCounter); - - if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0) - return ioamhram[oamDmaPos]; - } - - if (P < 0xC000) { - if (P < 0x8000) - return cart.romdata(P >> 14)[P]; - - if (P < 0xA000) { - if (!display.vramAccessible(cycleCounter)) - return 0xFF; - - return cart.vrambankptr()[P]; - } - - if (cart.rsrambankptr()) - return cart.rsrambankptr()[P]; - - return cart.rtcRead(); - } - - if (P < 0xFE00) - return cart.wramdata(P >> 12 & 1)[P & 0xFFF]; - - if (P >= 0xFF00) - return nontrivial_ff_read(P, cycleCounter); - - if (!display.oamReadable(cycleCounter) || oamDmaPos < 0xA0) - return 0xFF; - } - - return ioamhram[P - 0xFE00]; -} - -unsigned Memory::nontrivial_peek(const unsigned P) { - if (P < 0xC000) { - if (P < 0x8000) - return cart.romdata(P >> 14)[P]; - - if (P < 0xA000) { - return cart.vrambankptr()[P]; - } - - if (cart.rsrambankptr()) - return cart.rsrambankptr()[P]; - - return cart.rtcRead(); // verified side-effect free - } - if (P < 0xFE00) - return cart.wramdata(P >> 12 & 1)[P & 0xFFF]; - if (P >= 0xFF00 && P < 0xFF80) - return nontrivial_ff_peek(P); - return ioamhram[P - 0xFE00]; -} - -unsigned Memory::nontrivial_ff_peek(const unsigned P) { - // some regs may be somewhat wrong with this - return ioamhram[P - 0xFE00]; -} - -void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned long cycleCounter) { - if (lastOamDmaUpdate != DISABLED_TIME) - updateOamDma(cycleCounter); - - switch (P & 0xFF) { + ioamhram[0x100] = (ioamhram[0x100] & -0x10u) | state; +} + +void Memory::updateOamDma(const unsigned long cycleCounter) { + const unsigned char *const oamDmaSrc = oamDmaSrcPtr(); + unsigned cycles = (cycleCounter - lastOamDmaUpdate) >> 2; + + while (cycles--) { + oamDmaPos = (oamDmaPos + 1) & 0xFF; + lastOamDmaUpdate += 4; + + if (oamDmaPos < 0xA0) { + if (oamDmaPos == 0) + startOamDma(lastOamDmaUpdate - 1); + + ioamhram[oamDmaPos] = oamDmaSrc ? oamDmaSrc[oamDmaPos] : cart.rtcRead(); + } else if (oamDmaPos == 0xA0) { + endOamDma(lastOamDmaUpdate - 1); + lastOamDmaUpdate = DISABLED_TIME; + break; + } + } +} + +void Memory::oamDmaInitSetup() { + if (ioamhram[0x146] < 0xA0) { + cart.setOamDmaSrc(ioamhram[0x146] < 0x80 ? OAM_DMA_SRC_ROM : OAM_DMA_SRC_VRAM); + } else if (ioamhram[0x146] < 0xFE - isCgb() * 0x1E) { + cart.setOamDmaSrc(ioamhram[0x146] < 0xC0 ? OAM_DMA_SRC_SRAM : OAM_DMA_SRC_WRAM); + } else + cart.setOamDmaSrc(OAM_DMA_SRC_INVALID); +} + +static const unsigned char * oamDmaSrcZero() { + static unsigned char zeroMem[0xA0]; + return zeroMem; +} + +const unsigned char * Memory::oamDmaSrcPtr() const { + switch (cart.oamDmaSrc()) { + case OAM_DMA_SRC_ROM: return cart.romdata(ioamhram[0x146] >> 6) + (ioamhram[0x146] << 8); + case OAM_DMA_SRC_SRAM: return cart.rsrambankptr() ? cart.rsrambankptr() + (ioamhram[0x146] << 8) : 0; + case OAM_DMA_SRC_VRAM: return cart.vrambankptr() + (ioamhram[0x146] << 8); + case OAM_DMA_SRC_WRAM: return cart.wramdata(ioamhram[0x146] >> 4 & 1) + (ioamhram[0x146] << 8 & 0xFFF); + case OAM_DMA_SRC_INVALID: + case OAM_DMA_SRC_OFF: break; + } + + return ioamhram[0x146] == 0xFF && !isCgb() ? oamDmaSrcZero() : cart.rdisabledRam(); +} + +void Memory::startOamDma(const unsigned long cycleCounter) { + display.oamChange(cart.rdisabledRam(), cycleCounter); +} + +void Memory::endOamDma(const unsigned long cycleCounter) { + oamDmaPos = 0xFE; + cart.setOamDmaSrc(OAM_DMA_SRC_OFF); + display.oamChange(ioamhram, cycleCounter); +} + +unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleCounter) { + if (lastOamDmaUpdate != DISABLED_TIME) + updateOamDma(cycleCounter); + + switch (P & 0x7F) { + case 0x00: + updateInput(); + break; + case 0x01: + case 0x02: + updateSerial(cycleCounter); + break; + case 0x04: + { + const unsigned long divcycles = (cycleCounter - divLastUpdate) >> 8; + ioamhram[0x104] = (ioamhram[0x104] + divcycles) & 0xFF; + divLastUpdate += divcycles << 8; + } + + break; + case 0x05: + ioamhram[0x105] = tima.tima(cycleCounter); + break; + case 0x0F: + updateIrqs(cycleCounter); + ioamhram[0x10F] = intreq.ifreg(); + break; + case 0x26: + if (ioamhram[0x126] & 0x80) { + sound.generate_samples(cycleCounter, isDoubleSpeed()); + ioamhram[0x126] = 0xF0 | sound.getStatus(); + } else + ioamhram[0x126] = 0x70; + + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + sound.generate_samples(cycleCounter, isDoubleSpeed()); + return sound.waveRamRead(P & 0xF); + case 0x41: + return ioamhram[0x141] | display.getStat(ioamhram[0x145], cycleCounter); + case 0x44: + return display.getLyReg(cycleCounter/*+4*/); + case 0x69: + return display.cgbBgColorRead(ioamhram[0x168] & 0x3F, cycleCounter); + case 0x6B: + return display.cgbSpColorRead(ioamhram[0x16A] & 0x3F, cycleCounter); + default: break; + } + + return ioamhram[P - 0xFE00]; +} + +static bool isInOamDmaConflictArea(const OamDmaSrc oamDmaSrc, const unsigned addr, const bool cgb) { + struct Area { unsigned short areaUpper, exceptAreaLower, exceptAreaWidth, pad; }; + + static const Area cgbAreas[] = { + { 0xC000, 0x8000, 0x2000, 0 }, + { 0xC000, 0x8000, 0x2000, 0 }, + { 0xA000, 0x0000, 0x8000, 0 }, + { 0xFE00, 0x0000, 0xC000, 0 }, + { 0xC000, 0x8000, 0x2000, 0 }, + { 0x0000, 0x0000, 0x0000, 0 } + }; + + static const Area dmgAreas[] = { + { 0xFE00, 0x8000, 0x2000, 0 }, + { 0xFE00, 0x8000, 0x2000, 0 }, + { 0xA000, 0x0000, 0x8000, 0 }, + { 0xFE00, 0x8000, 0x2000, 0 }, + { 0xFE00, 0x8000, 0x2000, 0 }, + { 0x0000, 0x0000, 0x0000, 0 } + }; + + const Area *const a = cgb ? cgbAreas : dmgAreas; + + return addr < a[oamDmaSrc].areaUpper && addr - a[oamDmaSrc].exceptAreaLower >= a[oamDmaSrc].exceptAreaWidth; +} + +unsigned Memory::nontrivial_read(const unsigned P, const unsigned long cycleCounter) { + if (P < 0xFF80) { + if (lastOamDmaUpdate != DISABLED_TIME) { + updateOamDma(cycleCounter); + + if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0) + return ioamhram[oamDmaPos]; + } + + if (P < 0xC000) { + if (P < 0x8000) + return cart.romdata(P >> 14)[P]; + + if (P < 0xA000) { + if (!display.vramAccessible(cycleCounter)) + return 0xFF; + + return cart.vrambankptr()[P]; + } + + if (cart.rsrambankptr()) + return cart.rsrambankptr()[P]; + + return cart.rtcRead(); + } + + if (P < 0xFE00) + return cart.wramdata(P >> 12 & 1)[P & 0xFFF]; + + if (P >= 0xFF00) + return nontrivial_ff_read(P, cycleCounter); + + if (!display.oamReadable(cycleCounter) || oamDmaPos < 0xA0) + return 0xFF; + } + + return ioamhram[P - 0xFE00]; +} + +unsigned Memory::nontrivial_peek(const unsigned P) { + if (P < 0xC000) { + if (P < 0x8000) + return cart.romdata(P >> 14)[P]; + + if (P < 0xA000) { + return cart.vrambankptr()[P]; + } + + if (cart.rsrambankptr()) + return cart.rsrambankptr()[P]; + + return cart.rtcRead(); // verified side-effect free + } + if (P < 0xFE00) + return cart.wramdata(P >> 12 & 1)[P & 0xFFF]; + if (P >= 0xFF00 && P < 0xFF80) + return nontrivial_ff_peek(P); + return ioamhram[P - 0xFE00]; +} + +unsigned Memory::nontrivial_ff_peek(const unsigned P) { + // some regs may be somewhat wrong with this + return ioamhram[P - 0xFE00]; +} + +void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned long cycleCounter) { + if (lastOamDmaUpdate != DISABLED_TIME) + updateOamDma(cycleCounter); + + switch (P & 0xFF) { case 0x00: if ((data ^ ioamhram[0x100]) & 0x30) { ioamhram[0x100] = (ioamhram[0x100] & ~0x30u) | (data & 0x30); updateInput(); } - return; - case 0x01: - updateSerial(cycleCounter); - break; - case 0x02: - updateSerial(cycleCounter); - - serialCnt = 8; - intreq.setEventTime((data & 0x81) == 0x81 - ? (data & isCgb() * 2 ? (cycleCounter & ~0x7ul) + 0x10 * 8 : (cycleCounter & ~0xFFul) + 0x200 * 8) - : static_cast(DISABLED_TIME)); - - data |= 0x7E - isCgb() * 2; - break; - case 0x04: - ioamhram[0x104] = 0; - divLastUpdate = cycleCounter; - return; - case 0x05: - tima.setTima(data, cycleCounter, TimaInterruptRequester(intreq)); - break; - case 0x06: - tima.setTma(data, cycleCounter, TimaInterruptRequester(intreq)); - break; - case 0x07: - data |= 0xF8; - tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq)); - break; - case 0x0F: - updateIrqs(cycleCounter); - intreq.setIfreg(0xE0 | data); - return; - case 0x10: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr10(data); - data |= 0x80; - break; - case 0x11: - if (!sound.isEnabled()) { - if (isCgb()) - return; - - data &= 0x3F; - } - - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr11(data); - data |= 0x3F; - break; - case 0x12: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr12(data); - break; - case 0x13: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr13(data); - return; - case 0x14: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr14(data); - data |= 0xBF; - break; - case 0x16: - if (!sound.isEnabled()) { - if (isCgb()) - return; - - data &= 0x3F; - } - - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr21(data); - data |= 0x3F; - break; - case 0x17: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr22(data); - break; - case 0x18: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr23(data); - return; - case 0x19: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr24(data); - data |= 0xBF; - break; - case 0x1A: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr30(data); - data |= 0x7F; - break; - case 0x1B: - if (!sound.isEnabled() && isCgb()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr31(data); - return; - case 0x1C: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr32(data); - data |= 0x9F; - break; - case 0x1D: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr33(data); - return; - case 0x1E: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr34(data); - data |= 0xBF; - break; - case 0x20: - if (!sound.isEnabled() && isCgb()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr41(data); - return; - case 0x21: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr42(data); - break; - case 0x22: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr43(data); - break; - case 0x23: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr44(data); - data |= 0xBF; - break; - case 0x24: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_so_volume(data); - break; - case 0x25: - if (!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.map_so(data); - break; - case 0x26: - if ((ioamhram[0x126] ^ data) & 0x80) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - - if (!(data & 0x80)) { - for (unsigned i = 0xFF10; i < 0xFF26; ++i) - ff_write(i, 0, cycleCounter); - - sound.setEnabled(false); - } else { - sound.reset(); - sound.setEnabled(true); - } - } - - data = (data & 0x80) | (ioamhram[0x126] & 0x7F); - break; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.waveRamWrite(P & 0xF, data); - break; - case 0x40: - if (ioamhram[0x140] != data) { - if ((ioamhram[0x140] ^ data) & 0x80) { - const unsigned lyc = display.getStat(ioamhram[0x145], cycleCounter) & 4; - const bool hdmaEnabled = display.hdmaIsEnabled(); - - display.lcdcChange(data, cycleCounter); - ioamhram[0x144] = 0; - ioamhram[0x141] &= 0xF8; - - if (data & 0x80) { - intreq.setEventTime(display.nextMode1IrqTime() + (blanklcd ? 0 : 70224 << isDoubleSpeed())); - } else { - ioamhram[0x141] |= lyc; - intreq.setEventTime(cycleCounter + (456 * 4 << isDoubleSpeed())); - - if (hdmaEnabled) - flagHdmaReq(&intreq); - } - } else - display.lcdcChange(data, cycleCounter); - - ioamhram[0x140] = data; - } - - return; - case 0x41: - display.lcdstatChange(data, cycleCounter); - data = (ioamhram[0x141] & 0x87) | (data & 0x78); - break; - case 0x42: - display.scyChange(data, cycleCounter); - break; - case 0x43: - display.scxChange(data, cycleCounter); - break; - case 0x45: - display.lycRegChange(data, cycleCounter); - break; - case 0x46: - if (lastOamDmaUpdate != DISABLED_TIME) - endOamDma(cycleCounter); - - lastOamDmaUpdate = cycleCounter; - intreq.setEventTime(cycleCounter + 8); - ioamhram[0x146] = data; - oamDmaInitSetup(); - return; - case 0x47: - if (!isCgb()) - display.dmgBgPaletteChange(data, cycleCounter); - - break; - case 0x48: - if (!isCgb()) - display.dmgSpPalette1Change(data, cycleCounter); - - break; - case 0x49: - if (!isCgb()) - display.dmgSpPalette2Change(data, cycleCounter); - - break; - case 0x4A: - display.wyChange(data, cycleCounter); - break; - case 0x4B: - display.wxChange(data, cycleCounter); - break; - - case 0x4D: + return; + case 0x01: + updateSerial(cycleCounter); + break; + case 0x02: + updateSerial(cycleCounter); + + serialCnt = 8; + intreq.setEventTime((data & 0x81) == 0x81 + ? (data & isCgb() * 2 ? (cycleCounter & ~0x7ul) + 0x10 * 8 : (cycleCounter & ~0xFFul) + 0x200 * 8) + : static_cast(DISABLED_TIME)); + + data |= 0x7E - isCgb() * 2; + break; + case 0x04: + ioamhram[0x104] = 0; + divLastUpdate = cycleCounter; + return; + case 0x05: + tima.setTima(data, cycleCounter, TimaInterruptRequester(intreq)); + break; + case 0x06: + tima.setTma(data, cycleCounter, TimaInterruptRequester(intreq)); + break; + case 0x07: + data |= 0xF8; + tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq)); + break; + case 0x0F: + updateIrqs(cycleCounter); + intreq.setIfreg(0xE0 | data); + return; + case 0x10: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr10(data); + data |= 0x80; + break; + case 0x11: + if (!sound.isEnabled()) { + if (isCgb()) + return; + + data &= 0x3F; + } + + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr11(data); + data |= 0x3F; + break; + case 0x12: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr12(data); + break; + case 0x13: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr13(data); + return; + case 0x14: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr14(data); + data |= 0xBF; + break; + case 0x16: + if (!sound.isEnabled()) { + if (isCgb()) + return; + + data &= 0x3F; + } + + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr21(data); + data |= 0x3F; + break; + case 0x17: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr22(data); + break; + case 0x18: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr23(data); + return; + case 0x19: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr24(data); + data |= 0xBF; + break; + case 0x1A: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr30(data); + data |= 0x7F; + break; + case 0x1B: + if (!sound.isEnabled() && isCgb()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr31(data); + return; + case 0x1C: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr32(data); + data |= 0x9F; + break; + case 0x1D: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr33(data); + return; + case 0x1E: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr34(data); + data |= 0xBF; + break; + case 0x20: + if (!sound.isEnabled() && isCgb()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr41(data); + return; + case 0x21: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr42(data); + break; + case 0x22: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr43(data); + break; + case 0x23: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_nr44(data); + data |= 0xBF; + break; + case 0x24: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.set_so_volume(data); + break; + case 0x25: + if (!sound.isEnabled()) return; + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.map_so(data); + break; + case 0x26: + if ((ioamhram[0x126] ^ data) & 0x80) { + sound.generate_samples(cycleCounter, isDoubleSpeed()); + + if (!(data & 0x80)) { + for (unsigned i = 0xFF10; i < 0xFF26; ++i) + ff_write(i, 0, cycleCounter); + + sound.setEnabled(false); + } else { + sound.reset(); + sound.setEnabled(true); + } + } + + data = (data & 0x80) | (ioamhram[0x126] & 0x7F); + break; + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + sound.generate_samples(cycleCounter, isDoubleSpeed()); + sound.waveRamWrite(P & 0xF, data); + break; + case 0x40: + if (ioamhram[0x140] != data) { + if ((ioamhram[0x140] ^ data) & 0x80) { + const unsigned lyc = display.getStat(ioamhram[0x145], cycleCounter) & 4; + const bool hdmaEnabled = display.hdmaIsEnabled(); + + display.lcdcChange(data, cycleCounter); + ioamhram[0x144] = 0; + ioamhram[0x141] &= 0xF8; + + if (data & 0x80) { + intreq.setEventTime(display.nextMode1IrqTime() + (blanklcd ? 0 : 70224 << isDoubleSpeed())); + } else { + ioamhram[0x141] |= lyc; + intreq.setEventTime(cycleCounter + (456 * 4 << isDoubleSpeed())); + + if (hdmaEnabled) + flagHdmaReq(&intreq); + } + } else + display.lcdcChange(data, cycleCounter); + + ioamhram[0x140] = data; + } + + return; + case 0x41: + display.lcdstatChange(data, cycleCounter); + data = (ioamhram[0x141] & 0x87) | (data & 0x78); + break; + case 0x42: + display.scyChange(data, cycleCounter); + break; + case 0x43: + display.scxChange(data, cycleCounter); + break; + case 0x45: + display.lycRegChange(data, cycleCounter); + break; + case 0x46: + if (lastOamDmaUpdate != DISABLED_TIME) + endOamDma(cycleCounter); + + lastOamDmaUpdate = cycleCounter; + intreq.setEventTime(cycleCounter + 8); + ioamhram[0x146] = data; + oamDmaInitSetup(); + return; + case 0x47: + if (!isCgb()) + display.dmgBgPaletteChange(data, cycleCounter); + + break; + case 0x48: + if (!isCgb()) + display.dmgSpPalette1Change(data, cycleCounter); + + break; + case 0x49: + if (!isCgb()) + display.dmgSpPalette2Change(data, cycleCounter); + + break; + case 0x4A: + display.wyChange(data, cycleCounter); + break; + case 0x4B: + display.wxChange(data, cycleCounter); + break; + + case 0x4D: if (isCgb()) - ioamhram[0x14D] = (ioamhram[0x14D] & ~1u) | (data & 1); return; - case 0x4F: - if (isCgb()) { - cart.setVrambank(data & 1); - ioamhram[0x14F] = 0xFE | data; - } - - return; - case 0x51: - dmaSource = data << 8 | (dmaSource & 0xFF); - return; - case 0x52: - dmaSource = (dmaSource & 0xFF00) | (data & 0xF0); - return; - case 0x53: - dmaDestination = data << 8 | (dmaDestination & 0xFF); - return; - case 0x54: - dmaDestination = (dmaDestination & 0xFF00) | (data & 0xF0); - return; - case 0x55: - if (isCgb()) { - ioamhram[0x155] = data & 0x7F; - - if (display.hdmaIsEnabled()) { - if (!(data & 0x80)) { - ioamhram[0x155] |= 0x80; - display.disableHdma(cycleCounter); - } - } else { - if (data & 0x80) { - if (ioamhram[0x140] & 0x80) { - display.enableHdma(cycleCounter); - } else - flagHdmaReq(&intreq); - } else - flagGdmaReq(&intreq); - } - } - - return; - case 0x56: - if (isCgb()) - ioamhram[0x156] = data | 0x3E; - - return; - case 0x68: - if (isCgb()) - ioamhram[0x168] = data | 0x40; - - return; - case 0x69: - if (isCgb()) { - const unsigned index = ioamhram[0x168] & 0x3F; - - display.cgbBgColorChange(index, data, cycleCounter); - - ioamhram[0x168] = (ioamhram[0x168] & ~0x3F) | ((index + (ioamhram[0x168] >> 7)) & 0x3F); - } - - return; - case 0x6A: - if (isCgb()) - ioamhram[0x16A] = data | 0x40; - - return; - case 0x6B: - if (isCgb()) { - const unsigned index = ioamhram[0x16A] & 0x3F; - - display.cgbSpColorChange(index, data, cycleCounter); - - ioamhram[0x16A] = (ioamhram[0x16A] & ~0x3F) | ((index + (ioamhram[0x16A] >> 7)) & 0x3F); - } - - return; - case 0x6C: - if (isCgb()) - ioamhram[0x16C] = data | 0xFE; - - return; - case 0x70: - if (isCgb()) { - cart.setWrambank((data & 0x07) ? (data & 0x07) : 1); - ioamhram[0x170] = data | 0xF8; - } - - return; - case 0x72: - case 0x73: - case 0x74: - if (isCgb()) - break; - - return; - case 0x75: - if (isCgb()) - ioamhram[0x175] = data | 0x8F; - - return; - case 0xFF: - intreq.setIereg(data); - break; - default: - return; - } - - ioamhram[P - 0xFE00] = data; -} - -void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (lastOamDmaUpdate != DISABLED_TIME) { - updateOamDma(cycleCounter); - - if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0) { - ioamhram[oamDmaPos] = data; - return; - } - } - - if (P < 0xFE00) { - if (P < 0xA000) { - if (P < 0x8000) { - cart.mbcWrite(P, data); - } else if (display.vramAccessible(cycleCounter)) { - display.vramChange(cycleCounter); - cart.vrambankptr()[P] = data; - } - } else if (P < 0xC000) { - if (cart.wsrambankptr()) - cart.wsrambankptr()[P] = data; - else - cart.rtcWrite(data); - } else - cart.wramdata(P >> 12 & 1)[P & 0xFFF] = data; - } else if (P - 0xFF80u >= 0x7Fu) { - if (P < 0xFF00) { - if (display.oamWritable(cycleCounter) && oamDmaPos >= 0xA0 && (P < 0xFEA0 || isCgb())) { - display.oamChange(cycleCounter); - ioamhram[P - 0xFE00] = data; - } - } else - nontrivial_ff_write(P, data, cycleCounter); - } else - ioamhram[P - 0xFE00] = data; -} - -int Memory::loadROM(const char *romfiledata, unsigned romfilelength, const bool forceDmg, const bool multicartCompat) { - if (const int fail = cart.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat)) - return fail; - - sound.init(cart.isCgb()); - display.reset(ioamhram, cart.vramdata(), cart.isCgb()); - - return 0; -} - -unsigned Memory::fillSoundBuffer(const unsigned long cycleCounter) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - return sound.fillBuffer(); -} - -void Memory::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32) { - display.setDmgPaletteColor(palNum, colorNum, rgb32); -} - -void Memory::setCgbPalette(unsigned *lut) { - display.setCgbPalette(lut); -} - -bool Memory::getMemoryArea(int which, unsigned char **data, int *length) { - if (!data || !length) - return false; - - switch (which) - { - case 4: // oam - *data = &ioamhram[0]; - *length = 160; - return true; - case 5: // hram - *data = &ioamhram[384]; - *length = 128; - return true; - case 6: // bgpal - *data = (unsigned char *)display.bgPalette(); - *length = 32; - return true; - case 7: // sppal - *data = (unsigned char *)display.spPalette(); - *length = 32; - return true; - default: // pass to cartridge - return cart.getMemoryArea(which, data, length); - } -} - -int Memory::LinkStatus(int which) -{ - switch (which) - { - case 256: // ClockSignaled - return linkClockTrigger; - case 257: // AckClockSignal - linkClockTrigger = false; - return 0; - case 258: // GetOut - return ioamhram[0x101] & 0xff; - case 259: // connect link cable - LINKCABLE = true; - return 0; - default: // ShiftIn - if (ioamhram[0x102] & 0x80) // was enabled - { - ioamhram[0x101] = which; - ioamhram[0x102] &= 0x7F; - intreq.flagIrq(8); - } - return 0; - } - - return -1; -} - + ioamhram[0x14D] = (ioamhram[0x14D] & ~1u) | (data & 1); return; + case 0x4F: + if (isCgb()) { + cart.setVrambank(data & 1); + ioamhram[0x14F] = 0xFE | data; + } + + return; + case 0x50: + // this is the register that turns off the bootrom + // it can only ever be written to once (with 1) once boot rom finishes + cart.bios_remap(data); + return; + case 0x51: + dmaSource = data << 8 | (dmaSource & 0xFF); + return; + case 0x52: + dmaSource = (dmaSource & 0xFF00) | (data & 0xF0); + return; + case 0x53: + dmaDestination = data << 8 | (dmaDestination & 0xFF); + return; + case 0x54: + dmaDestination = (dmaDestination & 0xFF00) | (data & 0xF0); + return; + case 0x55: + if (isCgb()) { + ioamhram[0x155] = data & 0x7F; + + if (display.hdmaIsEnabled()) { + if (!(data & 0x80)) { + ioamhram[0x155] |= 0x80; + display.disableHdma(cycleCounter); + } + } else { + if (data & 0x80) { + if (ioamhram[0x140] & 0x80) { + display.enableHdma(cycleCounter); + } else + flagHdmaReq(&intreq); + } else + flagGdmaReq(&intreq); + } + } + + return; + case 0x56: + if (isCgb()) + ioamhram[0x156] = data | 0x3E; + + return; + case 0x68: + if (isCgb()) + ioamhram[0x168] = data | 0x40; + + return; + case 0x69: + if (isCgb()) { + const unsigned index = ioamhram[0x168] & 0x3F; + + display.cgbBgColorChange(index, data, cycleCounter); + + ioamhram[0x168] = (ioamhram[0x168] & ~0x3F) | ((index + (ioamhram[0x168] >> 7)) & 0x3F); + } + + return; + case 0x6A: + if (isCgb()) + ioamhram[0x16A] = data | 0x40; + + return; + case 0x6B: + if (isCgb()) { + const unsigned index = ioamhram[0x16A] & 0x3F; + + display.cgbSpColorChange(index, data, cycleCounter); + + ioamhram[0x16A] = (ioamhram[0x16A] & ~0x3F) | ((index + (ioamhram[0x16A] >> 7)) & 0x3F); + } + + return; + case 0x6C: + if (isCgb()) + ioamhram[0x16C] = data | 0xFE; + + return; + case 0x70: + if (isCgb()) { + cart.setWrambank((data & 0x07) ? (data & 0x07) : 1); + ioamhram[0x170] = data | 0xF8; + } + + return; + case 0x72: + case 0x73: + case 0x74: + if (isCgb()) + break; + + return; + case 0x75: + if (isCgb()) + ioamhram[0x175] = data | 0x8F; + + return; + case 0xFF: + intreq.setIereg(data); + break; + default: + return; + } + + ioamhram[P - 0xFE00] = data; +} + +void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { + if (lastOamDmaUpdate != DISABLED_TIME) { + updateOamDma(cycleCounter); + + if (isInOamDmaConflictArea(cart.oamDmaSrc(), P, isCgb()) && oamDmaPos < 0xA0) { + ioamhram[oamDmaPos] = data; + return; + } + } + + if (P < 0xFE00) { + if (P < 0xA000) { + if (P < 0x8000) { + cart.mbcWrite(P, data); + } else if (display.vramAccessible(cycleCounter)) { + display.vramChange(cycleCounter); + cart.vrambankptr()[P] = data; + } + } else if (P < 0xC000) { + if (cart.wsrambankptr()) + cart.wsrambankptr()[P] = data; + else + cart.rtcWrite(data); + } else + cart.wramdata(P >> 12 & 1)[P & 0xFFF] = data; + } else if (P - 0xFF80u >= 0x7Fu) { + if (P < 0xFF00) { + if (display.oamWritable(cycleCounter) && oamDmaPos >= 0xA0 && (P < 0xFEA0 || isCgb())) { + display.oamChange(cycleCounter); + ioamhram[P - 0xFE00] = data; + } + } else + nontrivial_ff_write(P, data, cycleCounter); + } else + ioamhram[P - 0xFE00] = data; +} + +int Memory::loadROM(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, const bool forceDmg, const bool multicartCompat) { + if (const int fail = cart.loadROM(romfiledata, romfilelength, biosfiledata, biosfilelength, forceDmg, multicartCompat)) + return fail; + + sound.init(cart.isCgb()); + display.reset(ioamhram, cart.vramdata(), cart.isCgb()); + + return 0; +} + +unsigned Memory::fillSoundBuffer(const unsigned long cycleCounter) { + sound.generate_samples(cycleCounter, isDoubleSpeed()); + return sound.fillBuffer(); +} + +void Memory::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32) { + display.setDmgPaletteColor(palNum, colorNum, rgb32); +} + +void Memory::setCgbPalette(unsigned *lut) { + display.setCgbPalette(lut); +} + +bool Memory::getMemoryArea(int which, unsigned char **data, int *length) { + if (!data || !length) + return false; + + switch (which) + { + case 4: // oam + *data = &ioamhram[0]; + *length = 160; + return true; + case 5: // hram + *data = &ioamhram[384]; + *length = 128; + return true; + case 6: // bgpal + *data = (unsigned char *)display.bgPalette(); + *length = 32; + return true; + case 7: // sppal + *data = (unsigned char *)display.spPalette(); + *length = 32; + return true; + default: // pass to cartridge + return cart.getMemoryArea(which, data, length); + } +} + +int Memory::LinkStatus(int which) +{ + switch (which) + { + case 256: // ClockSignaled + return linkClockTrigger; + case 257: // AckClockSignal + linkClockTrigger = false; + return 0; + case 258: // GetOut + return ioamhram[0x101] & 0xff; + case 259: // connect link cable + LINKCABLE = true; + return 0; + default: // ShiftIn + if (ioamhram[0x102] & 0x80) // was enabled + { + ioamhram[0x101] = which; + ioamhram[0x102] &= 0x7F; + intreq.flagIrq(8); + } + return 0; + } + + return -1; +} + SYNCFUNC(Memory) { SSS(cart); @@ -1107,5 +1112,5 @@ SYNCFUNC(Memory) NSS(LINKCABLE); NSS(linkClockTrigger); } - -} + +} diff --git a/libgambatte/src/memory.h b/libgambatte/src/memory.h index bbf9e89c6d..78a89a0ee4 100644 --- a/libgambatte/src/memory.h +++ b/libgambatte/src/memory.h @@ -1,293 +1,297 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * 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 version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MEMORY_H -#define MEMORY_H - -#include "mem/cartridge.h" -#include "video.h" -#include "sound.h" -#include "interrupter.h" -#include "tima.h" +/*************************************************************************** + * Copyright (C) 2007 by Sindre Aamås * + * aamas@stud.ntnu.no * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2 as * + * published by the Free Software Foundation. * + * * + * 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 version 2 for more details. * + * * + * You should have received a copy of the GNU General Public License * + * version 2 along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef MEMORY_H +#define MEMORY_H + +#include "mem/cartridge.h" +#include "video.h" +#include "sound.h" +#include "interrupter.h" +#include "tima.h" #include "newstate.h" #include "gambatte.h" - -namespace gambatte { -class InputGetter; -class FilterInfo; - -class Memory { - Cartridge cart; - unsigned char ioamhram[0x200]; - - void (*readCallback)(unsigned); - void (*writeCallback)(unsigned); - void (*execCallback)(unsigned); - CDCallback cdCallback; - - unsigned (*getInput)(); - unsigned long divLastUpdate; - unsigned long lastOamDmaUpdate; - - InterruptRequester intreq; - Tima tima; - LCD display; - PSG sound; - Interrupter interrupter; - - unsigned short dmaSource; - unsigned short dmaDestination; - unsigned char oamDmaPos; - unsigned char serialCnt; - bool blanklcd; - - bool LINKCABLE; - bool linkClockTrigger; - - void decEventCycles(MemEventId eventId, unsigned long dec); - - void oamDmaInitSetup(); - void updateOamDma(unsigned long cycleCounter); - void startOamDma(unsigned long cycleCounter); - void endOamDma(unsigned long cycleCounter); - const unsigned char * oamDmaSrcPtr() const; - - unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter); - unsigned nontrivial_read(unsigned P, unsigned long cycleCounter); - void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter); - void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter); - - unsigned nontrivial_peek(unsigned P); - unsigned nontrivial_ff_peek(unsigned P); - - void updateSerial(unsigned long cc); - void updateTimaIrq(unsigned long cc); - void updateIrqs(unsigned long cc); - - bool isDoubleSpeed() const { return display.isDoubleSpeed(); } - -public: - explicit Memory(const Interrupter &interrupter); - - bool loaded() const { return cart.loaded(); } - const char * romTitle() const { return cart.romTitle(); } - - int debugGetLY() const { return display.debugGetLY(); } - - void setStatePtrs(SaveState &state); - void loadState(const SaveState &state/*, unsigned long oldCc*/); - void loadSavedata(const char *data) { cart.loadSavedata(data); } - int saveSavedataLength() {return cart.saveSavedataLength(); } - void saveSavedata(char *dest) { cart.saveSavedata(dest); } - void updateInput(); - - bool getMemoryArea(int which, unsigned char **data, int *length); // { return cart.getMemoryArea(which, data, length); } - - unsigned long stop(unsigned long cycleCounter); - bool isCgb() const { return display.isCgb(); } - bool ime() const { return intreq.ime(); } - bool halted() const { return intreq.halted(); } - unsigned long nextEventTime() const { return intreq.minEventTime(); } - - void setLayers(unsigned mask) { display.setLayers(mask); } - - bool isActive() const { return intreq.eventTime(END) != DISABLED_TIME; } - - long cyclesSinceBlit(const unsigned long cc) const { - return cc < intreq.eventTime(BLIT) ? -1 : static_cast((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed()); - } - - void halt() { intreq.halt(); } - void ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } } - - void di() { intreq.di(); } - - unsigned ff_read(const unsigned P, const unsigned long cycleCounter) { - return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00]; - } - - struct CDMapResult - { - eCDLog_AddrType type; - unsigned addr; - }; - - CDMapResult CDMap(const unsigned P) const - { - if(P<0x4000) - { - CDMapResult ret = { eCDLog_AddrType_ROM, P }; - return ret; - } - else if(P<0x8000) - { - unsigned bank = cart.rmem(P>>12) - cart.rmem(0); - unsigned addr = P+bank; - CDMapResult ret = { eCDLog_AddrType_ROM, addr }; - return ret; - } - else if(P<0xA000) {} - else if(P<0xC000) - { - if(cart.wsrambankptr()) - { - //not bankable. but. we're not sure how much might be here - unsigned char *data; - int length; - bool has = cart.getMemoryArea(3,&data,&length); - unsigned addr = P&(length-1); - if(has && length!=0) - { - CDMapResult ret = { eCDLog_AddrType_CartRAM, addr }; - return ret; - } - } - } - else if(P<0xE000) - { - unsigned bank = cart.wramdata(P >> 12 & 1) - cart.wramdata(0); - unsigned addr = (P&0xFFF)+bank; - CDMapResult ret = { eCDLog_AddrType_WRAM, addr }; - return ret; - } - else if(P<0xFF80) {} - else - { - ////this is just for debugging, really, it's pretty useless - //CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) }; - //return ret; - } - - CDMapResult ret = { eCDLog_AddrType_None }; - return ret; - } - - - unsigned read(const unsigned P, const unsigned long cycleCounter) { - if (readCallback) - readCallback(P); - if(cdCallback) - { - CDMapResult map = CDMap(P); - if(map.type != eCDLog_AddrType_None) - cdCallback(map.addr,map.type,eCDLog_Flags_Data); - } - return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter); - } - - unsigned read_excb(const unsigned P, const unsigned long cycleCounter, bool first) { - if (execCallback) - execCallback(P); - if(cdCallback) - { - CDMapResult map = CDMap(P); - if(map.type != eCDLog_AddrType_None) - cdCallback(map.addr,map.type,first?eCDLog_Flags_ExecFirst : eCDLog_Flags_ExecOperand); - } - return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter); - } - - unsigned peek(const unsigned P) { - return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_peek(P); - } - - void write_nocb(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (cart.wmem(P >> 12)) { - cart.wmem(P >> 12)[P] = data; - } else - nontrivial_write(P, data, cycleCounter); - } - - void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (cart.wmem(P >> 12)) { - cart.wmem(P >> 12)[P] = data; - } else - nontrivial_write(P, data, cycleCounter); - if (writeCallback) - writeCallback(P); - if(cdCallback) - { - CDMapResult map = CDMap(P); - if(map.type != eCDLog_AddrType_None) - cdCallback(map.addr,map.type,eCDLog_Flags_Data); - } - } - - void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (P - 0xFF80u < 0x7Fu) { - ioamhram[P - 0xFE00] = data; - } else - nontrivial_ff_write(P, data, cycleCounter); - if(cdCallback) - { - CDMapResult map = CDMap(P); - if(map.type != eCDLog_AddrType_None) - cdCallback(map.addr,map.type,eCDLog_Flags_Data); - } - } - - unsigned long event(unsigned long cycleCounter); - unsigned long resetCounters(unsigned long cycleCounter); - - int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat); - - void setInputGetter(unsigned (*getInput)()) { - this->getInput = getInput; - } - - void setReadCallback(void (*callback)(unsigned)) { - this->readCallback = callback; - } - void setWriteCallback(void (*callback)(unsigned)) { - this->writeCallback = callback; - } - void setExecCallback(void (*callback)(unsigned)) { - this->execCallback = callback; - } - void setCDCallback(CDCallback cdc) { - this->cdCallback = cdc; - } - - void setScanlineCallback(void (*callback)(), int sl) { - display.setScanlineCallback(callback, sl); - } - - void setRTCCallback(std::uint32_t (*callback)()) { - cart.setRTCCallback(callback); - } - - void setEndtime(unsigned long cc, unsigned long inc); - - void setSoundBuffer(uint_least32_t *const buf) { sound.setBuffer(buf); } - unsigned fillSoundBuffer(unsigned long cc); - - void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { - display.setVideoBuffer(videoBuf, pitch); - } - - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32); - void setCgbPalette(unsigned *lut); - - int LinkStatus(int which); - + +namespace gambatte { +class InputGetter; +class FilterInfo; + +class Memory { + Cartridge cart; + unsigned char ioamhram[0x200]; + + void (*readCallback)(unsigned); + void (*writeCallback)(unsigned); + void (*execCallback)(unsigned); + CDCallback cdCallback; + + unsigned (*getInput)(); + unsigned long divLastUpdate; + unsigned long lastOamDmaUpdate; + + InterruptRequester intreq; + Tima tima; + LCD display; + PSG sound; + Interrupter interrupter; + + unsigned short dmaSource; + unsigned short dmaDestination; + unsigned char oamDmaPos; + unsigned char serialCnt; + bool blanklcd; + + bool LINKCABLE; + bool linkClockTrigger; + + void decEventCycles(MemEventId eventId, unsigned long dec); + + void oamDmaInitSetup(); + void updateOamDma(unsigned long cycleCounter); + void startOamDma(unsigned long cycleCounter); + void endOamDma(unsigned long cycleCounter); + const unsigned char * oamDmaSrcPtr() const; + + unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter); + unsigned nontrivial_read(unsigned P, unsigned long cycleCounter); + void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter); + void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter); + + unsigned nontrivial_peek(unsigned P); + unsigned nontrivial_ff_peek(unsigned P); + + void updateSerial(unsigned long cc); + void updateTimaIrq(unsigned long cc); + void updateIrqs(unsigned long cc); + + bool isDoubleSpeed() const { return display.isDoubleSpeed(); } + +public: + explicit Memory(const Interrupter &interrupter); + + bool loaded() const { return cart.loaded(); } + const char * romTitle() const { return cart.romTitle(); } + + void bios_reset(int setting) { + nontrivial_ff_write(0x50, setting, 0); + } + + int debugGetLY() const { return display.debugGetLY(); } + + void setStatePtrs(SaveState &state); + void loadState(const SaveState &state/*, unsigned long oldCc*/); + void loadSavedata(const char *data) { cart.loadSavedata(data); } + int saveSavedataLength() {return cart.saveSavedataLength(); } + void saveSavedata(char *dest) { cart.saveSavedata(dest); } + void updateInput(); + + bool getMemoryArea(int which, unsigned char **data, int *length); // { return cart.getMemoryArea(which, data, length); } + + unsigned long stop(unsigned long cycleCounter); + bool isCgb() const { return display.isCgb(); } + bool ime() const { return intreq.ime(); } + bool halted() const { return intreq.halted(); } + unsigned long nextEventTime() const { return intreq.minEventTime(); } + + void setLayers(unsigned mask) { display.setLayers(mask); } + + bool isActive() const { return intreq.eventTime(END) != DISABLED_TIME; } + + long cyclesSinceBlit(const unsigned long cc) const { + return cc < intreq.eventTime(BLIT) ? -1 : static_cast((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed()); + } + + void halt() { intreq.halt(); } + void ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } } + + void di() { intreq.di(); } + + unsigned ff_read(const unsigned P, const unsigned long cycleCounter) { + return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00]; + } + + struct CDMapResult + { + eCDLog_AddrType type; + unsigned addr; + }; + + CDMapResult CDMap(const unsigned P) const + { + if(P<0x4000) + { + CDMapResult ret = { eCDLog_AddrType_ROM, P }; + return ret; + } + else if(P<0x8000) + { + unsigned bank = cart.rmem(P>>12) - cart.rmem(0); + unsigned addr = P+bank; + CDMapResult ret = { eCDLog_AddrType_ROM, addr }; + return ret; + } + else if(P<0xA000) {} + else if(P<0xC000) + { + if(cart.wsrambankptr()) + { + //not bankable. but. we're not sure how much might be here + unsigned char *data; + int length; + bool has = cart.getMemoryArea(3,&data,&length); + unsigned addr = P&(length-1); + if(has && length!=0) + { + CDMapResult ret = { eCDLog_AddrType_CartRAM, addr }; + return ret; + } + } + } + else if(P<0xE000) + { + unsigned bank = cart.wramdata(P >> 12 & 1) - cart.wramdata(0); + unsigned addr = (P&0xFFF)+bank; + CDMapResult ret = { eCDLog_AddrType_WRAM, addr }; + return ret; + } + else if(P<0xFF80) {} + else + { + ////this is just for debugging, really, it's pretty useless + //CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) }; + //return ret; + } + + CDMapResult ret = { eCDLog_AddrType_None }; + return ret; + } + + + unsigned read(const unsigned P, const unsigned long cycleCounter) { + if (readCallback) + readCallback(P); + if(cdCallback) + { + CDMapResult map = CDMap(P); + if(map.type != eCDLog_AddrType_None) + cdCallback(map.addr,map.type,eCDLog_Flags_Data); + } + return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter); + } + + unsigned read_excb(const unsigned P, const unsigned long cycleCounter, bool first) { + if (execCallback) + execCallback(P); + if(cdCallback) + { + CDMapResult map = CDMap(P); + if(map.type != eCDLog_AddrType_None) + cdCallback(map.addr,map.type,first?eCDLog_Flags_ExecFirst : eCDLog_Flags_ExecOperand); + } + return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter); + } + + unsigned peek(const unsigned P) { + return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_peek(P); + } + + void write_nocb(const unsigned P, const unsigned data, const unsigned long cycleCounter) { + if (cart.wmem(P >> 12)) { + cart.wmem(P >> 12)[P] = data; + } else + nontrivial_write(P, data, cycleCounter); + } + + void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { + if (cart.wmem(P >> 12)) { + cart.wmem(P >> 12)[P] = data; + } else + nontrivial_write(P, data, cycleCounter); + if (writeCallback) + writeCallback(P); + if(cdCallback) + { + CDMapResult map = CDMap(P); + if(map.type != eCDLog_AddrType_None) + cdCallback(map.addr,map.type,eCDLog_Flags_Data); + } + } + + void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { + if (P - 0xFF80u < 0x7Fu) { + ioamhram[P - 0xFE00] = data; + } else + nontrivial_ff_write(P, data, cycleCounter); + if(cdCallback) + { + CDMapResult map = CDMap(P); + if(map.type != eCDLog_AddrType_None) + cdCallback(map.addr,map.type,eCDLog_Flags_Data); + } + } + + unsigned long event(unsigned long cycleCounter); + unsigned long resetCounters(unsigned long cycleCounter); + + int loadROM(const char *romfiledata, unsigned romfilelength, const char *biosfiledata, unsigned biosfilelength, bool forceDmg, bool multicartCompat); + + void setInputGetter(unsigned (*getInput)()) { + this->getInput = getInput; + } + + void setReadCallback(void (*callback)(unsigned)) { + this->readCallback = callback; + } + void setWriteCallback(void (*callback)(unsigned)) { + this->writeCallback = callback; + } + void setExecCallback(void (*callback)(unsigned)) { + this->execCallback = callback; + } + void setCDCallback(CDCallback cdc) { + this->cdCallback = cdc; + } + + void setScanlineCallback(void (*callback)(), int sl) { + display.setScanlineCallback(callback, sl); + } + + void setRTCCallback(std::uint32_t (*callback)()) { + cart.setRTCCallback(callback); + } + + void setEndtime(unsigned long cc, unsigned long inc); + + void setSoundBuffer(uint_least32_t *const buf) { sound.setBuffer(buf); } + unsigned fillSoundBuffer(unsigned long cc); + + void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { + display.setVideoBuffer(videoBuf, pitch); + } + + void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32); + void setCgbPalette(unsigned *lut); + + int LinkStatus(int which); + templatevoid SyncState(NewState *ns); -}; - -} - -#endif +}; + +} + +#endif diff --git a/libgambatte/src/savestate.h b/libgambatte/src/savestate.h index 4110161ca0..e0726764aa 100644 --- a/libgambatte/src/savestate.h +++ b/libgambatte/src/savestate.h @@ -38,7 +38,7 @@ struct SaveState { void set(T *ptr, const unsigned long sz) { this->ptr = ptr; this->sz = sz; } friend class SaverList; - friend void setInitState(SaveState &, bool, bool, std::uint32_t); + friend void setInitState(SaveState &, bool, bool, std::uint32_t, bool); }; struct CPU { From 68f46c580a3e11b8a009c05a90af72ae26453dff Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 12:57:55 -0400 Subject: [PATCH 04/12] Add files via upload --- libgambatte/libgambatte.vcxproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libgambatte/libgambatte.vcxproj b/libgambatte/libgambatte.vcxproj index 2f3aaa552c..4d34da2828 100644 --- a/libgambatte/libgambatte.vcxproj +++ b/libgambatte/libgambatte.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -28,23 +28,27 @@ DynamicLibrary true Unicode + v140 DynamicLibrary true Unicode + v140 DynamicLibrary false true Unicode + v140 DynamicLibrary false true Unicode + v140 From 0ce16cf727bceb163de5dacc46ad0f2f97fd4427 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 13:00:02 -0400 Subject: [PATCH 05/12] Add files via upload --- output/dll/libgambatte.dll | Bin 169984 -> 186880 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index 87284591fdaab29443906841700ecf77d36fb297..e709cf470f18e6df4441b6d737b9e8364a48e778 100644 GIT binary patch literal 186880 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 z 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%0DhP>j^MU+X;ukc%2kIhL(~af7{6VbR5AWbx@=b? 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 literal 169984 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 Y&)%N?o_#$7yu1Cs@P9q Date: Sat, 24 Jun 2017 13:02:44 -0400 Subject: [PATCH 06/12] Update FirmwareDatabase.cs --- BizHawk.Emulation.Common/Database/FirmwareDatabase.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs b/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs index fc48c80b9d..af3d781483 100644 --- a/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs +++ b/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs @@ -205,6 +205,9 @@ namespace BizHawk.Emulation.Common FirmwareAndOption("b2e1955d957a475de2411770452eff4ea19f4cee", 1024, "O2", "BIOS", "Odyssey2.bin", "Odyssey 2 Bios"); FirmwareAndOption("a6120aed50831c9c0d95dbdf707820f601d9452e", 1024, "O2", "BIOS-C52", "PhillipsC52.bin", "Phillips C52 Bios"); + + FirmwareAndOption("4ED31EC6B0B175BB109C0EB5FD3D193DA823339F", 256, "GB", "World", "GB_boot_ROM.gb", "Game Boy BIOS"); + FirmwareAndOption("1293D68BF9643BC4F36954C1E80E38F39864528D", 2304, "GBC", "World", "GBC_boot_ROM.gb", "Game Boy Color BIOS"); } // adds a defined firmware ID to the database @@ -336,4 +339,4 @@ namespace BizHawk.Emulation.Common return found.FirstOrDefault(); } } // static class FirmwareDatabase -} \ No newline at end of file +} From 627b666d3e6fed9234322c7e75937224ba2e11de Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 13:05:00 -0400 Subject: [PATCH 07/12] Add files via upload --- .../Nintendo/Gameboy/Gambatte.IEmulator.cs | 3 ++ .../Nintendo/Gameboy/Gambatte.ISettable.cs | 5 +++ .../Consoles/Nintendo/Gameboy/Gambatte.cs | 31 ++++++++++++++++++- .../Consoles/Nintendo/Gameboy/LibGambatte.cs | 2 +- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs index b13d7e4dc8..38c11b0234 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IEmulator.cs @@ -95,8 +95,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { if (GambatteState != IntPtr.Zero) { + Console.WriteLine("disposing"); LibGambatte.gambatte_destroy(GambatteState); + Console.WriteLine("step2"); GambatteState = IntPtr.Zero; + Console.WriteLine("disposed"); } DisposeSound(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs index f6cf22c4f1..d25557a7e4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs @@ -80,6 +80,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public class GambatteSyncSettings { + [DisplayName("Use System BIOS")] + [Description("Boots game using system BIOS. Should be used for TASing")] + [DefaultValue(false)] + public bool EnableBIOS { get; set; } + [DisplayName("Force DMG Mode")] [Description("Force the game to run on DMG hardware, even if it's detected as a CGB game. Relevant for games that are \"CGB Enhanced\" but do not require CGB.")] [DefaultValue(false)] diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index e2e3f6b4ea..8f6554632f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -52,6 +52,23 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy throw new InvalidOperationException("gambatte_create() returned null???"); } + Console.WriteLine(game.System); + + byte[] BiosRom; + + if (game.System == "GB") + { + BiosRom = new byte[256]; + BiosRom = comm.CoreFileProvider.GetFirmware("GB", "World", false); + } + else + { + BiosRom = new byte[2304]; + BiosRom = comm.CoreFileProvider.GetFirmware("GBC", "World", false); + } + + int bios_length = BiosRom == null ? 0 : BiosRom.Length; + try { _syncSettings = (GambatteSyncSettings)syncSettings ?? new GambatteSyncSettings(); @@ -63,6 +80,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy LibGambatte.LoadFlags flags = 0; + if (_syncSettings.EnableBIOS && BiosRom == null) + { + Console.WriteLine("Warning: BIOS not found, loading without BIOS"); + bios_length = 0; + } + + // to disable BIOS loading into gambatte, just set bios_length to 0 + if (!_syncSettings.EnableBIOS) + { + bios_length = 0; + } + if (_syncSettings.ForceDMG) { flags |= LibGambatte.LoadFlags.FORCE_DMG; @@ -78,7 +107,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy flags |= LibGambatte.LoadFlags.MULTICART_COMPAT; } - if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, GetCurrentTime(), flags) != 0) + if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, BiosRom, (uint)bios_length, GetCurrentTime(), flags) != 0) { throw new InvalidOperationException("gambatte_load() returned non-zero (is this not a gb or gbc rom?)"); } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs index 86b7e4fffd..06aaa58fa6 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibGambatte.cs @@ -57,7 +57,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy /// ORed combination of LoadFlags. /// 0 on success, negative value on failure. [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, long now, LoadFlags flags); + public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, byte[] biosdata, uint bioslength, long now, LoadFlags flags); ///

/// Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer, From c60763484d69bbf0913dbc5f3a99fee40536946c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 15:58:51 -0400 Subject: [PATCH 08/12] Add files via upload --- output/dll/libgambatte.dll | Bin 186880 -> 187904 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index e709cf470f18e6df4441b6d737b9e8364a48e778..ecd8fa7bbb83a7f18178aa00066dc403a6eddd6e 100644 GIT binary patch delta 76525 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
np!a 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 From b54a738c97e921773cb79f3992675b56b81cc3e5 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 16:01:07 -0400 Subject: [PATCH 09/12] Add files via upload --- .../Nintendo/Gameboy/Gambatte.ISettable.cs | 2 +- .../Consoles/Nintendo/Gameboy/Gambatte.cs | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs index d25557a7e4..f213b6cdb1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.ISettable.cs @@ -80,7 +80,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public class GambatteSyncSettings { - [DisplayName("Use System BIOS")] + [DisplayName("Enable BIOS: WARNING: File must exist!")] [Description("Boots game using system BIOS. Should be used for TASing")] [DefaultValue(false)] public bool EnableBIOS { get; set; } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index 8f6554632f..d7e3812de6 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -80,10 +80,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy LibGambatte.LoadFlags flags = 0; + if (_syncSettings.ForceDMG) + { + flags |= LibGambatte.LoadFlags.FORCE_DMG; + + // we need to change the BIOS to GB bios + if (game.System == "GBC") + { + BiosRom = null; + BiosRom = new byte[256]; + BiosRom = comm.CoreFileProvider.GetFirmware("GB", "World", false); + } + } + if (_syncSettings.EnableBIOS && BiosRom == null) { - Console.WriteLine("Warning: BIOS not found, loading without BIOS"); - bios_length = 0; + throw new MissingFirmwareException("Boot Rom not found"); } // to disable BIOS loading into gambatte, just set bios_length to 0 @@ -92,11 +104,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy bios_length = 0; } - if (_syncSettings.ForceDMG) - { - flags |= LibGambatte.LoadFlags.FORCE_DMG; - } - if (_syncSettings.GBACGB) { flags |= LibGambatte.LoadFlags.GBA_CGB; From 4bae91b4f59ffc4b7a6a1c7a0b881f0562f39692 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 16:02:50 -0400 Subject: [PATCH 11/12] Add files via upload --- libgambatte/src/mem/cartridge.cpp | 19 +++++++++++++++++-- libgambatte/src/mem/cartridge.h | 1 + libgambatte/src/mem/memptrs.cpp | 11 +++++++++-- libgambatte/src/mem/memptrs.h | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/libgambatte/src/mem/cartridge.cpp b/libgambatte/src/mem/cartridge.cpp index 7539be22bf..4117c86f54 100644 --- a/libgambatte/src/mem/cartridge.cpp +++ b/libgambatte/src/mem/cartridge.cpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace gambatte { @@ -500,11 +501,15 @@ void Cartridge::setStatePtrs(SaveState &state) { state.mem.vram.set(memptrs.vramdata(), memptrs.vramdataend() - memptrs.vramdata()); state.mem.sram.set(memptrs.rambankdata(), memptrs.rambankdataend() - memptrs.rambankdata()); state.mem.wram.set(memptrs.wramdata(0), memptrs.wramdataend() - memptrs.wramdata(0)); + } void Cartridge::loadState(const SaveState &state) { rtc.loadState(state); mbc->loadState(state.mem); + //if (state.mem.using_bios) { + // bios_remap(0); + //} } static void enforce8bit(unsigned char *data, unsigned long sz) { @@ -528,11 +533,13 @@ void Cartridge::bios_remap(int setting) { // disable the BIOS if writing 1 or 0x22 (GBC) if (setting == 1 || setting == 0x11) { std::memcpy(memptrs.romdata(), memptrs.notbiosdata_, loc_bios_length); + using_bios = false; } // we'll also use it to reset to BIOS on reset if (setting == 0) { std::memcpy(memptrs.romdata(), memptrs.biosdata_, loc_bios_length); + using_bios = true; } } @@ -633,7 +640,7 @@ int Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, const ch std::printf("rambanks: %u\n", rambanks); const std::size_t filesize = romfilelength; //rom->size(); - rombanks = std::fmax(pow2ceil(filesize / 0x4000), 2u); + rombanks = std::max(pow2ceil(filesize / 0x4000), 2u); std::printf("rombanks: %u\n", static_cast(filesize / 0x4000)); mbc.reset(); @@ -653,9 +660,12 @@ int Cartridge::loadROM(const char *romfiledata, unsigned romfilelength, const ch //we want to copy in the bios data only if it exists if (use_bios) { + using_bios = true; + memptrs.use_bios = true; + memptrs.biosdata_ = new unsigned char[biosfilelength]; memptrs.notbiosdata_ = new unsigned char[biosfilelength]; - + std::memcpy(memptrs.biosdata_, biosfiledata, biosfilelength); std::memcpy(memptrs.notbiosdata_, romfiledata, biosfilelength); @@ -778,6 +788,11 @@ SYNCFUNC(Cartridge) SSS(memptrs); SSS(rtc); TSS(mbc); + NSS(using_bios); + + if (using_bios) { + bios_remap(0); + } } } diff --git a/libgambatte/src/mem/cartridge.h b/libgambatte/src/mem/cartridge.h index 51c73d1ece..c3a3d7ce27 100644 --- a/libgambatte/src/mem/cartridge.h +++ b/libgambatte/src/mem/cartridge.h @@ -68,6 +68,7 @@ public: void loadState(const SaveState &); bool use_bios; + bool using_bios; unsigned loc_bios_length; bool loaded() const { return mbc.get(); } diff --git a/libgambatte/src/mem/memptrs.cpp b/libgambatte/src/mem/memptrs.cpp index 425b9b4e61..4ddf5e0149 100644 --- a/libgambatte/src/mem/memptrs.cpp +++ b/libgambatte/src/mem/memptrs.cpp @@ -31,12 +31,15 @@ MemPtrs::MemPtrs() MemPtrs::~MemPtrs() { delete []memchunk_; + if (use_bios) + { + delete[]biosdata_; + delete[]notbiosdata_; + } } void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) { delete []memchunk_; - delete []biosdata_; - delete []notbiosdata_; memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000; memchunk_ = new unsigned char[memchunk_len]; @@ -223,6 +226,10 @@ SYNCFUNC(MemPtrs) MSS(rambankdata_); MSS(wramdataend_); NSS(oamDmaSrc_); + + NSS(biosdata_); + NSS(notbiosdata_); + NSS(use_bios); } } diff --git a/libgambatte/src/mem/memptrs.h b/libgambatte/src/mem/memptrs.h index ec63dd4a8b..3c63670907 100644 --- a/libgambatte/src/mem/memptrs.h +++ b/libgambatte/src/mem/memptrs.h @@ -53,6 +53,7 @@ class MemPtrs { public: unsigned char *biosdata_; unsigned char *notbiosdata_; + bool use_bios; enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 }; From 70900cfadbb835be4c571b891545569934e5a62f Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 24 Jun 2017 16:03:55 -0400 Subject: [PATCH 12/12] Add files via upload --- libgambatte/src/gambatte.cpp | 4 +--- libgambatte/src/initstate.cpp | 2 +- libgambatte/src/savestate.h | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index 9a4fa62bf2..c3843a862c 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -98,10 +98,7 @@ void GB::reset(const std::uint32_t now) { { p_->cpu.reset_bios(0); } - else - { - } setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode, now, use_bios); p_->cpu.loadState(state); if (length > 0) @@ -237,6 +234,7 @@ SYNCFUNC(GB) SSS(p_->cpu); NSS(p_->gbaCgbMode); NSS(p_->vbuff); + NSS(use_bios); } } diff --git a/libgambatte/src/initstate.cpp b/libgambatte/src/initstate.cpp index e2e1892a76..307a7f460c 100644 --- a/libgambatte/src/initstate.cpp +++ b/libgambatte/src/initstate.cpp @@ -1182,7 +1182,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM state.cpu.cycleCounter = 0; state.mem.ioamhram.ptr[0x140] = 0x00; state.mem.ioamhram.ptr[0x104] = 0x00; - + state.mem.using_bios = true; } else { diff --git a/libgambatte/src/savestate.h b/libgambatte/src/savestate.h index e0726764aa..be3f21322a 100644 --- a/libgambatte/src/savestate.h +++ b/libgambatte/src/savestate.h @@ -78,6 +78,7 @@ struct SaveState { bool enableRam; bool rambankMode; bool hdmaTransfer; + bool using_bios; } mem; struct PPU {