Ports from Upstream GSR for Babs and Robopon (squashed #2091)
This commit is contained in:
parent
89789b4358
commit
81628bf109
|
@ -167,6 +167,7 @@
|
|||
<ClInclude Include="src\interruptrequester.h" />
|
||||
<ClInclude Include="src\memory.h" />
|
||||
<ClInclude Include="src\mem\cartridge.h" />
|
||||
<ClInclude Include="src\mem\huc3.h" />
|
||||
<ClInclude Include="src\mem\memptrs.h" />
|
||||
<ClInclude Include="src\mem\rtc.h" />
|
||||
<ClInclude Include="src\mem\time.h" />
|
||||
|
@ -204,6 +205,7 @@
|
|||
<ClCompile Include="src\interruptrequester.cpp" />
|
||||
<ClCompile Include="src\memory.cpp" />
|
||||
<ClCompile Include="src\mem\cartridge.cpp" />
|
||||
<ClCompile Include="src\mem\huc3.cpp" />
|
||||
<ClCompile Include="src\mem\memptrs.cpp" />
|
||||
<ClCompile Include="src\mem\rtc.cpp" />
|
||||
<ClCompile Include="src\mem\time.cpp" />
|
||||
|
|
|
@ -135,6 +135,9 @@
|
|||
<ClInclude Include="src\video\lcddef.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\mem\huc3.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\cinterface.cpp">
|
||||
|
@ -218,5 +221,8 @@
|
|||
<ClCompile Include="src\Interrupter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\mem\huc3.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1330,4 +1330,12 @@ void gambatte::setInitState(SaveState &state, const bool cgb) {
|
|||
state.rtc.dataM = 0;
|
||||
state.rtc.dataS = 0;
|
||||
state.rtc.lastLatchData = false;
|
||||
|
||||
state.huc3.haltTime = state.time.seconds;
|
||||
state.huc3.dataTime = 0;
|
||||
state.huc3.writingTime = 0;
|
||||
state.huc3.halted = false;
|
||||
state.huc3.shift = 0;
|
||||
state.huc3.ramValue = 1;
|
||||
state.huc3.modeflag = 2; // huc3_none
|
||||
}
|
||||
|
|
|
@ -437,6 +437,95 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class HuC3 : public DefaultMbc {
|
||||
public:
|
||||
HuC3(MemPtrs& memptrs, HuC3Chip* const huc3)
|
||||
: memptrs_(memptrs)
|
||||
, huc3_(huc3)
|
||||
, rombank_(1)
|
||||
, rambank_(0)
|
||||
, ramflag_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual unsigned char curRomBank() const {
|
||||
return rombank_;
|
||||
}
|
||||
|
||||
virtual bool disabledRam() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void romWrite(unsigned const p, unsigned const data, unsigned long const /*cc*/) {
|
||||
switch (p >> 13 & 3) {
|
||||
case 0:
|
||||
ramflag_ = data;
|
||||
//printf("[HuC3] set ramflag to %02X\n", data);
|
||||
setRambank();
|
||||
break;
|
||||
case 1:
|
||||
//printf("[HuC3] set rombank to %02X\n", data);
|
||||
rombank_ = data;
|
||||
setRombank();
|
||||
break;
|
||||
case 2:
|
||||
//printf("[HuC3] set rambank to %02X\n", data);
|
||||
rambank_ = data;
|
||||
setRambank();
|
||||
break;
|
||||
case 3:
|
||||
// GEST: "programs will write 1 here"
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SyncState(NewState *ns, bool isReader)
|
||||
{
|
||||
NSS(rombank_);
|
||||
NSS(rambank_);
|
||||
NSS(ramflag_);
|
||||
}
|
||||
|
||||
virtual void loadState(SaveState::Mem const& ss) {
|
||||
rombank_ = ss.rombank;
|
||||
rambank_ = ss.rambank;
|
||||
ramflag_ = ss.HuC3RAMflag;
|
||||
setRambank();
|
||||
setRombank();
|
||||
}
|
||||
|
||||
private:
|
||||
MemPtrs& memptrs_;
|
||||
HuC3Chip* const huc3_;
|
||||
unsigned char rombank_;
|
||||
unsigned char rambank_;
|
||||
unsigned char ramflag_;
|
||||
|
||||
void setRambank() const {
|
||||
huc3_->setRamflag(ramflag_);
|
||||
|
||||
unsigned flags;
|
||||
if (ramflag_ >= 0x0B && ramflag_ < 0x0F) {
|
||||
// System registers mode
|
||||
flags = MemPtrs::read_en | MemPtrs::write_en | MemPtrs::rtc_en;
|
||||
}
|
||||
else if (ramflag_ == 0x0A || ramflag_ > 0x0D) {
|
||||
// Read/write mode
|
||||
flags = MemPtrs::read_en | MemPtrs::write_en;
|
||||
}
|
||||
else {
|
||||
// Read-only mode ??
|
||||
flags = MemPtrs::read_en;
|
||||
}
|
||||
|
||||
memptrs_.setRambank(flags, rambank_ & (rambanks(memptrs_) - 1));
|
||||
}
|
||||
|
||||
void setRombank() const {
|
||||
memptrs_.setRombank(std::max(rombank_ & (rombanks(memptrs_) - 1), 1u));
|
||||
}
|
||||
};
|
||||
|
||||
class Mbc5 : public DefaultMbc {
|
||||
public:
|
||||
explicit Mbc5(MemPtrs &memptrs)
|
||||
|
@ -578,6 +667,7 @@ int asHex(char c) {
|
|||
|
||||
Cartridge::Cartridge()
|
||||
: rtc_(time_)
|
||||
, huc3_(time_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -588,7 +678,9 @@ void Cartridge::setStatePtrs(SaveState &state) {
|
|||
}
|
||||
|
||||
void Cartridge::loadState(SaveState const &state) {
|
||||
huc3_.loadState(state);
|
||||
rtc_.loadState(state);
|
||||
time_.loadState(state);
|
||||
mbc_->loadState(state.mem);
|
||||
}
|
||||
|
||||
|
@ -613,7 +705,8 @@ LoadRes Cartridge::loadROM(char const *romfiledata, unsigned romfilelength, bool
|
|||
type_mbc2,
|
||||
type_mbc3,
|
||||
type_mbc5,
|
||||
type_huc1 };
|
||||
type_huc1,
|
||||
type_huc3 };
|
||||
Cartridgetype type = type_plain;
|
||||
unsigned rambanks = 1;
|
||||
unsigned rombanks = 2;
|
||||
|
@ -656,7 +749,7 @@ LoadRes Cartridge::loadROM(char const *romfiledata, unsigned romfilelength, bool
|
|||
case 0x22: return LOADRES_UNSUPPORTED_MBC_MBC7;
|
||||
case 0xFC: return LOADRES_UNSUPPORTED_MBC_POCKET_CAMERA;
|
||||
case 0xFD: return LOADRES_UNSUPPORTED_MBC_TAMA5;
|
||||
case 0xFE: return LOADRES_UNSUPPORTED_MBC_HUC3;
|
||||
case 0xFE: type = type_huc3; break;
|
||||
case 0xFF: type = type_huc1; break;
|
||||
default: return LOADRES_BAD_FILE_OR_UNKNOWN_MBC;
|
||||
}
|
||||
|
@ -686,6 +779,7 @@ LoadRes Cartridge::loadROM(char const *romfiledata, unsigned romfilelength, bool
|
|||
mbc_.reset();
|
||||
memptrs_.reset(rombanks, rambanks, cgb ? 8 : 2);
|
||||
rtc_.set(false, 0);
|
||||
huc3_.set(false);
|
||||
|
||||
std::memcpy(memptrs_.romdata(), romfiledata, (filesize / rombank_size() * rombank_size()));
|
||||
std::memset(memptrs_.romdata() + filesize / rombank_size() * rombank_size(),
|
||||
|
@ -708,6 +802,10 @@ LoadRes Cartridge::loadROM(char const *romfiledata, unsigned romfilelength, bool
|
|||
break;
|
||||
case type_mbc5: mbc_.reset(new Mbc5(memptrs_)); break;
|
||||
case type_huc1: mbc_.reset(new HuC1(memptrs_)); break;
|
||||
case type_huc3:
|
||||
huc3_.set(true);
|
||||
mbc_.reset(new HuC3(memptrs_, &huc3_));
|
||||
break;
|
||||
}
|
||||
|
||||
return LOADRES_OK;
|
||||
|
@ -798,6 +896,7 @@ bool Cartridge::getMemoryArea(int which, unsigned char **data, int *length) cons
|
|||
|
||||
SYNCFUNC(Cartridge)
|
||||
{
|
||||
SSS(huc3_);
|
||||
SSS(memptrs_);
|
||||
SSS(time_);
|
||||
SSS(rtc_);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "memptrs.h"
|
||||
#include "time.h"
|
||||
#include "rtc.h"
|
||||
#include "huc3.h"
|
||||
#include "savestate.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -82,11 +83,15 @@ public:
|
|||
bool getMemoryArea(int which, unsigned char **data, int *length) const;
|
||||
LoadRes loadROM(char const *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
|
||||
char const * romTitle() const { return reinterpret_cast<char const *>(memptrs_.romdata() + 0x134); }
|
||||
bool isHuC3() const { return huc3_.isHuC3(); }
|
||||
unsigned char HuC3Read(unsigned p, unsigned long const cc) { return huc3_.read(p, cc); }
|
||||
void HuC3Write(unsigned p, unsigned data, unsigned long const cc) { huc3_.write(p, data, cc); }
|
||||
|
||||
private:
|
||||
MemPtrs memptrs_;
|
||||
Time time_;
|
||||
Rtc rtc_;
|
||||
HuC3Chip huc3_;
|
||||
std::unique_ptr<Mbc> mbc_;
|
||||
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
//
|
||||
// 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 "huc3.h"
|
||||
#include "../savestate.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
HuC3Chip::HuC3Chip(Time &time)
|
||||
: time_(time)
|
||||
, haltTime_(0)
|
||||
, dataTime_(0)
|
||||
, writingTime_(0)
|
||||
, ramValue_(0)
|
||||
, shift_(0)
|
||||
, ramflag_(0)
|
||||
, modeflag_(HUC3_NONE)
|
||||
, irBaseCycle_(0)
|
||||
, enabled_(false)
|
||||
, lastLatchData_(false)
|
||||
, halted_(false)
|
||||
, irReceivingPulse_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void HuC3Chip::doLatch(unsigned long const cc) {
|
||||
std::uint32_t tmp = time(cc);
|
||||
|
||||
unsigned minute = (tmp / 60) % 1440;
|
||||
unsigned day = (tmp / 86400) & 0xFFF;
|
||||
dataTime_ = (day << 12) | minute;
|
||||
}
|
||||
|
||||
//void HuC3Chip::setStatePtrs(SaveState &state) {
|
||||
// state.huc3.haltTime.set(haltTime_, sizeof haltTime_);
|
||||
// state.huc3.dataTime.set(dataTime_, sizeof dataTime_);
|
||||
// state.huc3.writingTime.set(writingTime_, sizeof writingTime_);
|
||||
// state.huc3.irBaseCycle.set(irBaseCycle_, sizeof irBaseCycle_);
|
||||
// state.huc3.halted.set(halted_, sizeof halted_);
|
||||
// state.huc3.shift.set(shift_, sizeof shift_);
|
||||
// state.huc3.ramValue.set(ramValue_, sizeof ramValue_);
|
||||
// state.huc3.modeflag.set(modeflag_, sizeof modeflag_);
|
||||
// state.huc3.irReceivingPulse.set(irReceivingPulse_, sizeof irReceivingPulse_);
|
||||
//}
|
||||
|
||||
void HuC3Chip::loadState(SaveState const &state) {
|
||||
haltTime_ = state.huc3.haltTime;
|
||||
dataTime_ = state.huc3.dataTime;
|
||||
ramValue_ = state.huc3.ramValue;
|
||||
shift_ = state.huc3.shift;
|
||||
halted_ = state.huc3.halted;
|
||||
modeflag_ = state.huc3.modeflag;
|
||||
writingTime_ = state.huc3.writingTime;
|
||||
irBaseCycle_ = state.huc3.irBaseCycle;
|
||||
irReceivingPulse_ = state.huc3.irReceivingPulse;
|
||||
}
|
||||
|
||||
unsigned char HuC3Chip::read(unsigned /*p*/, unsigned long const cc) {
|
||||
// should only reach here with ramflag = 0B-0E
|
||||
if(ramflag_ == 0x0E) {
|
||||
// INFRARED
|
||||
if(!irReceivingPulse_) {
|
||||
irReceivingPulse_ = true;
|
||||
irBaseCycle_ = cc;
|
||||
}
|
||||
unsigned long cyclesSinceStart = cc - irBaseCycle_;
|
||||
unsigned char modulation = (cyclesSinceStart/105) & 1; // 4194304 Hz CPU, 40000 Hz remote signal
|
||||
unsigned long timeUs = cyclesSinceStart*36/151; // actually *1000000/4194304
|
||||
// sony protocol
|
||||
if(timeUs < 10000) {
|
||||
// initialization allowance
|
||||
return 0;
|
||||
}
|
||||
else if(timeUs < 10000 + 2400) {
|
||||
// initial mark
|
||||
return modulation;
|
||||
}
|
||||
else if(timeUs < 10000 + 2400 + 600) {
|
||||
// initial space
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// send data
|
||||
timeUs -= 13000;
|
||||
// write 20 bits (any 20 seem to do)
|
||||
unsigned int data = 0xFFFFF;
|
||||
for(unsigned long mask = 1UL << (20-1); mask; mask >>= 1) {
|
||||
unsigned int markTime = (data & mask) ? 1200 : 600;
|
||||
if(timeUs < markTime) { return modulation; }
|
||||
timeUs -= markTime;
|
||||
if(timeUs < 600) { return 0; }
|
||||
timeUs -= 600;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(ramflag_ < 0x0B || ramflag_ > 0x0D) {
|
||||
//printf("[HuC3] error, hit huc3 read with ramflag=%02X\n", ramflag_);
|
||||
return 0xFF;
|
||||
}
|
||||
if(ramflag_ == 0x0D) return 1;
|
||||
else return ramValue_;
|
||||
}
|
||||
|
||||
void HuC3Chip::write(unsigned /*p*/, unsigned data, unsigned long const cc) {
|
||||
// as above
|
||||
if(ramflag_ == 0x0B) {
|
||||
// command
|
||||
switch(data & 0xF0) {
|
||||
case 0x10:
|
||||
// read time
|
||||
doLatch(cc);
|
||||
if(modeflag_ == HUC3_READ) {
|
||||
ramValue_ = (dataTime_ >> shift_) & 0x0F;
|
||||
shift_ += 4;
|
||||
if(shift_ > 24) shift_ = 0;
|
||||
}
|
||||
break;
|
||||
case 0x30:
|
||||
// write time
|
||||
if(modeflag_ == HUC3_WRITE) {
|
||||
if(shift_ == 0) writingTime_ = 0;
|
||||
if(shift_ < 24) {
|
||||
writingTime_ |= (data & 0x0F) << shift_;
|
||||
shift_ += 4;
|
||||
if(shift_ == 24) {
|
||||
updateTime(cc);
|
||||
modeflag_ = HUC3_READ;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
// some kind of mode shift
|
||||
switch(data & 0x0F) {
|
||||
case 0x0:
|
||||
// shift reset?
|
||||
shift_ = 0;
|
||||
break;
|
||||
case 0x3:
|
||||
// write time?
|
||||
modeflag_ = HUC3_WRITE;
|
||||
shift_ = 0;
|
||||
break;
|
||||
case 0x7:
|
||||
modeflag_ = HUC3_READ;
|
||||
shift_ = 0;
|
||||
break;
|
||||
// others are unimplemented so far
|
||||
}
|
||||
break;
|
||||
case 0x50:
|
||||
// ???
|
||||
break;
|
||||
case 0x60:
|
||||
modeflag_ = HUC3_READ; // ???
|
||||
break;
|
||||
}
|
||||
}
|
||||
// do nothing for 0C/0D yet
|
||||
}
|
||||
|
||||
void HuC3Chip::updateTime(unsigned long const cc) {
|
||||
unsigned minute = (writingTime_ & 0xFFF) % 1440;
|
||||
unsigned day = (writingTime_ & 0xFFF000) >> 12;
|
||||
std::uint32_t seconds = minute*60 + day*86400;
|
||||
time_.reset(seconds, cc);
|
||||
haltTime_ = seconds;
|
||||
|
||||
}
|
||||
SYNCFUNC(HuC3Chip)
|
||||
{
|
||||
NSS(haltTime_);
|
||||
NSS(dataTime_);
|
||||
NSS(writingTime_);
|
||||
NSS(ramValue_);
|
||||
NSS(shift_);
|
||||
NSS(halted_);
|
||||
NSS(modeflag_);
|
||||
NSS(irBaseCycle_);
|
||||
NSS(irReceivingPulse_);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// 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 HuC3Chip_H
|
||||
#define HuC3Chip_H
|
||||
|
||||
enum
|
||||
{
|
||||
HUC3_READ = 0,
|
||||
HUC3_WRITE = 1,
|
||||
HUC3_NONE = 2
|
||||
};
|
||||
|
||||
#include "time.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
struct SaveState;
|
||||
|
||||
class HuC3Chip {
|
||||
public:
|
||||
HuC3Chip(Time &time);
|
||||
//void setStatePtrs(SaveState &);
|
||||
void loadState(SaveState const& state);
|
||||
void setRamflag(unsigned char ramflag) { ramflag_ = ramflag; irReceivingPulse_ = false; }
|
||||
bool isHuC3() const { return enabled_; }
|
||||
|
||||
void set(bool enabled) {
|
||||
enabled_ = enabled;
|
||||
}
|
||||
|
||||
unsigned char read(unsigned p, unsigned long const cc);
|
||||
void write(unsigned p, unsigned data, unsigned long cycleCounter);
|
||||
|
||||
private:
|
||||
Time &time_;
|
||||
std::uint32_t haltTime_;
|
||||
unsigned dataTime_;
|
||||
unsigned writingTime_;
|
||||
unsigned char ramValue_;
|
||||
unsigned char shift_;
|
||||
unsigned char ramflag_;
|
||||
unsigned char modeflag_;
|
||||
unsigned long irBaseCycle_;
|
||||
bool enabled_;
|
||||
bool lastLatchData_;
|
||||
bool halted_;
|
||||
bool irReceivingPulse_;
|
||||
|
||||
void doLatch(unsigned long cycleCounter);
|
||||
void updateTime(unsigned long cycleCounter);
|
||||
|
||||
std::uint32_t time(unsigned long const cc) {
|
||||
return halted_ ? haltTime_ : time_.get(cc);
|
||||
}
|
||||
public:
|
||||
template<bool isReader>void SyncState(NewState* ns);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -514,7 +514,9 @@ void Memory::updateOamDma(unsigned long const cc) {
|
|||
startOamDma(lastOamDmaUpdate_);
|
||||
|
||||
if (oamDmaPos_ < oam_size) {
|
||||
ioamhram_[oamDmaPos_] = ((oamDmaSrc) ? oamDmaSrc[oamDmaPos_] : cart_.rtcRead());
|
||||
if (oamDmaSrc) ioamhram_[oamDmaPos_] = oamDmaSrc[oamDmaPos_];
|
||||
else if (cart_.isHuC3()) ioamhram_[oamDmaPos_] = cart_.HuC3Read(oamDmaPos_, cc);
|
||||
else ioamhram_[oamDmaPos_] = cart_.rtcRead();
|
||||
}
|
||||
else if (oamDmaPos_ == oam_size) {
|
||||
endOamDma(lastOamDmaUpdate_);
|
||||
|
@ -667,6 +669,9 @@ unsigned Memory::nontrivial_read(unsigned const p, unsigned long const cc) {
|
|||
if (cart_.rsrambankptr())
|
||||
return cart_.rsrambankptr()[p];
|
||||
|
||||
if (cart_.isHuC3())
|
||||
return cart_.HuC3Read(p, cc);
|
||||
|
||||
return cart_.rtcRead();
|
||||
}
|
||||
|
||||
|
@ -1200,6 +1205,8 @@ void Memory::nontrivial_write(unsigned const p, unsigned const data, unsigned lo
|
|||
else if (p < mm_wram_begin) {
|
||||
if (cart_.wsrambankptr())
|
||||
cart_.wsrambankptr()[p] = data;
|
||||
else if (cart_.isHuC3())
|
||||
cart_.HuC3Write(p, data, cc);
|
||||
else
|
||||
cart_.rtcWrite(data, cc);
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ struct SaveState {
|
|||
unsigned char rambank;
|
||||
unsigned char oamDmaPos;
|
||||
unsigned char haltHdmaState;
|
||||
unsigned char HuC3RAMflag;
|
||||
unsigned char /*bool*/ IME;
|
||||
unsigned char /*bool*/ halted;
|
||||
unsigned char /*bool*/ enableRam;
|
||||
|
@ -205,6 +206,18 @@ struct SaveState {
|
|||
unsigned char dataS;
|
||||
unsigned char /*bool*/ lastLatchData;
|
||||
} rtc;
|
||||
|
||||
struct HuC3 {
|
||||
unsigned long haltTime;
|
||||
unsigned long dataTime;
|
||||
unsigned long writingTime;
|
||||
unsigned long irBaseCycle;
|
||||
unsigned char /*bool*/ halted;
|
||||
unsigned char shift;
|
||||
unsigned char ramValue;
|
||||
unsigned char modeflag;
|
||||
unsigned char /*bool*/ irReceivingPulse;
|
||||
} huc3;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -563,8 +563,11 @@ namespace M3Loop {
|
|||
p.xpos = xpos;
|
||||
}
|
||||
|
||||
void doFullTilesUnrolledCgb(PPUPriv& p, int const xend, uint_least32_t* const dbufline,
|
||||
unsigned char const* const tileMapLine, unsigned const tileline, unsigned tileMapXpos) {
|
||||
void doFullTilesUnrolledCgb(PPUPriv &p, int const xend, uint_least32_t* const dbufline,
|
||||
unsigned char const *const tileMapLine, unsigned const tileline, unsigned tileMapXpos) {
|
||||
int const tileIndexSign = p.lcdc & lcdc_tdsel ? 0 : tile_pattern_table_size / tile_size / 2;
|
||||
unsigned char const* const tileDataLine = p.vram + 2 * tile_size * tileIndexSign
|
||||
+ tileline * tile_line_size;
|
||||
int xpos = p.xpos;
|
||||
unsigned char const* const vram = p.vram;
|
||||
unsigned const tdoffset = tileline * tile_line_size
|
||||
|
@ -620,7 +623,16 @@ namespace M3Loop {
|
|||
uint_least32_t* const dstend = dst + n;
|
||||
xpos += n;
|
||||
|
||||
do {
|
||||
if (!lcdcBgEn(p) && p.cgbDmg) {
|
||||
do { *dst++ = p.bgPalette[0]; } while (dst != dstend);
|
||||
tileMapXpos += n / (1u * tile_len);
|
||||
|
||||
unsigned const tno = tileMapLine[(tileMapXpos - 1) % tile_map_len];
|
||||
int const ts = tile_size;
|
||||
ntileword = expand_lut[(tileDataLine + ts * tno - 2 * ts * (tno & tileIndexSign))[0]]
|
||||
+ expand_lut[(tileDataLine + ts * tno - 2 * ts * (tno & tileIndexSign))[1]] * 2;
|
||||
}
|
||||
else do {
|
||||
unsigned long const* const bgPalette = p.bgPalette
|
||||
+ (nattrib & attr_cgbpalno) * num_palette_entries;
|
||||
dst[0] = bgPalette[ntileword & tile_bpp_mask];
|
||||
|
@ -659,7 +671,7 @@ namespace M3Loop {
|
|||
}
|
||||
|
||||
uint_least32_t* const dst = dbufline + (xpos - tile_len);
|
||||
unsigned const tileword = p.ntileword;
|
||||
unsigned const tileword = ((p.lcdc & 1u * lcdc_bgen) | !p.cgbDmg) * p.ntileword;;
|
||||
unsigned const attrib = p.nattrib;
|
||||
unsigned long const* const bgPalette = p.bgPalette
|
||||
+ (attrib & attr_cgbpalno) * num_palette_entries;
|
||||
|
@ -870,7 +882,7 @@ namespace M3Loop {
|
|||
p.winDrawState |= win_draw_start;
|
||||
}
|
||||
|
||||
unsigned const twdata = tileword & ((p.lcdc & lcdc_bgen) | p.cgb) * tile_bpp_mask;
|
||||
unsigned const twdata = tileword & ((p.lcdc & lcdc_bgen) | (p.cgb * !p.cgbDmg)) * tile_bpp_mask;
|
||||
unsigned long pixel = p.bgPalette[twdata + (p.attrib & attr_cgbpalno) * num_palette_entries];
|
||||
int i = static_cast<int>(p.nextSprite) - 1;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -310,6 +310,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
case 0x1D: return "MBC5 ROM+RUMBLE+RAM"; // = MBC5; break;
|
||||
case 0x1E: return "MBC5 ROM+RUMBLE+RAM+BATTERY"; // = MBC5; break;
|
||||
case 0xFF: return "HuC1 ROM+RAM+BATTERY"; // = HUC1; break;
|
||||
case 0xFE: return "HuC3 ROM+RAM+BATTERY";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +362,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
case 0xfc: throw new UnsupportedGameException("\"Pocket Camera\" Mapper not supported!");
|
||||
case 0xfd: throw new UnsupportedGameException("\"Bandai TAMA5\" Mapper not supported!");
|
||||
case 0xfe: throw new UnsupportedGameException("\"HuC3\" Mapper not supported!");
|
||||
case 0xfe: break;
|
||||
case 0xff: break;
|
||||
default: throw new UnsupportedGameException($"Unknown mapper: {romdata[0x147]:x2}");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue