Refactor cartridge code

This commit is contained in:
MrWint 2019-05-26 12:06:40 +02:00
parent 839c8abf54
commit a79febdef9
10 changed files with 761 additions and 728 deletions

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef GAMBATTE_H
#define GAMBATTE_H
@ -23,11 +23,10 @@
#include "loadres.h"
#include <cstddef>
#include <string>
#include <sstream>
#include <cstdint>
#include "newstate.h"
namespace gambatte {
enum { BG_PALETTE = 0, SP1_PALETTE = 1, SP2_PALETTE = 2 };
typedef void (*MemoryCallback)(int32_t address, int64_t cycleOffset);
@ -57,9 +56,11 @@ public:
MULTICART_COMPAT = 4, /**< Use heuristics to detect and support some multicart MBCs disguised as MBC1. */
};
/** Load ROM image.
/**
* Load ROM image.
*
* @param romfile Path to rom image file. Typically a .gbc, .gb, or .zip-file (if zip-support is compiled in).
* @param romfile Path to rom image file. Typically a .gbc, .gb, or .zip-file (if
* zip-support is compiled in).
* @param flags ORed combination of LoadFlags.
* @return 0 on success, negative value on failure.
*/
@ -68,24 +69,33 @@ public:
int loadGBCBios(const char* biosfiledata);
int loadDMGBios(const char* biosfiledata);
/** Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer,
* or until a video frame has been drawn.
/**
* Emulates until at least 'samples' audio samples are produced in the
* supplied audio buffer, or until a video frame has been drawn.
*
* There are 35112 stereo sound samples in a video frame.
* May run for up to 2064 stereo samples too long.
* A stereo sample consists of two native endian 2s complement 16-bit PCM samples,
* with the left sample preceding the right one. Usually casting soundBuf to/from
* short* is OK and recommended. The reason for not using a short* in the interface
* is to avoid implementation-defined behaviour without compromising performance.
* There are 35112 audio (stereo) samples in a video frame.
* May run for up to 2064 audio samples too long.
*
* An audio sample consists of two native endian 2s complement 16-bit PCM samples,
* with the left sample preceding the right one. Usually casting audioBuf to
* int16_t* is OK. The reason for using an uint_least32_t* in the interface is to
* avoid implementation-defined behavior without compromising performance.
* libgambatte is strictly c++98, so fixed-width types are not an option (and even
* c99/c++11 cannot guarantee their availability).
*
* Returns early when a new video frame has finished drawing in the video buffer,
* such that the caller may update the video output before the frame is overwritten.
* The return value indicates whether a new video frame has been drawn, and the
* exact time (in number of samples) at which it was drawn.
* exact time (in number of samples) at which it was completed.
*
* @param soundBuf buffer with space >= samples + 2064
* @param samples in: number of stereo samples to produce, out: actual number of samples produced
* @return sample number at which the video frame was produced. -1 means no frame was produced.
* @param videoBuf 160x144 RGB32 (native endian) video frame buffer or 0
* @param pitch distance in number of pixels (not bytes) from the start of one line
* to the next in videoBuf.
* @param audioBuf buffer with space >= samples + 2064
* @param samples in: number of stereo samples to produce,
* out: actual number of samples produced
* @return sample offset in audioBuf at which the video frame was completed, or -1
* if no new video frame was completed.
*/
std::ptrdiff_t runFor(gambatte::uint_least32_t *soundBuf, std::size_t &samples);
@ -93,12 +103,14 @@ public:
void setLayers(unsigned mask);
/** Reset to initial state.
/**
* Reset to initial state.
* Equivalent to reloading a ROM image, or turning a Game Boy Color off and on again.
*/
void reset(std::uint32_t now, unsigned div);
/** @param palNum 0 <= palNum < 3. One of BG_PALETTE, SP1_PALETTE and SP2_PALETTE.
/**
* @param palNum 0 <= palNum < 3. One of BG_PALETTE, SP1_PALETTE and SP2_PALETTE.
* @param colorNum 0 <= colorNum < 4
*/
void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32);
@ -150,8 +162,8 @@ private:
struct Priv;
Priv *const p_;
GB(const GB &);
GB & operator=(const GB &);
GB(GB const &);
GB & operator=(GB const &);
};
}

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef GAMBATTE_INT_H
#define GAMBATTE_INT_H

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007-2010 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef CARTRIDGE_H
#define CARTRIDGE_H
@ -30,26 +30,12 @@
namespace gambatte {
//DOOM
//enum eAddressMappingType
//{
// eAddressMappingType_ROM,
// eAddressMappingType_RAM
//};
//
//struct AddressMapping
//{
// int32_t address;
// eAddressMappingType type;
//};
class Mbc {
public:
virtual ~Mbc() {}
virtual void romWrite(unsigned P, unsigned data) = 0;
virtual void loadState(const SaveState::Mem &ss) = 0;
virtual void loadState(SaveState::Mem const &ss) = 0;
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned address, unsigned rombank) const = 0;
//virtual void mapAddress(AddressMapping* mapping, unsigned address) const = 0; //DOOM
template<bool isReader>void SyncState(NewState *ns)
{
@ -60,52 +46,45 @@ public:
};
class Cartridge {
MemPtrs memptrs;
Rtc rtc;
std::unique_ptr<Mbc> mbc;
public:
void setStatePtrs(SaveState &);
void loadState(const SaveState &);
bool loaded() const { return mbc.get(); }
const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); }
unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); }
unsigned char * vramdata() const { return memptrs.vramdata(); }
unsigned char * romdata(unsigned area) const { return memptrs.romdata(area); }
unsigned char * wramdata(unsigned area) const { return memptrs.wramdata(area); }
const unsigned char * rdisabledRam() const { return memptrs.rdisabledRam(); }
const unsigned char * rsrambankptr() const { return memptrs.rsrambankptr(); }
unsigned char * wsrambankptr() const { return memptrs.wsrambankptr(); }
unsigned char * vrambankptr() const { return memptrs.vrambankptr(); }
OamDmaSrc oamDmaSrc() const { return memptrs.oamDmaSrc(); }
unsigned curRomBank() const { return memptrs.curRomBank(); }
void setVrambank(unsigned bank) { memptrs.setVrambank(bank); }
void setWrambank(unsigned bank) { memptrs.setWrambank(bank); }
void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); }
void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); }
bool isCgb() const { return gambatte::isCgb(memptrs); }
void rtcWrite(unsigned data) { rtc.write(data); }
unsigned char rtcRead() const { return *rtc.getActive(); }
void loadSavedata(const char *data);
void loadState(SaveState const &);
bool loaded() const { return mbc_.get(); }
unsigned char const * rmem(unsigned area) const { return memptrs_.rmem(area); }
unsigned char * wmem(unsigned area) const { return memptrs_.wmem(area); }
unsigned char * vramdata() const { return memptrs_.vramdata(); }
unsigned char * romdata(unsigned area) const { return memptrs_.romdata(area); }
unsigned char * wramdata(unsigned area) const { return memptrs_.wramdata(area); }
unsigned char const * rdisabledRam() const { return memptrs_.rdisabledRam(); }
unsigned char const * rsrambankptr() const { return memptrs_.rsrambankptr(); }
unsigned char * wsrambankptr() const { return memptrs_.wsrambankptr(); }
unsigned char * vrambankptr() const { return memptrs_.vrambankptr(); }
OamDmaSrc oamDmaSrc() const { return memptrs_.oamDmaSrc(); }
void setVrambank(unsigned bank) { memptrs_.setVrambank(bank); }
void setWrambank(unsigned bank) { memptrs_.setWrambank(bank); }
void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs_.setOamDmaSrc(oamDmaSrc); }
unsigned curRomBank() const { return memptrs_.curRomBank(); }
void mbcWrite(unsigned addr, unsigned data) { mbc_->romWrite(addr, data); }
bool isCgb() const { return gambatte::isCgb(memptrs_); }
void rtcWrite(unsigned data) { rtc_.write(data); }
unsigned char rtcRead() const { return *rtc_.activeData(); }
void loadSavedata(char const *data);
int saveSavedataLength();
void saveSavedata(char *dest);
bool getMemoryArea(int which, unsigned char **data, int *length) const;
LoadRes loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
const char * romTitle() const { return reinterpret_cast<const char *>(memptrs.romdata() + 0x134); }
LoadRes loadROM(char const *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
char const * romTitle() const { return reinterpret_cast<char const *>(memptrs_.romdata() + 0x134); }
void setRTCCallback(std::uint32_t (*callback)()) {
rtc.setRTCCallback(callback);
rtc_.setRTCCallback(callback);
}
private:
MemPtrs memptrs_;
Rtc rtc_;
std::unique_ptr<Mbc> mbc_;
public:
template<bool isReader>void SyncState(NewState *ns);
};

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007-2010 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "memptrs.h"
#include <algorithm>
#include <cstring>
@ -23,10 +23,19 @@
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),
curRomBank_(1),
memchunk_len(0)
: rmem_()
, wmem_()
, romdata_()
, wramdata_()
, vrambankptr_(0)
, rsrambankptr_(0)
, wsrambankptr_(0)
, memchunk_(0)
, rambankdata_(0)
, wramdataend_(0)
, oamDmaSrc_(oam_dma_src_off)
, curRomBank_(1)
, memchunk_len(0)
{
}
@ -34,7 +43,7 @@ MemPtrs::~MemPtrs() {
delete []memchunk_;
}
void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) {
void MemPtrs::reset(unsigned const rombanks, unsigned const rambanks, unsigned const wrambanks) {
delete []memchunk_;
memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000;
memchunk_ = new unsigned char[memchunk_len];
@ -46,7 +55,7 @@ void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsi
std::memset(rdisabledRamw(), 0xFF, 0x2000);
oamDmaSrc_ = OAM_DMA_SRC_OFF;
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;
@ -60,39 +69,43 @@ void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsi
memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs;
}
void MemPtrs::setRombank0(const unsigned bank) {
void MemPtrs::setRombank0(unsigned bank) {
romdata_[0] = romdata() + bank * 0x4000ul;
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
disconnectOamDmaAreas();
}
void MemPtrs::setRombank(const unsigned bank) {
void MemPtrs::setRombank(unsigned bank) {
curRomBank_ = 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);
void MemPtrs::setRambank(unsigned const flags, unsigned const rambank) {
unsigned char *srambankptr = 0;
if (!(flags & rtc_en)) {
srambankptr = 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;
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) {
void MemPtrs::setWrambank(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) {
void MemPtrs::setOamDmaSrc(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_;
@ -108,37 +121,37 @@ void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) {
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:
case oam_dma_src_rom: // fall through
case oam_dma_src_sram:
case oam_dma_src_invalid:
std::fill(rmem_, rmem_ + 8, static_cast<unsigned char *>(0));
rmem_[0xB] = rmem_[0xA] = 0;
wmem_[0xB] = wmem_[0xA] = 0;
break;
case OAM_DMA_SRC_VRAM:
case oam_dma_src_vram:
break;
case OAM_DMA_SRC_WRAM:
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:
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:
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<unsigned char *>(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:
case oam_dma_src_vram:
break;
case OAM_DMA_SRC_OFF:
case oam_dma_src_off:
break;
}
}

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007-2010 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef MEMPTRS_H
#define MEMPTRS_H
@ -23,43 +23,22 @@
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 };
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_;
unsigned curRomBank_;
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 };
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 const * 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_; }
@ -70,8 +49,8 @@ public:
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 const * rdisabledRam() const { return rdisabledRamw(); }
unsigned char const * rsrambankptr() const { return rsrambankptr_; }
unsigned char * wsrambankptr() const { return wsrambankptr_; }
unsigned char * vrambankptr() const { return vrambankptr_; }
OamDmaSrc oamDmaSrc() const { return oamDmaSrc_; }
@ -84,10 +63,36 @@ public:
void setWrambank(unsigned bank);
void setOamDmaSrc(OamDmaSrc oamDmaSrc);
private:
unsigned char const *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_;
unsigned curRomBank_;
int memchunk_len;
int memchunk_saveoffs;
int memchunk_savelen;
MemPtrs(MemPtrs const &);
MemPtrs & operator=(MemPtrs const &);
void disconnectOamDmaAreas();
unsigned char * rdisabledRamw() const { return wramdataend_ ; }
unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; }
public:
template<bool isReader>void SyncState(NewState *ns);
};
inline bool isCgb(const MemPtrs &memptrs) {
inline bool isCgb(MemPtrs const &memptrs) {
return memptrs.wramdataend() - memptrs.wramdata(0) == 0x8000;
}

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "rtc.h"
#include "../savestate.h"
#include <cstdlib>
@ -23,155 +23,154 @@
namespace gambatte {
Rtc::Rtc()
: activeData(NULL),
activeSet(NULL),
baseTime(0),
haltTime(0),
index(5),
dataDh(0),
dataDl(0),
dataH(0),
dataM(0),
dataS(0),
enabled(false),
lastLatchData(false),
timeCB(0)
: activeData_(0)
, activeSet_(0)
, baseTime_(0)
, haltTime_(0)
, index_(5)
, dataDh_(0)
, dataDl_(0)
, dataH_(0)
, dataM_(0)
, dataS_(0)
, enabled_(false)
, lastLatchData_(false)
, timeCB(0)
{
}
void Rtc::doLatch() {
std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime;
std::uint32_t tmp = ((dataDh_ & 0x40) ? haltTime_ : timeCB()) - baseTime_;
while (tmp > 0x1FF * 86400) {
baseTime += 0x1FF * 86400;
baseTime_ += 0x1FF * 86400;
tmp -= 0x1FF * 86400;
dataDh |= 0x80;
dataDh_ |= 0x80;
}
dataDl = (tmp / 86400) & 0xFF;
dataDh &= 0xFE;
dataDh |= ((tmp / 86400) & 0x100) >> 8;
dataDl_ = (tmp / 86400) & 0xFF;
dataDh_ &= 0xFE;
dataDh_ |= ((tmp / 86400) & 0x100) >> 8;
tmp %= 86400;
dataH = tmp / 3600;
dataH_ = tmp / 3600;
tmp %= 3600;
dataM = tmp / 60;
dataM_ = tmp / 60;
tmp %= 60;
dataS = tmp;
dataS_ = tmp;
}
void Rtc::doSwapActive() {
if (!enabled || index > 4) {
activeData = NULL;
activeSet = NULL;
} else switch (index) {
if (!enabled_ || index_ > 4) {
activeData_ = 0;
activeSet_ = 0;
} else switch (index_) {
case 0x00:
activeData = &dataS;
activeSet = &Rtc::setS;
activeData_ = &dataS_;
activeSet_ = &Rtc::setS;
break;
case 0x01:
activeData = &dataM;
activeSet = &Rtc::setM;
activeData_ = &dataM_;
activeSet_ = &Rtc::setM;
break;
case 0x02:
activeData = &dataH;
activeSet = &Rtc::setH;
activeData_ = &dataH_;
activeSet_ = &Rtc::setH;
break;
case 0x03:
activeData = &dataDl;
activeSet = &Rtc::setDl;
activeData_ = &dataDl_;
activeSet_ = &Rtc::setDl;
break;
case 0x04:
activeData = &dataDh;
activeSet = &Rtc::setDh;
activeData_ = &dataDh_;
activeSet_ = &Rtc::setDh;
break;
}
}
void Rtc::loadState(const SaveState &state) {
baseTime = state.rtc.baseTime;
haltTime = state.rtc.haltTime;
dataDh = state.rtc.dataDh;
dataDl = state.rtc.dataDl;
dataH = state.rtc.dataH;
dataM = state.rtc.dataM;
dataS = state.rtc.dataS;
lastLatchData = state.rtc.lastLatchData;
void Rtc::loadState(SaveState const &state) {
baseTime_ = state.rtc.baseTime;
haltTime_ = state.rtc.haltTime;
dataDh_ = state.rtc.dataDh;
dataDl_ = state.rtc.dataDl;
dataH_ = state.rtc.dataH;
dataM_ = state.rtc.dataM;
dataS_ = state.rtc.dataS;
lastLatchData_ = state.rtc.lastLatchData;
doSwapActive();
}
void Rtc::setDh(const unsigned new_dh) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100;
baseTime += old_highdays * 86400;
baseTime -= ((new_dh & 0x1) << 8) * 86400;
void Rtc::setDh(unsigned const newDh) {
const std::uint32_t unixtime = (dataDh_ & 0x40) ? haltTime_ : timeCB();
const std::uint32_t oldHighdays = ((unixtime - baseTime_) / 86400) & 0x100;
baseTime_ += oldHighdays * 86400;
baseTime_ -= ((newDh & 0x1) << 8) * 86400;
if ((dataDh ^ new_dh) & 0x40) {
if (new_dh & 0x40)
haltTime = timeCB();
if ((dataDh_ ^ newDh) & 0x40) {
if (newDh & 0x40)
haltTime_ = timeCB();
else
baseTime += timeCB() - haltTime;
baseTime_ += timeCB() - haltTime_;
}
}
void Rtc::setDl(const unsigned new_lowdays) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF;
baseTime += old_lowdays * 86400;
baseTime -= new_lowdays * 86400;
void Rtc::setDl(unsigned const newLowdays) {
const std::uint32_t unixtime = (dataDh_ & 0x40) ? haltTime_ : timeCB();
const std::uint32_t oldLowdays = ((unixtime - baseTime_) / 86400) & 0xFF;
baseTime_ += oldLowdays * 86400;
baseTime_ -= newLowdays * 86400;
}
void Rtc::setH(const unsigned new_hours) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_hours = ((unixtime - baseTime) / 3600) % 24;
baseTime += old_hours * 3600;
baseTime -= new_hours * 3600;
void Rtc::setH(unsigned const newHours) {
const std::uint32_t unixtime = (dataDh_ & 0x40) ? haltTime_ : timeCB();
const std::uint32_t oldHours = ((unixtime - baseTime_) / 3600) % 24;
baseTime_ += oldHours * 3600;
baseTime_ -= newHours * 3600;
}
void Rtc::setM(const unsigned new_minutes) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_minutes = ((unixtime - baseTime) / 60) % 60;
baseTime += old_minutes * 60;
baseTime -= new_minutes * 60;
void Rtc::setM(unsigned const newMinutes) {
const std::uint32_t unixtime = (dataDh_ & 0x40) ? haltTime_ : timeCB();
const std::uint32_t oldMinutes = ((unixtime - baseTime_) / 60) % 60;
baseTime_ += oldMinutes * 60;
baseTime_ -= newMinutes * 60;
}
void Rtc::setS(const unsigned new_seconds) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
baseTime += (unixtime - baseTime) % 60;
baseTime -= new_seconds;
void Rtc::setS(unsigned const newSeconds) {
const std::uint32_t unixtime = (dataDh_ & 0x40) ? haltTime_ : timeCB();
baseTime_ += (unixtime - baseTime_) % 60;
baseTime_ -= newSeconds;
}
SYNCFUNC(Rtc)
{
EBS(activeData, 0);
EVS(activeData, &dataS, 1);
EVS(activeData, &dataM, 2);
EVS(activeData, &dataH, 3);
EVS(activeData, &dataDl, 4);
EVS(activeData, &dataDh, 5);
EES(activeData, NULL);
EBS(activeData_, 0);
EVS(activeData_, &dataS_, 1);
EVS(activeData_, &dataM_, 2);
EVS(activeData_, &dataH_, 3);
EVS(activeData_, &dataDl_, 4);
EVS(activeData_, &dataDh_, 5);
EES(activeData_, NULL);
EBS(activeSet, 0);
EVS(activeSet, &Rtc::setS, 1);
EVS(activeSet, &Rtc::setM, 2);
EVS(activeSet, &Rtc::setH, 3);
EVS(activeSet, &Rtc::setDl, 4);
EVS(activeSet, &Rtc::setDh, 5);
EES(activeSet, NULL);
EBS(activeSet_, 0);
EVS(activeSet_, &Rtc::setS, 1);
EVS(activeSet_, &Rtc::setM, 2);
EVS(activeSet_, &Rtc::setH, 3);
EVS(activeSet_, &Rtc::setDl, 4);
EVS(activeSet_, &Rtc::setDh, 5);
EES(activeSet_, NULL);
NSS(baseTime);
NSS(haltTime);
NSS(index);
NSS(dataDh);
NSS(dataDl);
NSS(dataH);
NSS(dataM);
NSS(dataS);
NSS(enabled);
NSS(lastLatchData);
NSS(baseTime_);
NSS(haltTime_);
NSS(index_);
NSS(dataDh_);
NSS(dataDl_);
NSS(dataH_);
NSS(dataM_);
NSS(dataS_);
NSS(enabled_);
NSS(lastLatchData_);
}
}

View File

@ -1,21 +1,21 @@
/***************************************************************************
* 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. *
***************************************************************************/
//
// Copyright (C) 2007 by sinamas <sinamas at users.sourceforge.net>
//
// 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.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef RTC_H
#define RTC_H
@ -27,69 +27,67 @@ namespace gambatte {
struct SaveState;
class Rtc {
private:
unsigned char *activeData;
void (Rtc::*activeSet)(unsigned);
std::uint32_t baseTime;
std::uint32_t haltTime;
unsigned char index;
unsigned char dataDh;
unsigned char dataDl;
unsigned char dataH;
unsigned char dataM;
unsigned char dataS;
bool enabled;
bool lastLatchData;
std::uint32_t (*timeCB)();
void doLatch();
void doSwapActive();
void setDh(unsigned new_dh);
void setDl(unsigned new_lowdays);
void setH(unsigned new_hours);
void setM(unsigned new_minutes);
void setS(unsigned new_seconds);
public:
Rtc();
const unsigned char* getActive() const { return activeData; }
std::uint32_t getBaseTime() const { return baseTime; }
unsigned char const * activeData() const { return activeData_; }
std::uint32_t getBaseTime() const { return baseTime_; }
void setBaseTime(const std::uint32_t baseTime) {
this->baseTime = baseTime;
// doLatch();
this->baseTime_ = baseTime;
}
void latch(const unsigned data) {
if (!lastLatchData && data == 1)
void latch(unsigned data) {
if (!lastLatchData_ && data == 1)
doLatch();
lastLatchData = data;
lastLatchData_ = data;
}
void loadState(const SaveState &state);
void loadState(SaveState const &state);
void set(const bool enabled, unsigned bank) {
void set(bool enabled, unsigned bank) {
bank &= 0xF;
bank -= 8;
this->enabled = enabled;
this->index = bank;
enabled_ = enabled;
index_ = bank;
doSwapActive();
}
void write(const unsigned data) {
// if (activeSet)
(this->*activeSet)(data);
*activeData = data;
void write(unsigned data) {
(this->*activeSet_)(data);
*activeData_ = data;
}
void setRTCCallback(std::uint32_t (*callback)()) {
timeCB = callback;
}
private:
unsigned char *activeData_;
void (Rtc::*activeSet_)(unsigned);
std::uint32_t baseTime_;
std::uint32_t haltTime_;
unsigned char index_;
unsigned char dataDh_;
unsigned char dataDl_;
unsigned char dataH_;
unsigned char dataM_;
unsigned char dataS_;
bool enabled_;
bool lastLatchData_;
std::uint32_t (*timeCB)();
void doLatch();
void doSwapActive();
void setDh(unsigned newDh);
void setDl(unsigned newLowdays);
void setH(unsigned newHours);
void setM(unsigned newMinutes);
void setS(unsigned newSeconds);
public:
template<bool isReader>void SyncState(NewState *ns);
};

View File

@ -85,7 +85,7 @@ void Memory::loadState(const SaveState &state) {
: 8;
cart.setVrambank(ioamhram[0x14F] & isCgb());
cart.setOamDmaSrc(OAM_DMA_SRC_OFF);
cart.setOamDmaSrc(oam_dma_src_off);
cart.setWrambank(isCgb() && (ioamhram[0x170] & 0x07) ? ioamhram[0x170] & 0x07 : 1);
if (lastOamDmaUpdate != disabled_time) {
@ -432,11 +432,11 @@ void Memory::updateOamDma(const unsigned long cycleCounter) {
void Memory::oamDmaInitSetup() {
if (ioamhram[0x146] < 0xA0) {
cart.setOamDmaSrc(ioamhram[0x146] < 0x80 ? OAM_DMA_SRC_ROM : OAM_DMA_SRC_VRAM);
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);
cart.setOamDmaSrc(ioamhram[0x146] < 0xC0 ? oam_dma_src_sram : oam_dma_src_wram);
} else
cart.setOamDmaSrc(OAM_DMA_SRC_INVALID);
cart.setOamDmaSrc(oam_dma_src_invalid);
}
static const unsigned char * oamDmaSrcZero() {
@ -446,12 +446,12 @@ static const unsigned char * oamDmaSrcZero() {
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;
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();
@ -463,7 +463,7 @@ void Memory::startOamDma(const unsigned long cycleCounter) {
void Memory::endOamDma(const unsigned long cycleCounter) {
oamDmaPos = 0xFE;
cart.setOamDmaSrc(OAM_DMA_SRC_OFF);
cart.setOamDmaSrc(oam_dma_src_off);
display.oamChange(ioamhram, cycleCounter);
}

Binary file not shown.