mirror of https://github.com/bsnes-emu/bsnes.git
Update to v095r06 release.
byuu says: Changelog: - fixed I/O register reads; perfect score on endrift's I/O tests now - fixed mouse capture clipping on Windows [Cydrak] - several hours of code maintenance work done on the SFC core All higan/sfc files should now use the auto fn() -> ret; syntax. Haven't converted all unsigned->uint yet. Also, probably won't do sfc/alt as that's mostly just speed hack stuff. Errata: - forgot auto& instead of just auto on SuperFamicom::Video::draw_cursor, which makes Super Scope / Justifier crash. Will be fixed in the next WIP.
This commit is contained in:
parent
6d9f43a37b
commit
40f4b91000
|
@ -7,7 +7,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "095.05";
|
static const string Version = "095.06";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -94,10 +94,10 @@ Board::Board(Markup::Node& document) {
|
||||||
auto crom = cartridge["chr/rom"];
|
auto crom = cartridge["chr/rom"];
|
||||||
auto cram = cartridge["chr/ram"];
|
auto cram = cartridge["chr/ram"];
|
||||||
|
|
||||||
prgrom.size = prom["size"].decimal();
|
prgrom.size = prom["size"].natural();
|
||||||
prgram.size = pram["size"].decimal();
|
prgram.size = pram["size"].natural();
|
||||||
chrrom.size = crom["size"].decimal();
|
chrrom.size = crom["size"].natural();
|
||||||
chrram.size = cram["size"].decimal();
|
chrram.size = cram["size"].natural();
|
||||||
|
|
||||||
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
||||||
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
||||||
|
|
|
@ -50,8 +50,8 @@ void serialize(serializer& s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
KonamiVRC2(Markup::Node& document) : Board(document), vrc2(*this) {
|
KonamiVRC2(Markup::Node& document) : Board(document), vrc2(*this) {
|
||||||
settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].decimal();
|
settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].natural();
|
||||||
settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].decimal();
|
settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].natural();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,8 +54,8 @@ void serialize(serializer& s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
KonamiVRC4(Markup::Node& document) : Board(document), vrc4(*this) {
|
KonamiVRC4(Markup::Node& document) : Board(document), vrc4(*this) {
|
||||||
settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].decimal();
|
settings.pinout.a0 = 1 << document["cartridge/chip/pinout/a0"].natural();
|
||||||
settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].decimal();
|
settings.pinout.a1 = 1 << document["cartridge/chip/pinout/a1"].natural();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,10 +66,10 @@ void Cartridge::load(System::Revision revision) {
|
||||||
auto rom = document["cartridge/rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
auto ram = document["cartridge/ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
romsize = rom["size"].decimal();
|
romsize = rom["size"].natural();
|
||||||
romdata = allocate<uint8>(romsize, 0xff);
|
romdata = allocate<uint8>(romsize, 0xff);
|
||||||
|
|
||||||
ramsize = ram["size"].decimal();
|
ramsize = ram["size"].natural();
|
||||||
ramdata = allocate<uint8>(ramsize, 0xff);
|
ramdata = allocate<uint8>(ramsize, 0xff);
|
||||||
|
|
||||||
//Super Game Boy core loads memory from Super Famicom core
|
//Super Game Boy core loads memory from Super Famicom core
|
||||||
|
@ -79,8 +79,8 @@ void Cartridge::load(System::Revision revision) {
|
||||||
if(auto name = ram["name"].text()) memory.append({ID::RAM, name});
|
if(auto name = ram["name"].text()) memory.append({ID::RAM, name});
|
||||||
}
|
}
|
||||||
|
|
||||||
information.romsize = rom["size"].decimal();
|
information.romsize = rom["size"].natural();
|
||||||
information.ramsize = ram["size"].decimal();
|
information.ramsize = ram["size"].natural();
|
||||||
information.battery = (bool)ram["name"];
|
information.battery = (bool)ram["name"];
|
||||||
|
|
||||||
switch(information.mapper) { default:
|
switch(information.mapper) { default:
|
||||||
|
|
|
@ -32,10 +32,10 @@ void APU::Noise::clockenvelope() {
|
||||||
|
|
||||||
uint8 APU::Noise::read(unsigned addr) const {
|
uint8 APU::Noise::read(unsigned addr) const {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 1: return (length << 0);
|
case 1: return 0;
|
||||||
case 2: return (envelope.frequency << 0) | (envelope.direction << 3) | (envelope.volume << 4);
|
case 2: return (envelope.frequency << 0) | (envelope.direction << 3) | (envelope.volume << 4);
|
||||||
case 3: return (divisor << 0) | (narrowlfsr << 3) | (frequency << 4);
|
case 3: return (divisor << 0) | (narrowlfsr << 3) | (frequency << 4);
|
||||||
case 4: return (counter << 6) | (initialize << 7);
|
case 4: return (counter << 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,13 +39,7 @@ uint8 APU::Sequencer::read(unsigned addr) const {
|
||||||
| (lenable[2] << 6)
|
| (lenable[2] << 6)
|
||||||
| (lenable[3] << 7)
|
| (lenable[3] << 7)
|
||||||
);
|
);
|
||||||
case 2: return (
|
case 2: return (masterenable << 7);
|
||||||
(enable[0] << 0)
|
|
||||||
| (enable[1] << 1)
|
|
||||||
| (enable[2] << 2)
|
|
||||||
| (enable[3] << 3)
|
|
||||||
| (masterenable << 7)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ void APU::Square1::clocksweep() {
|
||||||
uint8 APU::Square1::read(unsigned addr) const {
|
uint8 APU::Square1::read(unsigned addr) const {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0: return (sweep.shift << 0) | (sweep.direction << 3) | (sweep.frequency << 4);
|
case 0: return (sweep.shift << 0) | (sweep.direction << 3) | (sweep.frequency << 4);
|
||||||
case 1: return (length << 0) | (duty << 6);
|
case 1: return (duty << 6);
|
||||||
case 2: return (envelope.frequency << 0) | (envelope.direction << 3) | (envelope.volume << 4);
|
case 2: return (envelope.frequency << 0) | (envelope.direction << 3) | (envelope.volume << 4);
|
||||||
case 3: return (frequency << 0);
|
case 3: return 0;
|
||||||
case 4: return (frequency >> 8) | (counter << 6) | (initialize << 7);
|
case 4: return (counter << 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
uint8 APU::Square2::read(unsigned addr) const {
|
uint8 APU::Square2::read(unsigned addr) const {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 1: return (length << 0) | (duty << 6);
|
case 1: return (duty << 6);
|
||||||
case 2: return (envelope.frequency << 0) | (envelope.direction << 3) | (envelope.volume << 4);
|
case 2: return (envelope.frequency << 0) | (envelope.direction << 3) | (envelope.volume << 4);
|
||||||
case 3: return (frequency >> 0);
|
case 3: return 0;
|
||||||
case 4: return (frequency >> 8) | (counter << 6) | (initialize << 7);
|
case 4: return (counter << 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@ void APU::Wave::clocklength() {
|
||||||
uint8 APU::Wave::read(unsigned addr) const {
|
uint8 APU::Wave::read(unsigned addr) const {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0: return (mode << 5) | (bank << 6) | (dacenable << 7);
|
case 0: return (mode << 5) | (bank << 6) | (dacenable << 7);
|
||||||
case 1: return (length << 0);
|
case 1: return 0;
|
||||||
case 2: return (volume << 5);
|
case 2: return (volume << 5);
|
||||||
case 3: return (frequency >> 0);
|
case 3: return 0;
|
||||||
case 4: return (frequency >> 8) | (counter << 6) | (initialize << 7);
|
case 4: return (counter << 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,14 @@ auto Cartridge::load() -> void {
|
||||||
hasFLASH = false;
|
hasFLASH = false;
|
||||||
|
|
||||||
if(auto info = document["cartridge/mrom"]) {
|
if(auto info = document["cartridge/mrom"]) {
|
||||||
mrom.size = min(32 * 1024 * 1024, info["size"].decimal());
|
mrom.size = min(32 * 1024 * 1024, info["size"].natural());
|
||||||
|
|
||||||
interface->loadRequest(ID::MROM, info["name"].text(), true);
|
interface->loadRequest(ID::MROM, info["name"].text(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto info = document["cartridge/sram"]) {
|
if(auto info = document["cartridge/sram"]) {
|
||||||
hasSRAM = true;
|
hasSRAM = true;
|
||||||
sram.size = min(32 * 1024, info["size"].decimal());
|
sram.size = min(32 * 1024, info["size"].natural());
|
||||||
sram.mask = sram.size - 1;
|
sram.mask = sram.size - 1;
|
||||||
for(auto n : range(sram.size)) sram.data[n] = 0xff;
|
for(auto n : range(sram.size)) sram.data[n] = 0xff;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ auto Cartridge::load() -> void {
|
||||||
|
|
||||||
if(auto info = document["cartridge/eeprom"]) {
|
if(auto info = document["cartridge/eeprom"]) {
|
||||||
hasEEPROM = true;
|
hasEEPROM = true;
|
||||||
eeprom.size = min(8 * 1024, info["size"].decimal());
|
eeprom.size = min(8 * 1024, info["size"].natural());
|
||||||
eeprom.bits = eeprom.size <= 512 ? 6 : 14;
|
eeprom.bits = eeprom.size <= 512 ? 6 : 14;
|
||||||
if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size
|
if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size
|
||||||
eeprom.mask = mrom.size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
|
eeprom.mask = mrom.size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
|
||||||
|
@ -76,8 +76,8 @@ auto Cartridge::load() -> void {
|
||||||
|
|
||||||
if(auto info = document["cartridge/flash"]) {
|
if(auto info = document["cartridge/flash"]) {
|
||||||
hasFLASH = true;
|
hasFLASH = true;
|
||||||
flash.id = info["id"].decimal();
|
flash.id = info["id"].natural();
|
||||||
flash.size = min(128 * 1024, info["size"].decimal());
|
flash.size = min(128 * 1024, info["size"].natural());
|
||||||
for(auto n : range(flash.size)) flash.data[n] = 0xff;
|
for(auto n : range(flash.size)) flash.data[n] = 0xff;
|
||||||
|
|
||||||
//if flash ID not provided; guess that it's a Macronix chip
|
//if flash ID not provided; guess that it's a Macronix chip
|
||||||
|
|
|
@ -190,6 +190,7 @@ auto CPU::write(uint32 addr, uint8 byte) -> void {
|
||||||
case 0x040000c6: case 0x040000c7:
|
case 0x040000c6: case 0x040000c7:
|
||||||
case 0x040000d2: case 0x040000d3:
|
case 0x040000d2: case 0x040000d3:
|
||||||
case 0x040000de: case 0x040000df: {
|
case 0x040000de: case 0x040000df: {
|
||||||
|
if(addr == 0x040000bb || addr == 0x040000c7 || addr == 0x040000d3) byte &= 0xf7; //gamepak DRQ valid for DMA3 only
|
||||||
auto& dma = regs.dma[(addr - 0x040000ba) / 12];
|
auto& dma = regs.dma[(addr - 0x040000ba) / 12];
|
||||||
unsigned shift = (addr & 1) * 8;
|
unsigned shift = (addr & 1) * 8;
|
||||||
bool enable = dma.control.enable;
|
bool enable = dma.control.enable;
|
||||||
|
|
|
@ -41,6 +41,8 @@ uint8 PPU::read(uint32 addr) {
|
||||||
case 0x04000052: return regs.blend.eva;
|
case 0x04000052: return regs.blend.eva;
|
||||||
case 0x04000053: return regs.blend.evb;
|
case 0x04000053: return regs.blend.evb;
|
||||||
|
|
||||||
|
//BLDY is write-only
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0u;
|
return 0u;
|
||||||
|
@ -194,11 +196,11 @@ void PPU::write(uint32 addr, uint8 byte) {
|
||||||
case 0x04000051: regs.blend.control = (regs.blend.control & 0x00ff) | (byte << 8); return;
|
case 0x04000051: regs.blend.control = (regs.blend.control & 0x00ff) | (byte << 8); return;
|
||||||
|
|
||||||
//BLDALPHA
|
//BLDALPHA
|
||||||
case 0x04000052: regs.blend.eva = std::min(16, byte & 0x1f); return;
|
case 0x04000052: regs.blend.eva = byte & 0x1f; return;
|
||||||
case 0x04000053: regs.blend.evb = std::min(16, byte & 0x1f); return;
|
case 0x04000053: regs.blend.evb = byte & 0x1f; return;
|
||||||
|
|
||||||
//BLDY
|
//BLDY
|
||||||
case 0x04000054: regs.blend.evy = std::min(16, byte & 0x1f); return;
|
case 0x04000054: regs.blend.evy = byte & 0x1f; return;
|
||||||
case 0x04000055: return;
|
case 0x04000055: return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ PPU::Registers::BackgroundControl::operator uint16() const {
|
||||||
return (
|
return (
|
||||||
(priority << 0)
|
(priority << 0)
|
||||||
| (characterbaseblock << 2)
|
| (characterbaseblock << 2)
|
||||||
|
| (unused << 4)
|
||||||
| (mosaic << 6)
|
| (mosaic << 6)
|
||||||
| (colormode << 7)
|
| (colormode << 7)
|
||||||
| (screenbaseblock << 8)
|
| (screenbaseblock << 8)
|
||||||
|
|
|
@ -77,6 +77,9 @@ void PPU::render_window(unsigned w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PPU::blend(unsigned above, unsigned eva, unsigned below, unsigned evb) {
|
unsigned PPU::blend(unsigned above, unsigned eva, unsigned below, unsigned evb) {
|
||||||
|
eva = min(16, eva);
|
||||||
|
evb = min(16, evb);
|
||||||
|
|
||||||
uint5 ar = above >> 0, ag = above >> 5, ab = above >> 10;
|
uint5 ar = above >> 0, ag = above >> 5, ab = above >> 10;
|
||||||
uint5 br = below >> 0, bg = below >> 5, bb = below >> 10;
|
uint5 br = below >> 0, bg = below >> 5, bb = below >> 10;
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ NSFont* pFont::cocoaFont(string description) {
|
||||||
CGFloat size = 8.0;
|
CGFloat size = 8.0;
|
||||||
|
|
||||||
if(!part(0).empty()) family = [NSString stringWithUTF8String:part(0)];
|
if(!part(0).empty()) family = [NSString stringWithUTF8String:part(0)];
|
||||||
if(!part(1).empty()) size = decimal(part(1));
|
if(!part(1).empty()) size = part(1).natural();
|
||||||
if(part(2).ifind("bold")) traits |= NSBoldFontMask;
|
if(part(2).ifind("bold")) traits |= NSBoldFontMask;
|
||||||
if(part(2).ifind("italic")) traits |= NSItalicFontMask;
|
if(part(2).ifind("italic")) traits |= NSItalicFontMask;
|
||||||
if(part(2).ifind("narrow")) traits |= NSNarrowFontMask;
|
if(part(2).ifind("narrow")) traits |= NSNarrowFontMask;
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#define Hiro_BrowserWindow
|
#define Hiro_BrowserWindow
|
||||||
#define Hiro_MessageWindow
|
#define Hiro_MessageWindow
|
||||||
|
|
||||||
|
#define Hiro_Property
|
||||||
|
|
||||||
#define Hiro_Object
|
#define Hiro_Object
|
||||||
#define Hiro_Group
|
#define Hiro_Group
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ namespace hiro {
|
||||||
#include "browser-window.cpp"
|
#include "browser-window.cpp"
|
||||||
#include "message-window.cpp"
|
#include "message-window.cpp"
|
||||||
|
|
||||||
|
#include "property.cpp"
|
||||||
|
|
||||||
#include "object.cpp"
|
#include "object.cpp"
|
||||||
#include "group.cpp"
|
#include "group.cpp"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <nall/image.hpp>
|
#include <nall/image.hpp>
|
||||||
#include <nall/maybe.hpp>
|
#include <nall/maybe.hpp>
|
||||||
#include <nall/range.hpp>
|
#include <nall/range.hpp>
|
||||||
|
#include <nall/set.hpp>
|
||||||
#include <nall/shared-pointer.hpp>
|
#include <nall/shared-pointer.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
|
@ -15,6 +16,8 @@
|
||||||
using nall::function;
|
using nall::function;
|
||||||
using nall::lstring;
|
using nall::lstring;
|
||||||
using nall::maybe;
|
using nall::maybe;
|
||||||
|
using nall::nothing;
|
||||||
|
using nall::set;
|
||||||
using nall::shared_pointer;
|
using nall::shared_pointer;
|
||||||
using nall::shared_pointer_weak;
|
using nall::shared_pointer_weak;
|
||||||
using nall::string;
|
using nall::string;
|
||||||
|
@ -542,6 +545,25 @@ struct MessageWindow {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct Property {
|
||||||
|
using type = Property;
|
||||||
|
|
||||||
|
Property(const string& name, const string& value = "");
|
||||||
|
|
||||||
|
auto operator==(const Property& source) const -> bool;
|
||||||
|
auto operator< (const Property& source) const -> bool;
|
||||||
|
|
||||||
|
auto name() const -> string;
|
||||||
|
auto setValue(const string& value = "") -> type&;
|
||||||
|
auto value() const -> string;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct State {
|
||||||
|
string name;
|
||||||
|
string value;
|
||||||
|
} state;
|
||||||
|
};
|
||||||
|
|
||||||
#define Declare(Name) \
|
#define Declare(Name) \
|
||||||
using type = m##Name; \
|
using type = m##Name; \
|
||||||
operator s##Name() const { return instance; } \
|
operator s##Name() const { return instance; } \
|
||||||
|
@ -595,6 +617,7 @@ struct mObject {
|
||||||
auto parentTreeViewItem(bool recursive = false) const -> mTreeViewItem*;
|
auto parentTreeViewItem(bool recursive = false) const -> mTreeViewItem*;
|
||||||
auto parentWidget(bool recursive = false) const -> mWidget*;
|
auto parentWidget(bool recursive = false) const -> mWidget*;
|
||||||
auto parentWindow(bool recursive = false) const -> mWindow*;
|
auto parentWindow(bool recursive = false) const -> mWindow*;
|
||||||
|
auto property(const string& name) const -> string;
|
||||||
virtual auto remove() -> type&;
|
virtual auto remove() -> type&;
|
||||||
virtual auto reset() -> type&;
|
virtual auto reset() -> type&;
|
||||||
virtual auto setEnabled(bool enabled = true) -> type&;
|
virtual auto setEnabled(bool enabled = true) -> type&;
|
||||||
|
@ -602,6 +625,7 @@ struct mObject {
|
||||||
virtual auto setFont(const Font& font = {}) -> type&;
|
virtual auto setFont(const Font& font = {}) -> type&;
|
||||||
virtual auto setGroup(sGroup group = {}) -> type&;
|
virtual auto setGroup(sGroup group = {}) -> type&;
|
||||||
virtual auto setParent(mObject* parent = nullptr, signed offset = -1) -> type&;
|
virtual auto setParent(mObject* parent = nullptr, signed offset = -1) -> type&;
|
||||||
|
virtual auto setProperty(const string& name, const string& value = "") -> type&;
|
||||||
virtual auto setVisible(bool visible = true) -> type&;
|
virtual auto setVisible(bool visible = true) -> type&;
|
||||||
auto visible(bool recursive = false) const -> bool;
|
auto visible(bool recursive = false) const -> bool;
|
||||||
|
|
||||||
|
@ -611,6 +635,7 @@ struct mObject {
|
||||||
Font font;
|
Font font;
|
||||||
signed offset = -1;
|
signed offset = -1;
|
||||||
mObject* parent = nullptr;
|
mObject* parent = nullptr;
|
||||||
|
set<Property> properties;
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,13 @@ auto mObject::parentWindow(bool recursive) const -> mWindow* {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto mObject::property(const string& name) const -> string {
|
||||||
|
if(auto property = state.properties.find({name})) {
|
||||||
|
return property->value();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
auto mObject::remove() -> type& {
|
auto mObject::remove() -> type& {
|
||||||
signal(remove);
|
signal(remove);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -295,6 +302,16 @@ auto mObject::setParent(mObject* parent, signed offset) -> type& {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto mObject::setProperty(const string& name, const string& value) -> type& {
|
||||||
|
if(auto property = state.properties.find(name)) {
|
||||||
|
if(value) property->setValue(value);
|
||||||
|
else state.properties.remove(*property);
|
||||||
|
} else {
|
||||||
|
if(value) state.properties.insert({name, value});
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
auto mObject::setVisible(bool visible) -> type& {
|
auto mObject::setVisible(bool visible) -> type& {
|
||||||
state.visible = visible;
|
state.visible = visible;
|
||||||
signal(setVisible, this->visible(true));
|
signal(setVisible, this->visible(true));
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#if defined(Hiro_Property)
|
||||||
|
|
||||||
|
Property::Property(const string& name, const string& value) {
|
||||||
|
state.name = name;
|
||||||
|
state.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Property::operator==(const Property& source) const -> bool {
|
||||||
|
return state.name == source.state.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Property::operator<(const Property& source) const -> bool {
|
||||||
|
return state.name < source.state.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Property::name() const -> string {
|
||||||
|
return state.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Property::setValue(const string& value) -> type& {
|
||||||
|
state.value = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Property::value() const -> string {
|
||||||
|
return state.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -25,10 +25,12 @@
|
||||||
} \
|
} \
|
||||||
return Object(); \
|
return Object(); \
|
||||||
} \
|
} \
|
||||||
|
auto property(const string& name) const { return self().property(name); } \
|
||||||
auto remove() { return self().remove(), *this; } \
|
auto remove() { return self().remove(), *this; } \
|
||||||
auto setEnabled(bool enabled = true) { return self().setEnabled(enabled), *this; } \
|
auto setEnabled(bool enabled = true) { return self().setEnabled(enabled), *this; } \
|
||||||
auto setFocused() { return self().setFocused(), *this; } \
|
auto setFocused() { return self().setFocused(), *this; } \
|
||||||
auto setFont(const Font& font = {}) { return self().setFont(font), *this; } \
|
auto setFont(const Font& font = {}) { return self().setFont(font), *this; } \
|
||||||
|
auto setProperty(const string& name, const string& value = "") { return self().setProperty(name, value), *this; } \
|
||||||
auto setVisible(bool visible = true) { return self().setVisible(visible), *this; } \
|
auto setVisible(bool visible = true) { return self().setVisible(visible), *this; } \
|
||||||
auto visible(bool recursive = false) const { return self().visible(recursive); } \
|
auto visible(bool recursive = false) const { return self().visible(recursive); } \
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ auto mTreeViewItem::image() const -> Image {
|
||||||
auto mTreeViewItem::item(const string& path) const -> TreeViewItem {
|
auto mTreeViewItem::item(const string& path) const -> TreeViewItem {
|
||||||
if(path.empty()) return {};
|
if(path.empty()) return {};
|
||||||
auto paths = path.split("/");
|
auto paths = path.split("/");
|
||||||
unsigned position = decimal(paths.takeFirst());
|
unsigned position = paths.takeFirst().natural();
|
||||||
if(position >= itemCount()) return {};
|
if(position >= itemCount()) return {};
|
||||||
if(paths.empty()) return state.items[position];
|
if(paths.empty()) return state.items[position];
|
||||||
return state.items[position]->item(paths.merge("/"));
|
return state.items[position]->item(paths.merge("/"));
|
||||||
|
|
|
@ -45,7 +45,7 @@ auto mTreeView::foregroundColor() const -> Color {
|
||||||
auto mTreeView::item(const string& path) const -> TreeViewItem {
|
auto mTreeView::item(const string& path) const -> TreeViewItem {
|
||||||
if(path.empty()) return {};
|
if(path.empty()) return {};
|
||||||
auto paths = path.split("/");
|
auto paths = path.split("/");
|
||||||
unsigned position = decimal(paths.takeFirst());
|
unsigned position = paths.takeFirst().natural();
|
||||||
if(position >= itemCount()) return {};
|
if(position >= itemCount()) return {};
|
||||||
if(paths.empty()) return state.items[position];
|
if(paths.empty()) return state.items[position];
|
||||||
return state.items[position]->item(paths.merge("/"));
|
return state.items[position]->item(paths.merge("/"));
|
||||||
|
|
|
@ -193,7 +193,7 @@ auto pIconView::_updateSelected() -> void {
|
||||||
while(p) {
|
while(p) {
|
||||||
auto path = (GtkTreePath*)p->data;
|
auto path = (GtkTreePath*)p->data;
|
||||||
char* pathString = gtk_tree_path_to_string(path);
|
char* pathString = gtk_tree_path_to_string(path);
|
||||||
unsigned position = decimal(pathString);
|
unsigned position = natural(pathString);
|
||||||
g_free(pathString);
|
g_free(pathString);
|
||||||
selected.append(position);
|
selected.append(position);
|
||||||
p = p->next;
|
p = p->next;
|
||||||
|
|
|
@ -212,7 +212,7 @@ auto pListView::_doContext() -> void {
|
||||||
|
|
||||||
auto pListView::_doDataFunc(GtkTreeViewColumn* gtkColumn, GtkCellRenderer* renderer, GtkTreeIter* iter) -> void {
|
auto pListView::_doDataFunc(GtkTreeViewColumn* gtkColumn, GtkCellRenderer* renderer, GtkTreeIter* iter) -> void {
|
||||||
auto path = gtk_tree_model_get_string_from_iter(gtkTreeModel, iter);
|
auto path = gtk_tree_model_get_string_from_iter(gtkTreeModel, iter);
|
||||||
auto row = decimal(path);
|
auto row = natural(path);
|
||||||
g_free(path);
|
g_free(path);
|
||||||
|
|
||||||
if(auto& header = state().header) {
|
if(auto& header = state().header) {
|
||||||
|
@ -265,7 +265,7 @@ auto pListView::_doEdit(GtkCellRendererText* gtkCellRendererText, const char* pa
|
||||||
for(auto& column : header->state.columns) {
|
for(auto& column : header->state.columns) {
|
||||||
if(auto delegate = column->self()) {
|
if(auto delegate = column->self()) {
|
||||||
if(gtkCellRendererText == GTK_CELL_RENDERER_TEXT(delegate->gtkCellText)) {
|
if(gtkCellRendererText == GTK_CELL_RENDERER_TEXT(delegate->gtkCellText)) {
|
||||||
auto row = decimal(path);
|
auto row = natural(path);
|
||||||
if(auto item = self().item(row)) {
|
if(auto item = self().item(row)) {
|
||||||
if(auto cell = item->cell(column->offset())) {
|
if(auto cell = item->cell(column->offset())) {
|
||||||
if(string{text} != cell->state.text) {
|
if(string{text} != cell->state.text) {
|
||||||
|
@ -337,7 +337,7 @@ auto pListView::_doToggle(GtkCellRendererToggle* gtkCellRendererToggle, const ch
|
||||||
for(auto& column : header->state.columns) {
|
for(auto& column : header->state.columns) {
|
||||||
if(auto delegate = column->self()) {
|
if(auto delegate = column->self()) {
|
||||||
if(gtkCellRendererToggle == GTK_CELL_RENDERER_TOGGLE(delegate->gtkCellToggle)) {
|
if(gtkCellRendererToggle == GTK_CELL_RENDERER_TOGGLE(delegate->gtkCellToggle)) {
|
||||||
auto row = decimal(path);
|
auto row = natural(path);
|
||||||
if(auto item = self().item(row)) {
|
if(auto item = self().item(row)) {
|
||||||
if(auto cell = item->cell(column->offset())) {
|
if(auto cell = item->cell(column->offset())) {
|
||||||
cell->setChecked(!cell->checked());
|
cell->setChecked(!cell->checked());
|
||||||
|
@ -365,7 +365,7 @@ auto pListView::_updateSelected() -> void {
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
if(gtk_tree_model_get_iter(gtkTreeModel, &iter, (GtkTreePath*)p->data)) {
|
if(gtk_tree_model_get_iter(gtkTreeModel, &iter, (GtkTreePath*)p->data)) {
|
||||||
char* pathname = gtk_tree_model_get_string_from_iter(gtkTreeModel, &iter);
|
char* pathname = gtk_tree_model_get_string_from_iter(gtkTreeModel, &iter);
|
||||||
unsigned selection = decimal(pathname);
|
unsigned selection = natural(pathname);
|
||||||
g_free(pathname);
|
g_free(pathname);
|
||||||
selected.append(selection);
|
selected.append(selection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,10 +123,10 @@ auto pTreeView::_doDataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer
|
||||||
auto parts = string{path}.split(":");
|
auto parts = string{path}.split(":");
|
||||||
g_free(path);
|
g_free(path);
|
||||||
|
|
||||||
auto item = self().item(decimal(parts.takeFirst()));
|
auto item = self().item(parts.takeFirst().natural());
|
||||||
if(!item) return;
|
if(!item) return;
|
||||||
while(parts) {
|
while(parts) {
|
||||||
item = item.item(decimal(parts.takeFirst()));
|
item = item.item(parts.takeFirst().natural());
|
||||||
if(!item) return;
|
if(!item) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
#define NALL_ATOI_HPP
|
#define NALL_ATOI_HPP
|
||||||
|
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/varint.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
constexpr inline auto binary_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
constexpr inline auto binary_(const char* s, uintmax sum = 0) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s == '0' || *s == '1' ? binary_(s + 1, (sum << 1) | *s - '0') :
|
*s == '0' || *s == '1' ? binary_(s + 1, (sum << 1) | *s - '0') :
|
||||||
*s == '\'' ? binary_(s + 1, sum) :
|
*s == '\'' ? binary_(s + 1, sum) :
|
||||||
|
@ -13,7 +14,7 @@ constexpr inline auto binary_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto octal_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
constexpr inline auto octal_(const char* s, uintmax sum = 0) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s >= '0' && *s <= '7' ? octal_(s + 1, (sum << 3) | *s - '0') :
|
*s >= '0' && *s <= '7' ? octal_(s + 1, (sum << 3) | *s - '0') :
|
||||||
*s == '\'' ? octal_(s + 1, sum) :
|
*s == '\'' ? octal_(s + 1, sum) :
|
||||||
|
@ -21,15 +22,15 @@ constexpr inline auto octal_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto decimal_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
constexpr inline auto natural_(const char* s, uintmax sum = 0) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s >= '0' && *s <= '9' ? decimal_(s + 1, (sum * 10) + *s - '0') :
|
*s >= '0' && *s <= '9' ? natural_(s + 1, (sum * 10) + *s - '0') :
|
||||||
*s == '\'' ? decimal_(s + 1, sum) :
|
*s == '\'' ? natural_(s + 1, sum) :
|
||||||
sum
|
sum
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto hex_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
constexpr inline auto hex_(const char* s, uintmax sum = 0) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s >= 'A' && *s <= 'F' ? hex_(s + 1, (sum << 4) | *s - 'A' + 10) :
|
*s >= 'A' && *s <= 'F' ? hex_(s + 1, (sum << 4) | *s - 'A' + 10) :
|
||||||
*s >= 'a' && *s <= 'f' ? hex_(s + 1, (sum << 4) | *s - 'a' + 10) :
|
*s >= 'a' && *s <= 'f' ? hex_(s + 1, (sum << 4) | *s - 'a' + 10) :
|
||||||
|
@ -41,7 +42,7 @@ constexpr inline auto hex_(const char* s, uintmax_t sum = 0) -> uintmax_t {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
constexpr inline auto binary(const char* s) -> uintmax_t {
|
constexpr inline auto binary(const char* s) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s == '0' && *(s + 1) == 'B' ? binary_(s + 2) :
|
*s == '0' && *(s + 1) == 'B' ? binary_(s + 2) :
|
||||||
*s == '0' && *(s + 1) == 'b' ? binary_(s + 2) :
|
*s == '0' && *(s + 1) == 'b' ? binary_(s + 2) :
|
||||||
|
@ -50,7 +51,7 @@ constexpr inline auto binary(const char* s) -> uintmax_t {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto octal(const char* s) -> uintmax_t {
|
constexpr inline auto octal(const char* s) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s == '0' && *(s + 1) == 'O' ? octal_(s + 2) :
|
*s == '0' && *(s + 1) == 'O' ? octal_(s + 2) :
|
||||||
*s == '0' && *(s + 1) == 'o' ? octal_(s + 2) :
|
*s == '0' && *(s + 1) == 'o' ? octal_(s + 2) :
|
||||||
|
@ -58,21 +59,21 @@ constexpr inline auto octal(const char* s) -> uintmax_t {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto integer(const char* s) -> intmax_t {
|
constexpr inline auto integer(const char* s) -> intmax {
|
||||||
return (
|
return (
|
||||||
*s == '+' ? +decimal_(s + 1) :
|
*s == '+' ? +natural_(s + 1) :
|
||||||
*s == '-' ? -decimal_(s + 1) :
|
*s == '-' ? -natural_(s + 1) :
|
||||||
decimal_(s)
|
natural_(s)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto decimal(const char* s) -> uintmax_t {
|
constexpr inline auto natural(const char* s) -> uintmax {
|
||||||
return (
|
return (
|
||||||
decimal_(s)
|
natural_(s)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline auto hex(const char* s) -> uintmax_t {
|
constexpr inline auto hex(const char* s) -> uintmax {
|
||||||
return (
|
return (
|
||||||
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
||||||
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Configuration {
|
||||||
struct Node {
|
struct Node {
|
||||||
string name;
|
string name;
|
||||||
string desc;
|
string desc;
|
||||||
enum class Type : unsigned { Null, Bool, Signed, Unsigned, Double, String } type = Type::Null;
|
enum class Type : unsigned { Null, Boolean, Integer, Natural, Double, String } type = Type::Null;
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
vector<Node> children;
|
vector<Node> children;
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ struct Node {
|
||||||
|
|
||||||
auto get() const -> string {
|
auto get() const -> string {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::Bool: return {*(bool*)data};
|
case Type::Boolean: return {*(bool*)data};
|
||||||
case Type::Signed: return {*(signed*)data};
|
case Type::Integer: return {*(int*)data};
|
||||||
case Type::Unsigned: return {*(unsigned*)data};
|
case Type::Natural: return {*(uint*)data};
|
||||||
case Type::Double: return {*(double*)data};
|
case Type::Double: return {*(double*)data};
|
||||||
case Type::String: return {*(string*)data};
|
case Type::String: return {*(string*)data};
|
||||||
}
|
}
|
||||||
|
@ -32,18 +32,18 @@ struct Node {
|
||||||
|
|
||||||
auto set(const string& value) -> void {
|
auto set(const string& value) -> void {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::Bool: *(bool*)data = (value != "false"); break;
|
case Type::Boolean: *(bool*)data = (value != "false"); break;
|
||||||
case Type::Signed: *(signed*)data = integer(value); break;
|
case Type::Integer: *(int*)data = integer(value); break;
|
||||||
case Type::Unsigned: *(unsigned*)data = decimal(value); break;
|
case Type::Natural: *(uint*)data = natural(value); break;
|
||||||
case Type::Double: *(double*)data = real(value); break;
|
case Type::Double: *(double*)data = real(value); break;
|
||||||
case Type::String: *(string*)data = value; break;
|
case Type::String: *(string*)data = value; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto assign() { type = Type::Null; data = nullptr; }
|
auto assign() { type = Type::Null; data = nullptr; }
|
||||||
auto assign(bool& bind) { type = Type::Bool; data = (void*)&bind; }
|
auto assign(bool& bind) { type = Type::Boolean; data = (void*)&bind; }
|
||||||
auto assign(signed& bind) { type = Type::Signed; data = (void*)&bind; }
|
auto assign(int& bind) { type = Type::Integer; data = (void*)&bind; }
|
||||||
auto assign(unsigned& bind) { type = Type::Unsigned; data = (void*)&bind; }
|
auto assign(uint& bind) { type = Type::Natural; data = (void*)&bind; }
|
||||||
auto assign(double& bind) { type = Type::Double; data = (void*)&bind; }
|
auto assign(double& bind) { type = Type::Double; data = (void*)&bind; }
|
||||||
auto assign(string& bind) { type = Type::String; data = (void*)&bind; }
|
auto assign(string& bind) { type = Type::String; data = (void*)&bind; }
|
||||||
auto assign(const Node& node) { operator=(node); }
|
auto assign(const Node& node) { operator=(node); }
|
||||||
|
@ -80,10 +80,10 @@ struct Node {
|
||||||
auto save(file& fp, unsigned depth = 0) -> void {
|
auto save(file& fp, unsigned depth = 0) -> void {
|
||||||
for(auto& child : children) {
|
for(auto& child : children) {
|
||||||
if(child.desc) {
|
if(child.desc) {
|
||||||
for(unsigned n = 0; n < depth; n++) fp.print(" ");
|
for(auto n : range(depth)) fp.print(" ");
|
||||||
fp.print("//", child.desc, "\n");
|
fp.print("//", child.desc, "\n");
|
||||||
}
|
}
|
||||||
for(unsigned n = 0; n < depth; n++) fp.print(" ");
|
for(auto n : range(depth)) fp.print(" ");
|
||||||
fp.print(child.name);
|
fp.print(child.name);
|
||||||
if(!child.empty()) fp.print(": ", child.get());
|
if(!child.empty()) fp.print(": ", child.get());
|
||||||
fp.print("\n");
|
fp.print("\n");
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct ODBC {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto decimal(unsigned column) -> uint64_t {
|
auto natural(unsigned column) -> uint64_t {
|
||||||
if(auto value = _values(column)) return value.get<uint64_t>(0);
|
if(auto value = _values(column)) return value.get<uint64_t>(0);
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
SQLGetData(statement(), 1 + column, SQL_C_UBIGINT, &value, 0, nullptr);
|
SQLGetData(statement(), 1 + column, SQL_C_UBIGINT, &value, 0, nullptr);
|
||||||
|
@ -79,7 +79,7 @@ struct ODBC {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto integer() -> int64_t { return integer(_output++); }
|
auto integer() -> int64_t { return integer(_output++); }
|
||||||
auto decimal() -> uint64_t { return decimal(_output++); }
|
auto natural() -> uint64_t { return natural(_output++); }
|
||||||
auto real() -> double { return real(_output++); }
|
auto real() -> double { return real(_output++); }
|
||||||
auto text() -> string { return text(_output++); }
|
auto text() -> string { return text(_output++); }
|
||||||
auto data() -> vector<uint8_t> { return data(_output++); }
|
auto data() -> vector<uint8_t> { return data(_output++); }
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct SQLite3 {
|
||||||
return sqlite3_column_int64(statement(), column);
|
return sqlite3_column_int64(statement(), column);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto decimal(unsigned column) -> uint64_t {
|
auto natural(unsigned column) -> uint64_t {
|
||||||
return sqlite3_column_int64(statement(), column);
|
return sqlite3_column_int64(statement(), column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ struct SQLite3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto integer() -> int64_t { return integer(_output++); }
|
auto integer() -> int64_t { return integer(_output++); }
|
||||||
auto decimal() -> uint64_t { return decimal(_output++); }
|
auto natural() -> uint64_t { return natural(_output++); }
|
||||||
auto real() -> double { return real(_output++); }
|
auto real() -> double { return real(_output++); }
|
||||||
auto text() -> string { return text(_output++); }
|
auto text() -> string { return text(_output++); }
|
||||||
auto data() -> vector<uint8_t> { return data(_output++); }
|
auto data() -> vector<uint8_t> { return data(_output++); }
|
||||||
|
|
|
@ -95,7 +95,7 @@ auto Response::setHead() -> bool {
|
||||||
else if(response.ibeginsWith("HTTP/1.1 ")) response.iltrim("HTTP/1.1 ", 1L);
|
else if(response.ibeginsWith("HTTP/1.1 ")) response.iltrim("HTTP/1.1 ", 1L);
|
||||||
else return false;
|
else return false;
|
||||||
|
|
||||||
setResponseType(decimal(response));
|
setResponseType(natural(response));
|
||||||
|
|
||||||
for(auto& header : headers) {
|
for(auto& header : headers) {
|
||||||
if(header.beginsWith(" ") || header.beginsWith("\t")) continue;
|
if(header.beginsWith(" ") || header.beginsWith("\t")) continue;
|
||||||
|
@ -156,7 +156,7 @@ auto Response::hasBody() const -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Response::findContentLength() const -> unsigned {
|
auto Response::findContentLength() const -> unsigned {
|
||||||
if(auto contentLength = header["Content-Length"]) return contentLength.value().decimal();
|
if(auto contentLength = header["Content-Length"]) return contentLength.value().natural();
|
||||||
if(_body) return _body.size();
|
if(_body) return _body.size();
|
||||||
if(hasData()) return data().size();
|
if(hasData()) return data().size();
|
||||||
if(hasFile()) return file::size(file());
|
if(hasFile()) return file::size(file());
|
||||||
|
|
|
@ -83,7 +83,7 @@ auto Role::download(signed fd, Message& message) -> bool {
|
||||||
headReceived = true;
|
headReceived = true;
|
||||||
if(!message.setHead()) return false;
|
if(!message.setHead()) return false;
|
||||||
chunked = message.header["Transfer-Encoding"].value().iequals("chunked");
|
chunked = message.header["Transfer-Encoding"].value().iequals("chunked");
|
||||||
contentLength = message.header["Content-Length"].value().decimal();
|
contentLength = message.header["Content-Length"].value().natural();
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -12,9 +12,8 @@
|
||||||
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
||||||
//- floating-point usage is not portable across different implementations
|
//- floating-point usage is not portable across different implementations
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/traits.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
auto string::integer() const -> intmax_t {
|
auto string::integer() const -> intmax {
|
||||||
if(beginsWith("0b") || beginsWith("0B")) return nall::binary(data());
|
if(beginsWith("0b") || beginsWith("0B")) return nall::binary(data());
|
||||||
if(beginsWith("0o") || beginsWith("0O")) return nall::octal(data());
|
if(beginsWith("0o") || beginsWith("0O")) return nall::octal(data());
|
||||||
if(beginsWith("0x") || beginsWith("0X")) return nall::hex(data());
|
if(beginsWith("0x") || beginsWith("0X")) return nall::hex(data());
|
||||||
return nall::integer(data());
|
return nall::integer(data());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto string::decimal() const -> uintmax_t {
|
auto string::natural() const -> uintmax {
|
||||||
if(beginsWith("0b") || beginsWith("0B")) return nall::binary(data());
|
if(beginsWith("0b") || beginsWith("0B")) return nall::binary(data());
|
||||||
if(beginsWith("0o") || beginsWith("0O")) return nall::octal(data());
|
if(beginsWith("0o") || beginsWith("0O")) return nall::octal(data());
|
||||||
if(beginsWith("0x") || beginsWith("0X")) return nall::hex(data());
|
if(beginsWith("0x") || beginsWith("0X")) return nall::hex(data());
|
||||||
return nall::decimal(data());
|
return nall::natural(data());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto string::real() const -> double {
|
auto string::real() const -> double {
|
||||||
|
|
|
@ -150,8 +150,8 @@ public:
|
||||||
auto end() const -> const char* { return &data()[size()]; }
|
auto end() const -> const char* { return &data()[size()]; }
|
||||||
|
|
||||||
//atoi.hpp
|
//atoi.hpp
|
||||||
inline auto integer() const -> intmax_t;
|
inline auto integer() const -> intmax;
|
||||||
inline auto decimal() const -> uintmax_t;
|
inline auto natural() const -> uintmax;
|
||||||
inline auto real() const -> double;
|
inline auto real() const -> double;
|
||||||
|
|
||||||
//core.hpp
|
//core.hpp
|
||||||
|
|
|
@ -32,7 +32,7 @@ auto string::format(const nall::format& params) -> type& {
|
||||||
};
|
};
|
||||||
if(!isNumeric(&data[x + 1], &data[y - 1])) { x++; continue; }
|
if(!isNumeric(&data[x + 1], &data[y - 1])) { x++; continue; }
|
||||||
|
|
||||||
unsigned index = nall::decimal(&data[x + 1]);
|
unsigned index = nall::natural(&data[x + 1]);
|
||||||
if(index >= params.size()) { x++; continue; }
|
if(index >= params.size()) { x++; continue; }
|
||||||
|
|
||||||
unsigned sourceSize = y - x;
|
unsigned sourceSize = y - x;
|
||||||
|
|
|
@ -41,10 +41,10 @@ auto ManagedNode::_evaluate(string query) const -> bool {
|
||||||
switch(comparator) {
|
switch(comparator) {
|
||||||
case Comparator::EQ: if(data.match(side(1)) == true) continue; break;
|
case Comparator::EQ: if(data.match(side(1)) == true) continue; break;
|
||||||
case Comparator::NE: if(data.match(side(1)) == false) continue; break;
|
case Comparator::NE: if(data.match(side(1)) == false) continue; break;
|
||||||
case Comparator::LT: if(data.decimal() < side(1).decimal()) continue; break;
|
case Comparator::LT: if(data.natural() < side(1).natural()) continue; break;
|
||||||
case Comparator::LE: if(data.decimal() <= side(1).decimal()) continue; break;
|
case Comparator::LE: if(data.natural() <= side(1).natural()) continue; break;
|
||||||
case Comparator::GT: if(data.decimal() > side(1).decimal()) continue; break;
|
case Comparator::GT: if(data.natural() > side(1).natural()) continue; break;
|
||||||
case Comparator::GE: if(data.decimal() >= side(1).decimal()) continue; break;
|
case Comparator::GE: if(data.natural() >= side(1).natural()) continue; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -65,10 +65,10 @@ auto ManagedNode::_find(const string& query) const -> vector<Node> {
|
||||||
name = p(0);
|
name = p(0);
|
||||||
if(p(1).find("-")) {
|
if(p(1).find("-")) {
|
||||||
p = p(1).split("-", 1L);
|
p = p(1).split("-", 1L);
|
||||||
lo = p(0).empty() ? 0u : p(0).decimal();
|
lo = p(0).empty() ? 0u : p(0).natural();
|
||||||
hi = p(1).empty() ? ~0u : p(1).decimal();
|
hi = p(1).empty() ? ~0u : p(1).natural();
|
||||||
} else {
|
} else {
|
||||||
lo = hi = p(1).decimal();
|
lo = hi = p(1).natural();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,8 @@ struct Node {
|
||||||
|
|
||||||
auto text() const -> string { return value().strip(); }
|
auto text() const -> string { return value().strip(); }
|
||||||
auto boolean() const -> bool { return text() == "true"; }
|
auto boolean() const -> bool { return text() == "true"; }
|
||||||
auto integer() const -> intmax_t { return text().integer(); }
|
auto integer() const -> intmax { return text().integer(); }
|
||||||
auto decimal() const -> uintmax_t { return text().decimal(); }
|
auto natural() const -> uintmax { return text().natural(); }
|
||||||
|
|
||||||
auto setName(const string& name = "") -> Node& { shared->_name = name; return *this; }
|
auto setName(const string& name = "") -> Node& { shared->_name = name; return *this; }
|
||||||
auto setValue(const string& value = "") -> Node& { shared->_value = value; return *this; }
|
auto setValue(const string& value = "") -> Node& { shared->_value = value; return *this; }
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
#include <nall/serializer.hpp>
|
#include <nall/serializer.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/traits.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
|
@ -209,6 +208,8 @@ using int61 = nall::int_t<61>;
|
||||||
using int62 = nall::int_t<62>;
|
using int62 = nall::int_t<62>;
|
||||||
using int63 = nall::int_t<63>;
|
using int63 = nall::int_t<63>;
|
||||||
using int64 = int64_t;
|
using int64 = int64_t;
|
||||||
|
using intmax = intmax_t;
|
||||||
|
using intptr = intptr_t;
|
||||||
|
|
||||||
using uint1 = nall::uint_t<1>;
|
using uint1 = nall::uint_t<1>;
|
||||||
using uint2 = nall::uint_t<2>;
|
using uint2 = nall::uint_t<2>;
|
||||||
|
@ -274,6 +275,8 @@ using uint61 = nall::uint_t<61>;
|
||||||
using uint62 = nall::uint_t<62>;
|
using uint62 = nall::uint_t<62>;
|
||||||
using uint63 = nall::uint_t<63>;
|
using uint63 = nall::uint_t<63>;
|
||||||
using uint64 = uint64_t;
|
using uint64 = uint64_t;
|
||||||
|
using uintmax = uintmax_t;
|
||||||
|
using uintptr = uintptr_t;
|
||||||
|
|
||||||
#if defined(__SIZEOF_INT128__)
|
#if defined(__SIZEOF_INT128__)
|
||||||
using int128 = int128_t;
|
using int128 = int128_t;
|
||||||
|
|
|
@ -18,15 +18,15 @@ struct InputMouseRawInput {
|
||||||
} ms;
|
} ms;
|
||||||
|
|
||||||
auto acquire() -> bool {
|
auto acquire() -> bool {
|
||||||
if(mouseAcquired == false) {
|
if(!mouseAcquired) {
|
||||||
mouseAcquired = true;
|
mouseAcquired = true;
|
||||||
ShowCursor(false);
|
ShowCursor(false);
|
||||||
}
|
}
|
||||||
return true;
|
return acquired();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto release() -> bool {
|
auto release() -> bool {
|
||||||
if(mouseAcquired == true) {
|
if(mouseAcquired) {
|
||||||
mouseAcquired = false;
|
mouseAcquired = false;
|
||||||
ReleaseCapture();
|
ReleaseCapture();
|
||||||
ClipCursor(nullptr);
|
ClipCursor(nullptr);
|
||||||
|
@ -36,7 +36,7 @@ struct InputMouseRawInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto acquired() -> bool {
|
auto acquired() -> bool {
|
||||||
if(mouseAcquired == true) {
|
if(mouseAcquired) {
|
||||||
SetFocus((HWND)handle);
|
SetFocus((HWND)handle);
|
||||||
SetCapture((HWND)handle);
|
SetCapture((HWND)handle);
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
|
@ -19,7 +19,7 @@ auto OpenGL::shader(const string& pathname) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto node : document["input"]) {
|
for(auto node : document["input"]) {
|
||||||
if(node.name() == "history") historySize = node.decimal();
|
if(node.name() == "history") historySize = node.natural();
|
||||||
if(node.name() == "format") format = glrFormat(node.text());
|
if(node.name() == "format") format = glrFormat(node.text());
|
||||||
if(node.name() == "filter") filter = glrFilter(node.text());
|
if(node.name() == "filter") filter = glrFilter(node.text());
|
||||||
if(node.name() == "wrap") wrap = glrWrap(node.text());
|
if(node.name() == "wrap") wrap = glrWrap(node.text());
|
||||||
|
@ -29,11 +29,11 @@ auto OpenGL::shader(const string& pathname) -> void {
|
||||||
string text = node.text();
|
string text = node.text();
|
||||||
if(node.name() == "width") {
|
if(node.name() == "width") {
|
||||||
if(text.endsWith("%")) relativeWidth = real(text.rtrim("%", 1L)) / 100.0;
|
if(text.endsWith("%")) relativeWidth = real(text.rtrim("%", 1L)) / 100.0;
|
||||||
else absoluteWidth = text.decimal();
|
else absoluteWidth = text.natural();
|
||||||
}
|
}
|
||||||
if(node.name() == "height") {
|
if(node.name() == "height") {
|
||||||
if(text.endsWith("%")) relativeHeight = real(text.rtrim("%", 1L)) / 100.0;
|
if(text.endsWith("%")) relativeHeight = real(text.rtrim("%", 1L)) / 100.0;
|
||||||
else absoluteHeight = text.decimal();
|
else absoluteHeight = text.natural();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin
|
||||||
|
|
||||||
string w = node["width"].text(), h = node["height"].text();
|
string w = node["width"].text(), h = node["height"].text();
|
||||||
if(w.endsWith("%")) relativeWidth = real(w.rtrim("%", 1L)) / 100.0;
|
if(w.endsWith("%")) relativeWidth = real(w.rtrim("%", 1L)) / 100.0;
|
||||||
else absoluteWidth = w.decimal();
|
else absoluteWidth = w.natural();
|
||||||
if(h.endsWith("%")) relativeHeight = real(h.rtrim("%", 1L)) / 100.0;
|
if(h.endsWith("%")) relativeHeight = real(h.rtrim("%", 1L)) / 100.0;
|
||||||
else absoluteHeight = h.decimal();
|
else absoluteHeight = h.natural();
|
||||||
|
|
||||||
format = glrFormat(node["format"].text());
|
format = glrFormat(node["format"].text());
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ auto Cartridge::loadSatellaview() -> void {
|
||||||
auto rom = document["cartridge/rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
|
|
||||||
if(rom["name"]) {
|
if(rom["name"]) {
|
||||||
unsigned size = rom["size"].decimal();
|
unsigned size = rom["size"].natural();
|
||||||
satellaviewcartridge.memory.map(allocate<uint8>(size, 0xff), size);
|
satellaviewcartridge.memory.map(allocate<uint8>(size, 0xff), size);
|
||||||
interface->loadRequest(ID::SatellaviewROM, rom["name"].text(), true);
|
interface->loadRequest(ID::SatellaviewROM, rom["name"].text(), true);
|
||||||
|
|
||||||
|
@ -154,13 +154,13 @@ auto Cartridge::loadSufamiTurboA() -> void {
|
||||||
auto ram = document["cartridge/ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
if(rom["name"]) {
|
if(rom["name"]) {
|
||||||
unsigned size = rom["size"].decimal();
|
unsigned size = rom["size"].natural();
|
||||||
sufamiturboA.rom.map(allocate<uint8>(size, 0xff), size);
|
sufamiturboA.rom.map(allocate<uint8>(size, 0xff), size);
|
||||||
interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].text(), true);
|
interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].text(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ram["name"]) {
|
if(ram["name"]) {
|
||||||
unsigned size = ram["size"].decimal();
|
unsigned size = ram["size"].natural();
|
||||||
sufamiturboA.ram.map(allocate<uint8>(size, 0xff), size);
|
sufamiturboA.ram.map(allocate<uint8>(size, 0xff), size);
|
||||||
interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].text(), false);
|
interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].text(), false);
|
||||||
memory.append({ID::SufamiTurboSlotARAM, ram["name"].text()});
|
memory.append({ID::SufamiTurboSlotARAM, ram["name"].text()});
|
||||||
|
@ -180,13 +180,13 @@ auto Cartridge::loadSufamiTurboB() -> void {
|
||||||
auto ram = document["cartridge/ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
if(rom["name"]) {
|
if(rom["name"]) {
|
||||||
unsigned size = rom["size"].decimal();
|
unsigned size = rom["size"].natural();
|
||||||
sufamiturboB.rom.map(allocate<uint8>(size, 0xff), size);
|
sufamiturboB.rom.map(allocate<uint8>(size, 0xff), size);
|
||||||
interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].text(), true);
|
interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].text(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ram["name"]) {
|
if(ram["name"]) {
|
||||||
unsigned size = ram["size"].decimal();
|
unsigned size = ram["size"].natural();
|
||||||
sufamiturboB.ram.map(allocate<uint8>(size, 0xff), size);
|
sufamiturboB.ram.map(allocate<uint8>(size, 0xff), size);
|
||||||
interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].text(), false);
|
interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].text(), false);
|
||||||
memory.append({ID::SufamiTurboSlotBRAM, ram["name"].text()});
|
memory.append({ID::SufamiTurboSlotBRAM, ram["name"].text()});
|
||||||
|
|
|
@ -39,14 +39,14 @@ auto Cartridge::parseMarkup(const string& markup) -> void {
|
||||||
|
|
||||||
auto Cartridge::parseMarkupMap(Mapping& m, Markup::Node map) -> void {
|
auto Cartridge::parseMarkupMap(Mapping& m, Markup::Node map) -> void {
|
||||||
m.addr = map["address"].text();
|
m.addr = map["address"].text();
|
||||||
m.size = map["size"].decimal();
|
m.size = map["size"].natural();
|
||||||
m.base = map["base"].decimal();
|
m.base = map["base"].natural();
|
||||||
m.mask = map["mask"].decimal();
|
m.mask = map["mask"].natural();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, unsigned id, bool writable) -> void {
|
auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, unsigned id, bool writable) -> void {
|
||||||
string name = node["name"].text();
|
string name = node["name"].text();
|
||||||
unsigned size = node["size"].decimal();
|
unsigned size = node["size"].natural();
|
||||||
ram.map(allocate<uint8>(size, 0xff), size);
|
ram.map(allocate<uint8>(size, 0xff), size);
|
||||||
if(name) {
|
if(name) {
|
||||||
interface->loadRequest(id, name, !writable); //treat ROM as required; RAM as optional
|
interface->loadRequest(id, name, !writable); //treat ROM as required; RAM as optional
|
||||||
|
@ -78,7 +78,7 @@ auto Cartridge::parseMarkupCartridge(Markup::Node root) -> void {
|
||||||
auto Cartridge::parseMarkupICD2(Markup::Node root) -> void {
|
auto Cartridge::parseMarkupICD2(Markup::Node root) -> void {
|
||||||
hasSuperGameBoySlot = true;
|
hasSuperGameBoySlot = true;
|
||||||
hasICD2 = true;
|
hasICD2 = true;
|
||||||
icd2.revision = max(1, root["revision"].decimal());
|
icd2.revision = max(1, root["revision"].natural());
|
||||||
|
|
||||||
GameBoy::cartridge.load_empty(GameBoy::System::Revision::SuperGameBoy);
|
GameBoy::cartridge.load_empty(GameBoy::System::Revision::SuperGameBoy);
|
||||||
interface->loadRequest(ID::SuperGameBoy, "Game Boy", "gb", false);
|
interface->loadRequest(ID::SuperGameBoy, "Game Boy", "gb", false);
|
||||||
|
@ -188,7 +188,7 @@ auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
|
||||||
hasEvent = true;
|
hasEvent = true;
|
||||||
|
|
||||||
for(auto node : root.find("rom")) {
|
for(auto node : root.find("rom")) {
|
||||||
unsigned id = node["id"].decimal();
|
unsigned id = node["id"].natural();
|
||||||
if(id > 3) continue;
|
if(id > 3) continue;
|
||||||
parseMarkupMemory(event.rom[id], node, ID::EventROM0 + id, false);
|
parseMarkupMemory(event.rom[id], node, ID::EventROM0 + id, false);
|
||||||
}
|
}
|
||||||
|
@ -200,8 +200,8 @@ auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
|
||||||
|
|
||||||
event.revision = root["revision"].text() == "B" ? 2 : 1;
|
event.revision = root["revision"].text() == "B" ? 2 : 1;
|
||||||
lstring part = root["timer"].text().split(":", 1L);
|
lstring part = root["timer"].text().split(":", 1L);
|
||||||
if(part.size() == 1) event.timer = decimal(part(0));
|
if(part.size() == 1) event.timer = part(0).natural();
|
||||||
if(part.size() == 2) event.timer = decimal(part(0)) * 60 + decimal(part(1));
|
if(part.size() == 2) event.timer = part(0).natural() * 60 + part(1).natural();
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
for(auto node : root.find("map")) {
|
||||||
if(node["id"].text() == "rom") {
|
if(node["id"].text() == "rom") {
|
||||||
|
@ -338,7 +338,7 @@ auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, unsigned roms) -> void
|
||||||
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
||||||
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
||||||
|
|
||||||
hitachidsp.Frequency = root["frequency"].decimal();
|
hitachidsp.Frequency = root["frequency"].natural();
|
||||||
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
||||||
hitachidsp.Roms = roms;
|
hitachidsp.Roms = roms;
|
||||||
|
|
||||||
|
@ -380,7 +380,7 @@ auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void {
|
||||||
for(auto& word : necdsp.dataROM) word = 0x0000;
|
for(auto& word : necdsp.dataROM) word = 0x0000;
|
||||||
for(auto& word : necdsp.dataRAM) word = 0x0000;
|
for(auto& word : necdsp.dataRAM) word = 0x0000;
|
||||||
|
|
||||||
necdsp.frequency = root["frequency"].decimal();
|
necdsp.frequency = root["frequency"].natural();
|
||||||
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
||||||
necdsp.revision
|
necdsp.revision
|
||||||
= root["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725
|
= root["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725
|
||||||
|
@ -417,7 +417,7 @@ auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void {
|
||||||
Mapping m({&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
Mapping m({&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
||||||
parseMarkupMap(m, node);
|
parseMarkupMap(m, node);
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
necdsp.Select = node["select"].decimal();
|
necdsp.Select = node["select"].natural();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node["id"].text() == "ram") {
|
if(node["id"].text() == "ram") {
|
||||||
|
|
|
@ -6,9 +6,21 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
ArmDSP armdsp;
|
ArmDSP armdsp;
|
||||||
|
|
||||||
void ArmDSP::Enter() { armdsp.enter(); }
|
ArmDSP::ArmDSP() {
|
||||||
|
programROM = new uint8[128 * 1024];
|
||||||
|
dataROM = new uint8[32 * 1024];
|
||||||
|
programRAM = new uint8[16 * 1024];
|
||||||
|
}
|
||||||
|
|
||||||
void ArmDSP::enter() {
|
ArmDSP::~ArmDSP() {
|
||||||
|
delete[] programROM;
|
||||||
|
delete[] dataROM;
|
||||||
|
delete[] programRAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ArmDSP::Enter() -> void { armdsp.enter(); }
|
||||||
|
|
||||||
|
auto ArmDSP::enter() -> void {
|
||||||
//reset hold delay
|
//reset hold delay
|
||||||
while(bridge.reset) {
|
while(bridge.reset) {
|
||||||
step(1);
|
step(1);
|
||||||
|
@ -37,7 +49,7 @@ void ArmDSP::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::step(unsigned clocks) {
|
auto ArmDSP::step(uint clocks) -> void {
|
||||||
if(bridge.timer && --bridge.timer == 0);
|
if(bridge.timer && --bridge.timer == 0);
|
||||||
Coprocessor::step(clocks);
|
Coprocessor::step(clocks);
|
||||||
synchronize_cpu();
|
synchronize_cpu();
|
||||||
|
@ -47,7 +59,7 @@ void ArmDSP::step(unsigned clocks) {
|
||||||
//3800-3807 mirrored throughout
|
//3800-3807 mirrored throughout
|
||||||
//a0 ignored
|
//a0 ignored
|
||||||
|
|
||||||
uint8 ArmDSP::mmio_read(unsigned addr) {
|
auto ArmDSP::mmio_read(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
|
|
||||||
uint8 data = 0x00;
|
uint8 data = 0x00;
|
||||||
|
@ -71,7 +83,7 @@ uint8 ArmDSP::mmio_read(unsigned addr) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::mmio_write(unsigned addr, uint8 data) {
|
auto ArmDSP::mmio_write(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
|
|
||||||
addr &= 0xff06;
|
addr &= 0xff06;
|
||||||
|
@ -83,30 +95,30 @@ void ArmDSP::mmio_write(unsigned addr, uint8 data) {
|
||||||
|
|
||||||
if(addr == 0x3804) {
|
if(addr == 0x3804) {
|
||||||
data &= 1;
|
data &= 1;
|
||||||
if(!bridge.reset && data) arm_reset();
|
if(!bridge.reset && data) resetARM();
|
||||||
bridge.reset = data;
|
bridge.reset = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::init() {
|
auto ArmDSP::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::load() {
|
auto ArmDSP::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::unload() {
|
auto ArmDSP::unload() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::power() {
|
auto ArmDSP::power() -> void {
|
||||||
for(unsigned n = 0; n < 16 * 1024; n++) programRAM[n] = random(0x00);
|
for(auto n : range(16 * 1024)) programRAM[n] = random(0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::reset() {
|
auto ArmDSP::reset() -> void {
|
||||||
bridge.reset = false;
|
bridge.reset = false;
|
||||||
arm_reset();
|
resetARM();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::arm_reset() {
|
auto ArmDSP::resetARM() -> void {
|
||||||
create(ArmDSP::Enter, 21477272);
|
create(ArmDSP::Enter, 21477272);
|
||||||
ARM::power();
|
ARM::power();
|
||||||
|
|
||||||
|
@ -118,16 +130,4 @@ void ArmDSP::arm_reset() {
|
||||||
bridge.armtocpu.ready = false;
|
bridge.armtocpu.ready = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArmDSP::ArmDSP() {
|
|
||||||
programROM = new uint8[128 * 1024];
|
|
||||||
dataROM = new uint8[32 * 1024];
|
|
||||||
programRAM = new uint8[16 * 1024];
|
|
||||||
}
|
|
||||||
|
|
||||||
ArmDSP::~ArmDSP() {
|
|
||||||
delete[] programROM;
|
|
||||||
delete[] dataROM;
|
|
||||||
delete[] programRAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
//ARMv3 (ARM60)
|
//ARMv3 (ARM60)
|
||||||
|
|
||||||
struct ArmDSP : Processor::ARM, Coprocessor {
|
struct ArmDSP : Processor::ARM, Coprocessor {
|
||||||
uint8* programROM;
|
|
||||||
uint8* dataROM;
|
|
||||||
uint8* programRAM;
|
|
||||||
|
|
||||||
#include "registers.hpp"
|
#include "registers.hpp"
|
||||||
|
|
||||||
static void Enter();
|
|
||||||
void enter();
|
|
||||||
|
|
||||||
void step(unsigned clocks) override;
|
|
||||||
void bus_idle() override;
|
|
||||||
uint32 bus_read(unsigned mode, uint32 addr) override;
|
|
||||||
void bus_write(unsigned mode, uint32 addr, uint32 word) override;
|
|
||||||
|
|
||||||
uint8 mmio_read(unsigned addr);
|
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
void init();
|
|
||||||
void load();
|
|
||||||
void unload();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
void arm_reset();
|
|
||||||
|
|
||||||
nall::vector<uint8> firmware();
|
|
||||||
void serialize(serializer&);
|
|
||||||
|
|
||||||
ArmDSP();
|
ArmDSP();
|
||||||
~ArmDSP();
|
~ArmDSP();
|
||||||
|
|
||||||
|
static auto Enter() -> void;
|
||||||
|
auto enter() -> void;
|
||||||
|
|
||||||
|
auto step(uint clocks) -> void override;
|
||||||
|
auto bus_idle() -> void override;
|
||||||
|
auto bus_read(uint mode, uint32 addr) -> uint32 override;
|
||||||
|
auto bus_write(uint mode, uint32 addr, uint32 word) -> void override;
|
||||||
|
|
||||||
|
auto mmio_read(uint addr) -> uint8;
|
||||||
|
auto mmio_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
auto resetARM() -> void;
|
||||||
|
|
||||||
|
auto firmware() const -> nall::vector<uint8>;
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
uint8* programROM;
|
||||||
|
uint8* dataROM;
|
||||||
|
uint8* programRAM;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ArmDSP armdsp;
|
extern ArmDSP armdsp;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
//note: timings are completely unverified
|
//note: timings are completely unverified
|
||||||
//due to the ST018 chip design (on-die ROM), testing is nearly impossible
|
//due to the ST018 chip design (on-die ROM), testing is nearly impossible
|
||||||
|
|
||||||
void ArmDSP::bus_idle() {
|
auto ArmDSP::bus_idle() -> void {
|
||||||
step(1);
|
step(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ArmDSP::bus_read(unsigned mode, uint32 addr) {
|
auto ArmDSP::bus_read(unsigned mode, uint32 addr) -> uint32 {
|
||||||
step(1);
|
step(1);
|
||||||
|
|
||||||
static auto memory = [&](const uint8 *memory, unsigned mode, uint32 addr) -> uint32 {
|
static auto memory = [&](const uint8* memory, uint mode, uint32 addr) -> uint32 {
|
||||||
if(mode & Word) {
|
if(mode & Word) {
|
||||||
memory += addr & ~3;
|
memory += addr & ~3;
|
||||||
return memory[0] << 0 | memory[1] << 8 | memory[2] << 16 | memory[3] << 24;
|
return memory[0] << 0 | memory[1] << 8 | memory[2] << 16 | memory[3] << 24;
|
||||||
|
@ -46,10 +46,10 @@ uint32 ArmDSP::bus_read(unsigned mode, uint32 addr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::bus_write(unsigned mode, uint32 addr, uint32 word) {
|
auto ArmDSP::bus_write(uint mode, uint32 addr, uint32 word) -> void {
|
||||||
step(1);
|
step(1);
|
||||||
|
|
||||||
static auto memory = [](uint8 *memory, unsigned mode, uint32 addr, uint32 word) {
|
static auto memory = [](uint8* memory, uint mode, uint32 addr, uint32 word) {
|
||||||
if(mode & Word) {
|
if(mode & Word) {
|
||||||
memory += addr & ~3;
|
memory += addr & ~3;
|
||||||
*memory++ = word >> 0;
|
*memory++ = word >> 0;
|
||||||
|
|
|
@ -11,7 +11,7 @@ struct Bridge {
|
||||||
bool ready;
|
bool ready;
|
||||||
bool signal;
|
bool signal;
|
||||||
|
|
||||||
uint8 status() const {
|
auto status() const -> uint8 {
|
||||||
return (ready << 7) | (cputoarm.ready << 3) | (signal << 2) | (armtocpu.ready << 0);
|
return (ready << 7) | (cputoarm.ready << 3) | (signal << 2) | (armtocpu.ready << 0);
|
||||||
}
|
}
|
||||||
} bridge;
|
} bridge;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
nall::vector<uint8> ArmDSP::firmware() {
|
auto ArmDSP::firmware() const -> nall::vector<uint8> {
|
||||||
nall::vector<uint8> buffer;
|
nall::vector<uint8> buffer;
|
||||||
if(!cartridge.hasARMDSP()) return buffer;
|
if(!cartridge.hasARMDSP()) return buffer;
|
||||||
buffer.reserve(128 * 1024 + 32 * 1024);
|
buffer.reserve(128 * 1024 + 32 * 1024);
|
||||||
for(unsigned n = 0; n < 128 * 1024; n++) buffer.append(programROM[n]);
|
for(auto n : range(128 * 1024)) buffer.append(programROM[n]);
|
||||||
for(unsigned n = 0; n < 32 * 1024; n++) buffer.append(dataROM[n]);
|
for(auto n : range( 32 * 1024)) buffer.append(dataROM[n]);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArmDSP::serialize(serializer& s) {
|
auto ArmDSP::serialize(serializer& s) -> void {
|
||||||
ARM::serialize(s);
|
ARM::serialize(s);
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
EpsonRTC epsonrtc;
|
EpsonRTC epsonrtc;
|
||||||
|
|
||||||
void EpsonRTC::Enter() {
|
auto EpsonRTC::Enter() -> void {
|
||||||
epsonrtc.enter();
|
epsonrtc.enter();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::enter() {
|
auto EpsonRTC::enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
|
@ -36,12 +36,10 @@ void EpsonRTC::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::init() {
|
auto EpsonRTC::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::load() {
|
auto EpsonRTC::load() -> void {
|
||||||
return;
|
|
||||||
|
|
||||||
secondlo = 0;
|
secondlo = 0;
|
||||||
secondhi = 0;
|
secondhi = 0;
|
||||||
batteryfailure = 1;
|
batteryfailure = 1;
|
||||||
|
@ -82,13 +80,13 @@ void EpsonRTC::load() {
|
||||||
test = 0;
|
test = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::unload() {
|
auto EpsonRTC::unload() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::power() {
|
auto EpsonRTC::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::reset() {
|
auto EpsonRTC::reset() -> void {
|
||||||
create(EpsonRTC::Enter, 32768 * 64);
|
create(EpsonRTC::Enter, 32768 * 64);
|
||||||
|
|
||||||
clocks = 0;
|
clocks = 0;
|
||||||
|
@ -102,19 +100,19 @@ void EpsonRTC::reset() {
|
||||||
holdtick = 0;
|
holdtick = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::sync() {
|
auto EpsonRTC::sync() -> void {
|
||||||
time_t systime = time(0);
|
time_t systime = time(0);
|
||||||
tm* timeinfo = localtime(&systime);
|
tm* timeinfo = localtime(&systime);
|
||||||
|
|
||||||
unsigned second = min(59, timeinfo->tm_sec);
|
uint second = min(59, timeinfo->tm_sec);
|
||||||
secondlo = second % 10;
|
secondlo = second % 10;
|
||||||
secondhi = second / 10;
|
secondhi = second / 10;
|
||||||
|
|
||||||
unsigned minute = timeinfo->tm_min;
|
uint minute = timeinfo->tm_min;
|
||||||
minutelo = minute % 10;
|
minutelo = minute % 10;
|
||||||
minutehi = minute / 10;
|
minutehi = minute / 10;
|
||||||
|
|
||||||
unsigned hour = timeinfo->tm_hour;
|
uint hour = timeinfo->tm_hour;
|
||||||
if(atime) {
|
if(atime) {
|
||||||
hourlo = hour % 10;
|
hourlo = hour % 10;
|
||||||
hourhi = hour / 10;
|
hourhi = hour / 10;
|
||||||
|
@ -126,15 +124,15 @@ void EpsonRTC::sync() {
|
||||||
hourhi = hour / 10;
|
hourhi = hour / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned day = timeinfo->tm_mday;
|
uint day = timeinfo->tm_mday;
|
||||||
daylo = day % 10;
|
daylo = day % 10;
|
||||||
dayhi = day / 10;
|
dayhi = day / 10;
|
||||||
|
|
||||||
unsigned month = 1 + timeinfo->tm_mon;
|
uint month = 1 + timeinfo->tm_mon;
|
||||||
monthlo = month % 10;
|
monthlo = month % 10;
|
||||||
monthhi = month / 10;
|
monthhi = month / 10;
|
||||||
|
|
||||||
unsigned year = timeinfo->tm_year % 100;
|
uint year = timeinfo->tm_year % 100;
|
||||||
yearlo = year % 10;
|
yearlo = year % 10;
|
||||||
yearhi = year / 10;
|
yearhi = year / 10;
|
||||||
|
|
||||||
|
@ -143,7 +141,7 @@ void EpsonRTC::sync() {
|
||||||
resync = true; //alert program that time has changed
|
resync = true; //alert program that time has changed
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 EpsonRTC::read(unsigned addr) {
|
auto EpsonRTC::read(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
addr &= 3;
|
addr &= 3;
|
||||||
|
|
||||||
|
@ -166,7 +164,7 @@ uint8 EpsonRTC::read(unsigned addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::write(unsigned addr, uint8 data) {
|
auto EpsonRTC::write(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
addr &= 3, data &= 15;
|
addr &= 3, data &= 15;
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
//Epson RTC-4513 Real-Time Clock
|
//Epson RTC-4513 Real-Time Clock
|
||||||
|
|
||||||
struct EpsonRTC : Coprocessor {
|
struct EpsonRTC : Coprocessor {
|
||||||
static void Enter();
|
static auto Enter() -> void;
|
||||||
void enter();
|
auto enter() -> void;
|
||||||
|
|
||||||
void init();
|
auto init() -> void;
|
||||||
void load();
|
auto load() -> void;
|
||||||
void unload();
|
auto unload() -> void;
|
||||||
void power();
|
auto power() -> void;
|
||||||
void reset();
|
auto reset() -> void;
|
||||||
void sync();
|
auto sync() -> void;
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
auto read(uint addr) -> uint8;
|
||||||
void write(unsigned addr, uint8 data);
|
auto write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
void serialize(serializer&);
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
uint21 clocks;
|
uint21 clocks;
|
||||||
unsigned seconds;
|
uint seconds;
|
||||||
|
|
||||||
uint2 chipselect;
|
uint2 chipselect;
|
||||||
enum class State : unsigned { Mode, Seek, Read, Write } state;
|
enum class State : uint { Mode, Seek, Read, Write } state;
|
||||||
uint4 mdr;
|
uint4 mdr;
|
||||||
uint4 offset;
|
uint4 offset;
|
||||||
unsigned wait;
|
uint wait;
|
||||||
uint1 ready;
|
uint1 ready;
|
||||||
uint1 holdtick;
|
uint1 holdtick;
|
||||||
|
|
||||||
|
@ -67,25 +67,25 @@ struct EpsonRTC : Coprocessor {
|
||||||
uint1 test;
|
uint1 test;
|
||||||
|
|
||||||
//memory.cpp
|
//memory.cpp
|
||||||
void rtc_reset();
|
auto rtc_reset() -> void;
|
||||||
uint4 rtc_read(uint4 addr);
|
auto rtc_read(uint4 addr) -> uint4;
|
||||||
void rtc_write(uint4 addr, uint4 data);
|
auto rtc_write(uint4 addr, uint4 data) -> void;
|
||||||
|
|
||||||
void load(const uint8* data);
|
auto load(const uint8* data) -> void;
|
||||||
void save(uint8* data);
|
auto save(uint8* data) -> void;
|
||||||
|
|
||||||
//time.cpp
|
//time.cpp
|
||||||
void irq(uint2 period);
|
auto irq(uint2 period) -> void;
|
||||||
void duty();
|
auto duty() -> void;
|
||||||
void round_seconds();
|
auto round_seconds() -> void;
|
||||||
void tick();
|
auto tick() -> void;
|
||||||
|
|
||||||
void tick_second();
|
auto tick_second() -> void;
|
||||||
void tick_minute();
|
auto tick_minute() -> void;
|
||||||
void tick_hour();
|
auto tick_hour() -> void;
|
||||||
void tick_day();
|
auto tick_day() -> void;
|
||||||
void tick_month();
|
auto tick_month() -> void;
|
||||||
void tick_year();
|
auto tick_year() -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EpsonRTC epsonrtc;
|
extern EpsonRTC epsonrtc;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void EpsonRTC::rtc_reset() {
|
auto EpsonRTC::rtc_reset() -> void {
|
||||||
state = State::Mode;
|
state = State::Mode;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ void EpsonRTC::rtc_reset() {
|
||||||
test = 0;
|
test = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint4 EpsonRTC::rtc_read(uint4 addr) {
|
auto EpsonRTC::rtc_read(uint4 addr) -> uint4 {
|
||||||
switch(addr) { default:
|
switch(addr) { default:
|
||||||
case 0: return secondlo;
|
case 0: return secondlo;
|
||||||
case 1: return secondhi | batteryfailure << 3;
|
case 1: return secondhi | batteryfailure << 3;
|
||||||
|
@ -32,7 +32,7 @@ uint4 EpsonRTC::rtc_read(uint4 addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::rtc_write(uint4 addr, uint4 data) {
|
auto EpsonRTC::rtc_write(uint4 addr, uint4 data) -> void {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0:
|
case 0:
|
||||||
secondlo = data;
|
secondlo = data;
|
||||||
|
@ -110,7 +110,7 @@ void EpsonRTC::rtc_write(uint4 addr, uint4 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::load(const uint8* data) {
|
auto EpsonRTC::load(const uint8* data) -> void {
|
||||||
secondlo = data[0] >> 0;
|
secondlo = data[0] >> 0;
|
||||||
secondhi = data[0] >> 4;
|
secondhi = data[0] >> 4;
|
||||||
batteryfailure = data[0] >> 7;
|
batteryfailure = data[0] >> 7;
|
||||||
|
@ -151,7 +151,7 @@ void EpsonRTC::load(const uint8* data) {
|
||||||
test = data[7] >> 7;
|
test = data[7] >> 7;
|
||||||
|
|
||||||
uint64 timestamp = 0;
|
uint64 timestamp = 0;
|
||||||
for(unsigned byte = 0; byte < 8; byte++) {
|
for(auto byte : range(8)) {
|
||||||
timestamp |= data[8 + byte] << (byte * 8);
|
timestamp |= data[8 + byte] << (byte * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ void EpsonRTC::load(const uint8* data) {
|
||||||
while(diff--) tick_second();
|
while(diff--) tick_second();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::save(uint8* data) {
|
auto EpsonRTC::save(uint8* data) -> void {
|
||||||
data[0] = secondlo << 0 | secondhi << 4 | batteryfailure << 7;
|
data[0] = secondlo << 0 | secondhi << 4 | batteryfailure << 7;
|
||||||
data[1] = minutelo << 0 | minutehi << 4 | resync << 7;
|
data[1] = minutelo << 0 | minutehi << 4 | resync << 7;
|
||||||
data[2] = hourlo << 0 | hourhi << 4 | meridian << 6 | resync << 7;
|
data[2] = hourlo << 0 | hourhi << 4 | meridian << 6 | resync << 7;
|
||||||
|
@ -173,7 +173,7 @@ void EpsonRTC::save(uint8* data) {
|
||||||
data[7] = irqmask << 0 | irqduty << 1 | irqperiod << 2 | pause << 4 | stop << 5 | atime << 6 | test << 7;
|
data[7] = irqmask << 0 | irqduty << 1 | irqperiod << 2 | pause << 4 | stop << 5 | atime << 6 | test << 7;
|
||||||
|
|
||||||
uint64 timestamp = (uint64)time(0);
|
uint64 timestamp = (uint64)time(0);
|
||||||
for(unsigned byte = 0; byte < 8; byte++) {
|
for(auto byte : range(8)) {
|
||||||
data[8 + byte] = timestamp;
|
data[8 + byte] = timestamp;
|
||||||
timestamp >>= 8;
|
timestamp >>= 8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
void EpsonRTC::serialize(serializer& s) {
|
auto EpsonRTC::serialize(serializer& s) -> void {
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
s.integer(clocks);
|
s.integer(clocks);
|
||||||
s.integer(seconds);
|
s.integer(seconds);
|
||||||
|
|
||||||
s.integer(chipselect);
|
s.integer(chipselect);
|
||||||
s.integer((unsigned&)state);
|
s.integer((uint&)state);
|
||||||
s.integer(mdr);
|
s.integer(mdr);
|
||||||
s.integer(offset);
|
s.integer(offset);
|
||||||
s.integer(wait);
|
s.integer(wait);
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
void EpsonRTC::irq(uint2 period) {
|
auto EpsonRTC::irq(uint2 period) -> void {
|
||||||
if(stop || pause) return;
|
if(stop || pause) return;
|
||||||
|
|
||||||
if(period == irqperiod) irqflag = 1;
|
if(period == irqperiod) irqflag = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::duty() {
|
auto EpsonRTC::duty() -> void {
|
||||||
if(irqduty) irqflag = 0;
|
if(irqduty) irqflag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::round_seconds() {
|
auto EpsonRTC::round_seconds() -> void {
|
||||||
if(roundseconds == 0) return;
|
if(roundseconds == 0) return;
|
||||||
roundseconds = 0;
|
roundseconds = 0;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ void EpsonRTC::round_seconds() {
|
||||||
secondhi = 0;
|
secondhi = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::tick() {
|
auto EpsonRTC::tick() -> void {
|
||||||
if(stop || pause) return;
|
if(stop || pause) return;
|
||||||
|
|
||||||
if(hold) {
|
if(hold) {
|
||||||
|
@ -32,7 +32,7 @@ void EpsonRTC::tick() {
|
||||||
//below code provides bit-perfect emulation of invalid BCD values on the RTC-4513
|
//below code provides bit-perfect emulation of invalid BCD values on the RTC-4513
|
||||||
//code makes extensive use of variable-length integers (see epsonrtc.hpp for sizes)
|
//code makes extensive use of variable-length integers (see epsonrtc.hpp for sizes)
|
||||||
|
|
||||||
void EpsonRTC::tick_second() {
|
auto EpsonRTC::tick_second() -> void {
|
||||||
if(secondlo <= 8 || secondlo == 12) {
|
if(secondlo <= 8 || secondlo == 12) {
|
||||||
secondlo++;
|
secondlo++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -46,7 +46,7 @@ void EpsonRTC::tick_second() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::tick_minute() {
|
auto EpsonRTC::tick_minute() -> void {
|
||||||
if(minutelo <= 8 || minutelo == 12) {
|
if(minutelo <= 8 || minutelo == 12) {
|
||||||
minutelo++;
|
minutelo++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -60,7 +60,7 @@ void EpsonRTC::tick_minute() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::tick_hour() {
|
auto EpsonRTC::tick_hour() -> void {
|
||||||
if(atime) {
|
if(atime) {
|
||||||
if(hourhi < 2) {
|
if(hourhi < 2) {
|
||||||
if(hourlo <= 8 || hourlo == 12) {
|
if(hourlo <= 8 || hourlo == 12) {
|
||||||
|
@ -104,17 +104,17 @@ void EpsonRTC::tick_hour() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::tick_day() {
|
auto EpsonRTC::tick_day() -> void {
|
||||||
if(calendar == 0) return;
|
if(calendar == 0) return;
|
||||||
weekday = (weekday + 1) + (weekday == 6);
|
weekday = (weekday + 1) + (weekday == 6);
|
||||||
|
|
||||||
//January - December = 0x01 - 0x09; 0x10 - 0x12
|
//January - December = 0x01 - 0x09; 0x10 - 0x12
|
||||||
static const unsigned daysinmonth[32] = {
|
static const uint daysinmonth[32] = {
|
||||||
30, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30, 31, 30,
|
30, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30, 31, 30,
|
||||||
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
|
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned days = daysinmonth[monthhi << 4 | monthlo];
|
uint days = daysinmonth[monthhi << 4 | monthlo];
|
||||||
if(days == 28) {
|
if(days == 28) {
|
||||||
//add one day for leap years
|
//add one day for leap years
|
||||||
if((yearhi & 1) == 0 && ((yearlo - 0) & 3) == 0) days++;
|
if((yearhi & 1) == 0 && ((yearlo - 0) & 3) == 0) days++;
|
||||||
|
@ -153,7 +153,7 @@ void EpsonRTC::tick_day() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::tick_month() {
|
auto EpsonRTC::tick_month() -> void {
|
||||||
if(monthhi == 0 || !(monthlo & 2)) {
|
if(monthhi == 0 || !(monthlo & 2)) {
|
||||||
if(monthlo <= 8 || monthlo == 12) {
|
if(monthlo <= 8 || monthlo == 12) {
|
||||||
monthlo++;
|
monthlo++;
|
||||||
|
@ -168,7 +168,7 @@ void EpsonRTC::tick_month() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EpsonRTC::tick_year() {
|
auto EpsonRTC::tick_year() -> void {
|
||||||
if(yearlo <= 8 || yearlo == 12) {
|
if(yearlo <= 8 || yearlo == 12) {
|
||||||
yearlo++;
|
yearlo++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,9 +4,9 @@ namespace SuperFamicom {
|
||||||
|
|
||||||
Event event;
|
Event event;
|
||||||
|
|
||||||
void Event::Enter() { event.enter(); }
|
auto Event::Enter() -> void { event.enter(); }
|
||||||
|
|
||||||
void Event::enter() {
|
auto Event::enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
|
@ -15,7 +15,6 @@ void Event::enter() {
|
||||||
if(scoreActive && scoreSecondsRemaining) {
|
if(scoreActive && scoreSecondsRemaining) {
|
||||||
if(--scoreSecondsRemaining == 0) {
|
if(--scoreSecondsRemaining == 0) {
|
||||||
scoreActive = false;
|
scoreActive = false;
|
||||||
submitScore();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,40 +32,13 @@ void Event::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::submitScore() {
|
auto Event::init() -> void {
|
||||||
if(usedSaveState) return;
|
|
||||||
|
|
||||||
string data;
|
|
||||||
data.append("timer:", timer, "\n");
|
|
||||||
if(board == Board::CampusChallenge92) {
|
|
||||||
unsigned mw = 0, fz = 0, pw = 0;
|
|
||||||
for(unsigned n = 0x0408; n <= 0x040e; n++) mw = mw * 10 + ram.read(n);
|
|
||||||
for(unsigned n = 0x0413; n >= 0x0410; n--) fz = fz * 10 + ram.read(n);
|
|
||||||
for(unsigned n = 0x0418; n >= 0x0415; n--) pw = pw * 10 + ram.read(n);
|
|
||||||
data.append("mw:", mw, "\n");
|
|
||||||
data.append("fz:", fz, "\n");
|
|
||||||
data.append("pw:", pw, "\n");
|
|
||||||
}
|
|
||||||
if(board == Board::Powerfest94) {
|
|
||||||
unsigned ml = 0, mk[2] = {0}, ba[2] = {0};
|
|
||||||
for(unsigned n = 0x0408; n <= 0x040e; n++) ml = ml * 10 + ram.read(n);
|
|
||||||
for(unsigned n = 0x0413; n >= 0x0412; n--) mk[0] = mk[0] * 10 + ram.read(n);
|
|
||||||
for(unsigned n = 0x0411; n >= 0x0410; n--) mk[1] = mk[1] * 10 + ram.read(n);
|
|
||||||
for(unsigned n = 0x0418; n >= 0x0415; n--) ba[0] = ba[0] * 10 + ram.read(n);
|
|
||||||
for(unsigned n = 0x041a; n >= 0x0419; n--) ba[1] = ba[1] * 10 + ram.read(n);
|
|
||||||
data.append("ml:", ml, "\n");
|
|
||||||
data.append("mk:", mk[0], ",", mk[1], "\n");
|
|
||||||
data.append("ba:", ba[0], ",", ba[1], "\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::init() {
|
auto Event::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::load() {
|
auto Event::unload() -> void {
|
||||||
}
|
|
||||||
|
|
||||||
void Event::unload() {
|
|
||||||
rom[0].reset();
|
rom[0].reset();
|
||||||
rom[1].reset();
|
rom[1].reset();
|
||||||
rom[2].reset();
|
rom[2].reset();
|
||||||
|
@ -74,27 +46,25 @@ void Event::unload() {
|
||||||
ram.reset();
|
ram.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::power() {
|
auto Event::power() -> void {
|
||||||
usedSaveState = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::reset() {
|
auto Event::reset() -> void {
|
||||||
create(Event::Enter, 1);
|
create(Event::Enter, 1);
|
||||||
for(unsigned n = 0; n < ram.size(); n++) ram.write(n, 0x00);
|
for(auto n : range(ram.size())) ram.write(n, 0x00);
|
||||||
status = 0x00;
|
status = 0x00;
|
||||||
select = 0x00;
|
select = 0x00;
|
||||||
timerActive = false;
|
timerActive = false;
|
||||||
scoreActive = false;
|
scoreActive = false;
|
||||||
timerSecondsRemaining = 0;
|
timerSecondsRemaining = 0;
|
||||||
scoreSecondsRemaining = 0;
|
scoreSecondsRemaining = 0;
|
||||||
usedSaveState = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 Event::sr(unsigned) {
|
auto Event::sr(uint) -> uint8 {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::dr(unsigned, uint8 data) {
|
auto Event::dr(uint, uint8 data) -> void {
|
||||||
select = data;
|
select = data;
|
||||||
if(timer && data == 0x09) {
|
if(timer && data == 0x09) {
|
||||||
timerActive = true;
|
timerActive = true;
|
||||||
|
@ -102,9 +72,9 @@ void Event::dr(unsigned, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 Event::rom_read(unsigned addr) {
|
auto Event::rom_read(uint addr) -> uint8 {
|
||||||
if(board == Board::CampusChallenge92) {
|
if(board == Board::CampusChallenge92) {
|
||||||
unsigned id = 0;
|
uint id = 0;
|
||||||
if(select == 0x09) id = 1;
|
if(select == 0x09) id = 1;
|
||||||
if(select == 0x05) id = 2;
|
if(select == 0x05) id = 2;
|
||||||
if(select == 0x03) id = 3;
|
if(select == 0x03) id = 3;
|
||||||
|
@ -117,7 +87,7 @@ uint8 Event::rom_read(unsigned addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(board == Board::Powerfest94) {
|
if(board == Board::Powerfest94) {
|
||||||
unsigned id = 0;
|
uint id = 0;
|
||||||
if(select == 0x09) id = 1;
|
if(select == 0x09) id = 1;
|
||||||
if(select == 0x0c) id = 2;
|
if(select == 0x0c) id = 2;
|
||||||
if(select == 0x0a) id = 3;
|
if(select == 0x0a) id = 3;
|
||||||
|
@ -138,15 +108,15 @@ uint8 Event::rom_read(unsigned addr) {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 Event::ram_read(unsigned addr) {
|
auto Event::ram_read(uint addr) -> uint8 {
|
||||||
return ram.read(bus.mirror(addr, ram.size()));
|
return ram.read(bus.mirror(addr, ram.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::ram_write(unsigned addr, uint8 data) {
|
auto Event::ram_write(uint addr, uint8 data) -> void {
|
||||||
return ram.write(bus.mirror(addr, ram.size()), data);
|
return ram.write(bus.mirror(addr, ram.size()), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Event::serialize(serializer& s) {
|
auto Event::serialize(serializer& s) -> void {
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
s.array(ram.data(), ram.size());
|
s.array(ram.data(), ram.size());
|
||||||
s.integer(status);
|
s.integer(status);
|
||||||
|
@ -155,8 +125,6 @@ void Event::serialize(serializer& s) {
|
||||||
s.integer(scoreActive);
|
s.integer(scoreActive);
|
||||||
s.integer(timerSecondsRemaining);
|
s.integer(timerSecondsRemaining);
|
||||||
s.integer(scoreSecondsRemaining);
|
s.integer(scoreSecondsRemaining);
|
||||||
|
|
||||||
usedSaveState = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,42 +3,40 @@
|
||||||
//* Powerfest '94
|
//* Powerfest '94
|
||||||
|
|
||||||
struct Event : Coprocessor {
|
struct Event : Coprocessor {
|
||||||
|
static auto Enter() -> void;
|
||||||
|
auto enter() -> void;
|
||||||
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
|
auto submitScore() -> void;
|
||||||
|
|
||||||
|
auto sr(uint) -> uint8;
|
||||||
|
auto dr(uint, uint8 data) -> void;
|
||||||
|
auto rom_read(uint addr) -> uint8;
|
||||||
|
auto ram_read(uint addr) -> uint8;
|
||||||
|
auto ram_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
MappedRAM rom[4];
|
MappedRAM rom[4];
|
||||||
MappedRAM ram;
|
MappedRAM ram;
|
||||||
|
|
||||||
static void Enter();
|
enum class Board : uint { CampusChallenge92, Powerfest94 } board;
|
||||||
void enter();
|
uint revision;
|
||||||
void init();
|
uint timer;
|
||||||
void load();
|
|
||||||
void unload();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void submitScore();
|
|
||||||
|
|
||||||
uint8 sr(unsigned);
|
|
||||||
void dr(unsigned, uint8 data);
|
|
||||||
uint8 rom_read(unsigned addr);
|
|
||||||
uint8 ram_read(unsigned addr);
|
|
||||||
void ram_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
void serialize(serializer&);
|
|
||||||
|
|
||||||
//private:
|
|
||||||
enum class Board : unsigned { CampusChallenge92, Powerfest94 } board;
|
|
||||||
unsigned revision;
|
|
||||||
unsigned timer;
|
|
||||||
|
|
||||||
|
privileged:
|
||||||
uint8 status;
|
uint8 status;
|
||||||
uint8 select;
|
uint8 select;
|
||||||
|
|
||||||
bool timerActive;
|
bool timerActive;
|
||||||
bool scoreActive;
|
bool scoreActive;
|
||||||
|
|
||||||
unsigned timerSecondsRemaining;
|
uint timerSecondsRemaining;
|
||||||
unsigned scoreSecondsRemaining;
|
uint scoreSecondsRemaining;
|
||||||
|
|
||||||
bool usedSaveState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Event event;
|
extern Event event;
|
||||||
|
|
|
@ -6,16 +6,16 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
HitachiDSP hitachidsp;
|
HitachiDSP hitachidsp;
|
||||||
|
|
||||||
void HitachiDSP::Enter() { hitachidsp.enter(); }
|
auto HitachiDSP::Enter() -> void { hitachidsp.enter(); }
|
||||||
|
|
||||||
void HitachiDSP::enter() {
|
auto HitachiDSP::enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mmio.dma) {
|
if(mmio.dma) {
|
||||||
for(unsigned n = 0; n < mmio.dma_length; n++) {
|
for(auto n : range(mmio.dma_length)) {
|
||||||
bus.write(mmio.dma_target + n, bus.read(mmio.dma_source + n));
|
bus.write(mmio.dma_target + n, bus.read(mmio.dma_source + n));
|
||||||
step(2);
|
step(2);
|
||||||
}
|
}
|
||||||
|
@ -29,18 +29,18 @@ void HitachiDSP::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::init() {
|
auto HitachiDSP::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::load() {
|
auto HitachiDSP::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::unload() {
|
auto HitachiDSP::unload() -> void {
|
||||||
rom.reset();
|
rom.reset();
|
||||||
ram.reset();
|
ram.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::power() {
|
auto HitachiDSP::power() -> void {
|
||||||
mmio.dma = false;
|
mmio.dma = false;
|
||||||
|
|
||||||
mmio.dma_source = 0x000000;
|
mmio.dma_source = 0x000000;
|
||||||
|
@ -56,7 +56,7 @@ void HitachiDSP::power() {
|
||||||
mmio.r1f52 = 0x01;
|
mmio.r1f52 = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::reset() {
|
auto HitachiDSP::reset() -> void {
|
||||||
create(HitachiDSP::Enter, Frequency);
|
create(HitachiDSP::Enter, Frequency);
|
||||||
HG51B::power();
|
HG51B::power();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
struct HitachiDSP : Processor::HG51B, Coprocessor {
|
struct HitachiDSP : Processor::HG51B, Coprocessor {
|
||||||
unsigned Frequency;
|
|
||||||
unsigned Roms;
|
|
||||||
|
|
||||||
MappedRAM rom;
|
MappedRAM rom;
|
||||||
MappedRAM ram;
|
MappedRAM ram;
|
||||||
|
|
||||||
#include "mmio.hpp"
|
#include "mmio.hpp"
|
||||||
|
|
||||||
static void Enter();
|
static auto Enter() -> void;
|
||||||
void enter();
|
auto enter() -> void;
|
||||||
|
|
||||||
void init();
|
auto init() -> void;
|
||||||
void load();
|
auto load() -> void;
|
||||||
void unload();
|
auto unload() -> void;
|
||||||
void power();
|
auto power() -> void;
|
||||||
void reset();
|
auto reset() -> void;
|
||||||
|
|
||||||
//HG51B read/write
|
//HG51B read/write
|
||||||
uint8 bus_read(uint24 addr);
|
auto bus_read(uint24 addr) -> uint8;
|
||||||
void bus_write(uint24 addr, uint8 data);
|
auto bus_write(uint24 addr, uint8 data) -> void;
|
||||||
|
|
||||||
//CPU ROM read/write
|
//CPU ROM read/write
|
||||||
uint8 rom_read(unsigned addr);
|
auto rom_read(uint addr) -> uint8;
|
||||||
void rom_write(unsigned addr, uint8 data);
|
auto rom_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
//CPU RAM read/write
|
//CPU RAM read/write
|
||||||
uint8 ram_read(unsigned addr);
|
auto ram_read(uint addr) -> uint8;
|
||||||
void ram_write(unsigned addr, uint8 data);
|
auto ram_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
//CPU MMIO read/write
|
//CPU MMIO read/write
|
||||||
uint8 dsp_read(unsigned addr);
|
auto dsp_read(uint addr) -> uint8;
|
||||||
void dsp_write(unsigned addr, uint8 data);
|
auto dsp_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
vector<uint8> firmware();
|
auto firmware() const -> vector<uint8>;
|
||||||
void serialize(serializer&);
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
uint Frequency;
|
||||||
|
uint Roms;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern HitachiDSP hitachidsp;
|
extern HitachiDSP hitachidsp;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
uint8 HitachiDSP::bus_read(uint24 addr) {
|
auto HitachiDSP::bus_read(uint24 addr) -> uint8 {
|
||||||
if((addr & 0x408000) == 0x008000) return bus.read(addr); //$00-3f,80-bf:6000-7fff
|
if((addr & 0x408000) == 0x008000) return bus.read(addr); //$00-3f,80-bf:6000-7fff
|
||||||
if((addr & 0xf88000) == 0x700000) return bus.read(addr); //$70-77:0000-7fff
|
if((addr & 0xf88000) == 0x700000) return bus.read(addr); //$70-77:0000-7fff
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::bus_write(uint24 addr, uint8 data) {
|
auto HitachiDSP::bus_write(uint24 addr, uint8 data) -> void {
|
||||||
if((addr & 0x40e000) == 0x006000) return bus.write(addr, data); //$00-3f,80-bf:6000-7fff
|
if((addr & 0x40e000) == 0x006000) return bus.write(addr, data); //$00-3f,80-bf:6000-7fff
|
||||||
if((addr & 0xf88000) == 0x700000) return bus.write(addr, data); //$70-77:0000-7fff
|
if((addr & 0xf88000) == 0x700000) return bus.write(addr, data); //$70-77:0000-7fff
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 HitachiDSP::rom_read(unsigned addr) {
|
auto HitachiDSP::rom_read(uint addr) -> uint8 {
|
||||||
if(co_active() == hitachidsp.thread || regs.halt) {
|
if(co_active() == hitachidsp.thread || regs.halt) {
|
||||||
addr = bus.mirror(addr, rom.size());
|
addr = bus.mirror(addr, rom.size());
|
||||||
//if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00;
|
//if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00;
|
||||||
|
@ -19,20 +19,20 @@ uint8 HitachiDSP::rom_read(unsigned addr) {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::rom_write(unsigned addr, uint8 data) {
|
auto HitachiDSP::rom_write(uint addr, uint8 data) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 HitachiDSP::ram_read(unsigned addr) {
|
auto HitachiDSP::ram_read(uint addr) -> uint8 {
|
||||||
if(ram.size() == 0) return 0x00; //not open bus
|
if(ram.size() == 0) return 0x00; //not open bus
|
||||||
return ram.read(bus.mirror(addr, ram.size()));
|
return ram.read(bus.mirror(addr, ram.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::ram_write(unsigned addr, uint8 data) {
|
auto HitachiDSP::ram_write(uint addr, uint8 data) -> void {
|
||||||
if(ram.size() == 0) return;
|
if(ram.size() == 0) return;
|
||||||
return ram.write(bus.mirror(addr, ram.size()), data);
|
return ram.write(bus.mirror(addr, ram.size()), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 HitachiDSP::dsp_read(unsigned addr) {
|
auto HitachiDSP::dsp_read(uint addr) -> uint8 {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
|
||||||
//Data RAM
|
//Data RAM
|
||||||
|
@ -74,15 +74,15 @@ uint8 HitachiDSP::dsp_read(unsigned addr) {
|
||||||
|
|
||||||
//GPRs
|
//GPRs
|
||||||
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
||||||
unsigned index = (addr & 0x3f) / 3; //0..15
|
uint index = (addr & 0x3f) / 3; //0..15
|
||||||
unsigned shift = ((addr & 0x3f) % 3) * 8; //0, 8, 16
|
uint shift = ((addr & 0x3f) % 3) * 8; //0, 8, 16
|
||||||
return regs.gpr[index] >> shift;
|
return regs.gpr[index] >> shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::dsp_write(unsigned addr, uint8 data) {
|
auto HitachiDSP::dsp_write(uint addr, uint8 data) -> void {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
|
||||||
//Data RAM
|
//Data RAM
|
||||||
|
@ -129,7 +129,7 @@ void HitachiDSP::dsp_write(unsigned addr, uint8 data) {
|
||||||
|
|
||||||
//GPRs
|
//GPRs
|
||||||
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
if((addr >= 0x1f80 && addr <= 0x1faf) || (addr >= 0x1fc0 && addr <= 0x1fef)) {
|
||||||
unsigned index = (addr & 0x3f) / 3;
|
uint index = (addr & 0x3f) / 3;
|
||||||
switch((addr & 0x3f) % 3) {
|
switch((addr & 0x3f) % 3) {
|
||||||
case 0: regs.gpr[index] = (regs.gpr[index] & 0xffff00) | (data << 0); return;
|
case 0: regs.gpr[index] = (regs.gpr[index] & 0xffff00) | (data << 0); return;
|
||||||
case 1: regs.gpr[index] = (regs.gpr[index] & 0xff00ff) | (data << 8); return;
|
case 1: regs.gpr[index] = (regs.gpr[index] & 0xff00ff) | (data << 8); return;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
vector<uint8> HitachiDSP::firmware() {
|
auto HitachiDSP::firmware() const -> vector<uint8> {
|
||||||
vector<uint8> buffer;
|
vector<uint8> buffer;
|
||||||
if(!cartridge.hasHitachiDSP()) return buffer;
|
if(!cartridge.hasHitachiDSP()) return buffer;
|
||||||
buffer.reserve(1024 * 3);
|
buffer.reserve(1024 * 3);
|
||||||
for(unsigned n = 0; n < 1024; n++) {
|
for(auto n : range(1024)) {
|
||||||
buffer.append(dataROM[n] >> 0);
|
buffer.append(dataROM[n] >> 0);
|
||||||
buffer.append(dataROM[n] >> 8);
|
buffer.append(dataROM[n] >> 8);
|
||||||
buffer.append(dataROM[n] >> 16);
|
buffer.append(dataROM[n] >> 16);
|
||||||
|
@ -10,7 +10,7 @@ vector<uint8> HitachiDSP::firmware() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitachiDSP::serialize(serializer& s) {
|
auto HitachiDSP::serialize(serializer& s) -> void {
|
||||||
HG51B::serialize(s);
|
HG51B::serialize(s);
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
ICD2 icd2;
|
ICD2 icd2;
|
||||||
|
|
||||||
void ICD2::Enter() { icd2.enter(); }
|
auto ICD2::Enter() -> void { icd2.enter(); }
|
||||||
|
|
||||||
void ICD2::enter() {
|
auto ICD2::enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
GameBoy::system.runtosave();
|
GameBoy::system.runtosave();
|
||||||
|
@ -28,27 +28,27 @@ void ICD2::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::init() {
|
auto ICD2::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::load() {
|
auto ICD2::load() -> void {
|
||||||
bind = GameBoy::interface->bind;
|
bind = GameBoy::interface->bind;
|
||||||
hook = GameBoy::interface->hook;
|
hook = GameBoy::interface->hook;
|
||||||
GameBoy::interface->bind = this;
|
GameBoy::interface->bind = this;
|
||||||
GameBoy::interface->hook = this;
|
GameBoy::interface->hook = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::unload() {
|
auto ICD2::unload() -> void {
|
||||||
GameBoy::interface->bind = bind;
|
GameBoy::interface->bind = bind;
|
||||||
GameBoy::interface->hook = hook;
|
GameBoy::interface->hook = hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::power() {
|
auto ICD2::power() -> void {
|
||||||
audio.coprocessor_enable(true);
|
audio.coprocessor_enable(true);
|
||||||
audio.coprocessor_frequency(2 * 1024 * 1024);
|
audio.coprocessor_frequency(2 * 1024 * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::reset() {
|
auto ICD2::reset() -> void {
|
||||||
create(ICD2::Enter, cpu.frequency / 5);
|
create(ICD2::Enter, cpu.frequency / 5);
|
||||||
|
|
||||||
r6003 = 0x00;
|
r6003 = 0x00;
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor {
|
struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor {
|
||||||
unsigned revision;
|
static auto Enter() -> void;
|
||||||
|
auto enter() -> void;
|
||||||
|
|
||||||
static void Enter();
|
auto init() -> void;
|
||||||
void enter();
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
void init();
|
auto read(uint addr) -> uint8;
|
||||||
void load();
|
auto write(uint addr, uint8 data) -> void;
|
||||||
void unload();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
auto serialize(serializer&) -> void;
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
void serialize(serializer&);
|
uint revision;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Emulator::Interface::Bind* bind = nullptr;
|
Emulator::Interface::Bind* bind = nullptr;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void ICD2::lcdScanline() {
|
auto ICD2::lcdScanline() -> void {
|
||||||
if(GameBoy::ppu.status.ly > 143) return; //Vblank
|
if(GameBoy::ppu.status.ly > 143) return; //Vblank
|
||||||
if((GameBoy::ppu.status.ly & 7) == 0) {
|
if((GameBoy::ppu.status.ly & 7) == 0) {
|
||||||
write_bank = (write_bank + 1) & 3;
|
write_bank = (write_bank + 1) & 3;
|
||||||
|
@ -6,16 +6,16 @@ void ICD2::lcdScanline() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::lcdOutput(uint2 color) {
|
auto ICD2::lcdOutput(uint2 color) -> void {
|
||||||
unsigned y = write_addr / 160;
|
uint y = write_addr / 160;
|
||||||
unsigned x = write_addr % 160;
|
uint x = write_addr % 160;
|
||||||
unsigned addr = write_bank * 512 + y * 2 + x / 8 * 16;
|
uint addr = write_bank * 512 + y * 2 + x / 8 * 16;
|
||||||
output[addr + 0] = (output[addr + 0] << 1) | (bool)(color & 1);
|
output[addr + 0] = (output[addr + 0] << 1) | (bool)(color & 1);
|
||||||
output[addr + 1] = (output[addr + 1] << 1) | (bool)(color & 2);
|
output[addr + 1] = (output[addr + 1] << 1) | (bool)(color & 2);
|
||||||
write_addr = (write_addr + 1) % 1280;
|
write_addr = (write_addr + 1) % 1280;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::joypWrite(bool p15, bool p14) {
|
auto ICD2::joypWrite(bool p15, bool p14) -> void {
|
||||||
//joypad handling
|
//joypad handling
|
||||||
if(p15 == 1 && p14 == 1) {
|
if(p15 == 1 && p14 == 1) {
|
||||||
if(joyp15lock == 0 && joyp14lock == 0) {
|
if(joyp15lock == 0 && joyp14lock == 0) {
|
||||||
|
@ -85,21 +85,21 @@ void ICD2::joypWrite(bool p15, bool p14) {
|
||||||
packetlock = true;
|
packetlock = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ICD2::videoColor(unsigned source, uint16_t red, uint16_t green, uint16_t blue) {
|
auto ICD2::videoColor(uint source, uint16 red, uint16 green, uint16 blue) -> uint32 {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::videoRefresh(const uint32_t* data, unsigned pitch, unsigned width, unsigned height) {
|
auto ICD2::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::audioSample(int16_t left, int16_t right) {
|
auto ICD2::audioSample(int16 left, int16 right) -> void {
|
||||||
audio.coprocessor_sample(left, right);
|
audio.coprocessor_sample(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t ICD2::inputPoll(unsigned port, unsigned device, unsigned id) {
|
auto ICD2::inputPoll(uint port, uint device, uint id) -> int16 {
|
||||||
GameBoy::cpu.status.mlt_req = joyp_id & mlt_req;
|
GameBoy::cpu.status.mlt_req = joyp_id & mlt_req;
|
||||||
|
|
||||||
unsigned data = 0x00;
|
uint data = 0x00;
|
||||||
switch(joyp_id & mlt_req) {
|
switch(joyp_id & mlt_req) {
|
||||||
case 0: data = ~r6004; break;
|
case 0: data = ~r6004; break;
|
||||||
case 1: data = ~r6005; break;
|
case 1: data = ~r6005; break;
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
void lcdScanline();
|
auto lcdScanline() -> void;
|
||||||
void lcdOutput(uint2 color);
|
auto lcdOutput(uint2 color) -> void;
|
||||||
void joypWrite(bool p15, bool p14);
|
auto joypWrite(bool p15, bool p14) -> void;
|
||||||
|
|
||||||
uint32_t videoColor(unsigned source, uint16_t red, uint16_t green, uint16_t blue);
|
auto videoColor(uint source, uint16 red, uint16 green, uint16 blue) -> uint32;
|
||||||
void videoRefresh(const uint32_t* data, unsigned pitch, unsigned width, unsigned height);
|
auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void;
|
||||||
void audioSample(int16_t lsample, int16_t rsample);
|
auto audioSample(int16 lsample, int16 rsample) -> void;
|
||||||
int16_t inputPoll(unsigned port, unsigned device, unsigned id);
|
auto inputPoll(uint port, uint device, uint id) -> int16;
|
||||||
|
|
||||||
struct Packet {
|
struct Packet {
|
||||||
|
auto operator[](uint addr) -> uint8& { return data[addr & 15]; }
|
||||||
uint8 data[16];
|
uint8 data[16];
|
||||||
uint8& operator[](unsigned addr) { return data[addr & 15]; }
|
|
||||||
};
|
};
|
||||||
Packet packet[64];
|
Packet packet[64];
|
||||||
unsigned packetsize;
|
uint packetsize;
|
||||||
|
|
||||||
unsigned joyp_id;
|
uint joyp_id;
|
||||||
bool joyp15lock;
|
bool joyp15lock;
|
||||||
bool joyp14lock;
|
bool joyp14lock;
|
||||||
bool pulselock;
|
bool pulselock;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
uint8 ICD2::read(unsigned addr) {
|
auto ICD2::read(uint addr) -> uint8 {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
//LY counter
|
//LY counter
|
||||||
if(addr == 0x6000) {
|
if(addr == 0x6000) {
|
||||||
unsigned y = min(143u, GameBoy::ppu.status.ly);
|
uint y = min(143u, GameBoy::ppu.status.ly);
|
||||||
return (y & ~7) | write_bank;
|
return (y & ~7) | write_bank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ uint8 ICD2::read(unsigned addr) {
|
||||||
if(addr == 0x6002) {
|
if(addr == 0x6002) {
|
||||||
bool data = packetsize > 0;
|
bool data = packetsize > 0;
|
||||||
if(data) {
|
if(data) {
|
||||||
for(unsigned i = 0; i < 16; i++) r7000[i] = packet[0][i];
|
for(auto n : range(16)) r7000[n] = packet[0][n];
|
||||||
packetsize--;
|
packetsize--;
|
||||||
for(unsigned i = 0; i < packetsize; i++) packet[i] = packet[i + 1];
|
for(auto n : range(packetsize)) packet[n] = packet[n + 1];
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ uint8 ICD2::read(unsigned addr) {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::write(unsigned addr, uint8 data) {
|
auto ICD2::write(uint addr, uint8 data) -> void {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
//VRAM port
|
//VRAM port
|
||||||
|
|
|
@ -7,7 +7,7 @@ uint8 r7000[16]; //JOYP packet data
|
||||||
uint8 mlt_req; //number of active joypads
|
uint8 mlt_req; //number of active joypads
|
||||||
|
|
||||||
uint8 output[4 * 512];
|
uint8 output[4 * 512];
|
||||||
unsigned read_bank;
|
uint read_bank;
|
||||||
unsigned read_addr;
|
uint read_addr;
|
||||||
unsigned write_bank;
|
uint write_bank;
|
||||||
unsigned write_addr;
|
uint write_addr;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
void ICD2::serialize(serializer& s) {
|
auto ICD2::serialize(serializer& s) -> void {
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
GameBoy::system.serialize_all(s);
|
GameBoy::system.serialize_all(s);
|
||||||
|
|
||||||
for(unsigned n = 0; n < 64; n++) s.array(packet[n].data);
|
for(auto n : range(64)) s.array(packet[n].data);
|
||||||
s.integer(packetsize);
|
s.integer(packetsize);
|
||||||
|
|
||||||
s.integer(joyp_id);
|
s.integer(joyp_id);
|
||||||
|
|
|
@ -21,29 +21,29 @@ auto MCC::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::reset() -> void {
|
auto MCC::reset() -> void {
|
||||||
for(unsigned i = 0; i < 16; i++) r[i] = 0x00;
|
for(auto n : range(16)) r[n] = 0x00;
|
||||||
r[0x07] = 0x80;
|
r[0x07] = 0x80;
|
||||||
r[0x08] = 0x80;
|
r[0x08] = 0x80;
|
||||||
mmio_commit();
|
mmio_commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::memory_access(bool write, Memory& memory, unsigned addr, uint8 data) -> uint8 {
|
auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8 {
|
||||||
if(write == 0) return memory_read(memory, addr);
|
if(write == 0) return memory_read(memory, addr);
|
||||||
memory_write(memory, addr, data);
|
memory_write(memory, addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::memory_read(Memory& memory, unsigned addr) -> uint8 {
|
auto MCC::memory_read(Memory& memory, uint addr) -> uint8 {
|
||||||
addr = bus.mirror(addr, memory.size());
|
addr = bus.mirror(addr, memory.size());
|
||||||
return memory.read(addr);
|
return memory.read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::memory_write(Memory& memory, unsigned addr, uint8 data) -> void {
|
auto MCC::memory_write(Memory& memory, uint addr, uint8 data) -> void {
|
||||||
addr = bus.mirror(addr, memory.size());
|
addr = bus.mirror(addr, memory.size());
|
||||||
return memory.write(addr, data);
|
return memory.write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//mcu_access() allows mcu_read() and mcu_write() to share decoding logic
|
//mcu_access() allows mcu_read() and mcu_write() to share decoding logic
|
||||||
auto MCC::mcu_access(bool write, unsigned addr, uint8 data) -> uint8 {
|
auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
|
||||||
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
|
if((addr & 0xe08000) == 0x008000) { //$00-1f:8000-ffff
|
||||||
if(r07 == 1) {
|
if(r07 == 1) {
|
||||||
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff);
|
addr = ((addr & 0x1f0000) >> 1) | (addr & 0x7fff);
|
||||||
|
@ -89,15 +89,15 @@ auto MCC::mcu_access(bool write, unsigned addr, uint8 data) -> uint8 {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::mcu_read(unsigned addr) -> uint8 {
|
auto MCC::mcu_read(uint addr) -> uint8 {
|
||||||
return mcu_access(0, addr);
|
return mcu_access(0, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::mcu_write(unsigned addr, uint8 data) -> void {
|
auto MCC::mcu_write(uint addr, uint8 data) -> void {
|
||||||
mcu_access(1, addr, data);
|
mcu_access(1, addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::mmio_read(unsigned addr) -> uint8 {
|
auto MCC::mmio_read(uint addr) -> uint8 {
|
||||||
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
||||||
uint8 n = (addr >> 16) & 15;
|
uint8 n = (addr >> 16) & 15;
|
||||||
return r[n];
|
return r[n];
|
||||||
|
@ -110,7 +110,7 @@ auto MCC::mmio_read(unsigned addr) -> uint8 {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MCC::mmio_write(unsigned addr, uint8 data) -> void {
|
auto MCC::mmio_write(uint addr, uint8 data) -> void {
|
||||||
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
|
||||||
uint8 n = (addr >> 16) & 15;
|
uint8 n = (addr >> 16) & 15;
|
||||||
r[n] = data;
|
r[n] = data;
|
||||||
|
|
|
@ -11,16 +11,16 @@ struct MCC {
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
auto reset() -> void;
|
auto reset() -> void;
|
||||||
|
|
||||||
auto memory_access(bool write, Memory& memory, unsigned addr, uint8 data) -> uint8;
|
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8;
|
||||||
auto memory_read(Memory& memory, unsigned addr) -> uint8;
|
auto memory_read(Memory& memory, uint addr) -> uint8;
|
||||||
auto memory_write(Memory& memory, unsigned addr, uint8 data) -> void;
|
auto memory_write(Memory& memory, uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
auto mcu_access(bool write, unsigned addr, uint8 data = 0x00) -> uint8;
|
auto mcu_access(bool write, uint addr, uint8 data = 0x00) -> uint8;
|
||||||
auto mcu_read(unsigned addr) -> uint8;
|
auto mcu_read(uint addr) -> uint8;
|
||||||
auto mcu_write(unsigned addr, uint8 data) -> void;
|
auto mcu_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
auto mmio_read(unsigned addr) -> uint8;
|
auto mmio_read(uint addr) -> uint8;
|
||||||
auto mmio_write(unsigned addr, uint8 data) -> void;
|
auto mmio_write(uint addr, uint8 data) -> void;
|
||||||
auto mmio_commit() -> void;
|
auto mmio_commit() -> void;
|
||||||
|
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
|
|
@ -35,8 +35,8 @@ auto MSU1::enter() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signed lchannel = (double)left * (double)mmio.audioVolume / 255.0;
|
int lchannel = (double)left * (double)mmio.audioVolume / 255.0;
|
||||||
signed rchannel = (double)right * (double)mmio.audioVolume / 255.0;
|
int rchannel = (double)right * (double)mmio.audioVolume / 255.0;
|
||||||
left = sclamp<16>(lchannel);
|
left = sclamp<16>(lchannel);
|
||||||
right = sclamp<16>(rchannel);
|
right = sclamp<16>(rchannel);
|
||||||
if(dsp.mute()) left = 0, right = 0;
|
if(dsp.mute()) left = 0, right = 0;
|
||||||
|
@ -103,7 +103,7 @@ auto MSU1::audioOpen() -> void {
|
||||||
auto document = BML::unserialize(cartridge.information.markup.cartridge);
|
auto document = BML::unserialize(cartridge.information.markup.cartridge);
|
||||||
string name = {"track-", mmio.audioTrack, ".pcm"};
|
string name = {"track-", mmio.audioTrack, ".pcm"};
|
||||||
for(auto track : document.find("cartridge/msu1/track")) {
|
for(auto track : document.find("cartridge/msu1/track")) {
|
||||||
if(track["number"].decimal() != mmio.audioTrack) continue;
|
if(track["number"].natural() != mmio.audioTrack) continue;
|
||||||
name = track["name"].text();
|
name = track["name"].text();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ auto MSU1::audioOpen() -> void {
|
||||||
mmio.audioError = true;
|
mmio.audioError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MSU1::mmioRead(unsigned addr) -> uint8 {
|
auto MSU1::mmioRead(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
addr = 0x2000 | (addr & 7);
|
addr = 0x2000 | (addr & 7);
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ auto MSU1::mmioRead(unsigned addr) -> uint8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MSU1::mmioWrite(unsigned addr, uint8 data) -> void {
|
auto MSU1::mmioWrite(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
addr = 0x2000 | (addr & 7);
|
addr = 0x2000 | (addr & 7);
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ struct MSU1 : Coprocessor {
|
||||||
auto dataOpen() -> void;
|
auto dataOpen() -> void;
|
||||||
auto audioOpen() -> void;
|
auto audioOpen() -> void;
|
||||||
|
|
||||||
auto mmioRead(unsigned addr) -> uint8;
|
auto mmioRead(uint addr) -> uint8;
|
||||||
auto mmioWrite(unsigned addr, uint8 data) -> void;
|
auto mmioWrite(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ private:
|
||||||
file dataFile;
|
file dataFile;
|
||||||
file audioFile;
|
file audioFile;
|
||||||
|
|
||||||
enum Flag : unsigned {
|
enum Flag : uint {
|
||||||
DataBusy = 0x80,
|
DataBusy = 0x80,
|
||||||
AudioBusy = 0x40,
|
AudioBusy = 0x40,
|
||||||
AudioRepeating = 0x20,
|
AudioRepeating = 0x20,
|
||||||
|
|
|
@ -5,9 +5,9 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
NECDSP necdsp;
|
NECDSP necdsp;
|
||||||
|
|
||||||
void NECDSP::Enter() { necdsp.enter(); }
|
auto NECDSP::Enter() -> void { necdsp.enter(); }
|
||||||
|
|
||||||
void NECDSP::enter() {
|
auto NECDSP::enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
|
@ -19,7 +19,7 @@ void NECDSP::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NECDSP::read(unsigned addr) {
|
auto NECDSP::read(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
if(addr & Select) {
|
if(addr & Select) {
|
||||||
return uPD96050::sr_read();
|
return uPD96050::sr_read();
|
||||||
|
@ -28,7 +28,7 @@ uint8 NECDSP::read(unsigned addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::write(unsigned addr, uint8 data) {
|
auto NECDSP::write(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
if(addr & Select) {
|
if(addr & Select) {
|
||||||
return uPD96050::sr_write(data);
|
return uPD96050::sr_write(data);
|
||||||
|
@ -37,29 +37,29 @@ void NECDSP::write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NECDSP::ram_read(unsigned addr) {
|
auto NECDSP::ram_read(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
return uPD96050::dp_read(addr);
|
return uPD96050::dp_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::ram_write(unsigned addr, uint8 data) {
|
auto NECDSP::ram_write(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
return uPD96050::dp_write(addr, data);
|
return uPD96050::dp_write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::init() {
|
auto NECDSP::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::load() {
|
auto NECDSP::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::unload() {
|
auto NECDSP::unload() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::power() {
|
auto NECDSP::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::reset() {
|
auto NECDSP::reset() -> void {
|
||||||
create(NECDSP::Enter, frequency);
|
create(NECDSP::Enter, frequency);
|
||||||
uPD96050::power();
|
uPD96050::power();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
struct NECDSP : Processor::uPD96050, Coprocessor {
|
struct NECDSP : Processor::uPD96050, Coprocessor {
|
||||||
|
static auto Enter() -> void;
|
||||||
|
auto enter() -> void;
|
||||||
|
|
||||||
|
auto read(uint addr) -> uint8;
|
||||||
|
auto write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto ram_read(uint addr) -> uint8;
|
||||||
|
auto ram_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
|
auto firmware() const -> vector<uint8>;
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
unsigned Select;
|
unsigned Select;
|
||||||
|
|
||||||
static void Enter();
|
|
||||||
void enter();
|
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
uint8 ram_read(unsigned addr);
|
|
||||||
void ram_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
void init();
|
|
||||||
void load();
|
|
||||||
void unload();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
vector<uint8> firmware();
|
|
||||||
void serialize(serializer&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NECDSP necdsp;
|
extern NECDSP necdsp;
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
vector<uint8> NECDSP::firmware() {
|
auto NECDSP::firmware() const -> vector<uint8> {
|
||||||
vector<uint8> buffer;
|
vector<uint8> buffer;
|
||||||
if(!cartridge.hasNECDSP()) return buffer;
|
if(!cartridge.hasNECDSP()) return buffer;
|
||||||
unsigned plength = 2048, dlength = 1024;
|
uint plength = 2048, dlength = 1024;
|
||||||
if(revision == Revision::uPD96050) plength = 16384, dlength = 2048;
|
if(revision == Revision::uPD96050) plength = 16384, dlength = 2048;
|
||||||
buffer.reserve(plength * 3 + dlength * 2);
|
buffer.reserve(plength * 3 + dlength * 2);
|
||||||
|
|
||||||
for(unsigned n = 0; n < plength; n++) {
|
for(auto n : range(plength)) {
|
||||||
buffer.append(programROM[n] >> 0);
|
buffer.append(programROM[n] >> 0);
|
||||||
buffer.append(programROM[n] >> 8);
|
buffer.append(programROM[n] >> 8);
|
||||||
buffer.append(programROM[n] >> 16);
|
buffer.append(programROM[n] >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned n = 0; n < dlength; n++) {
|
for(auto n : range(dlength)) {
|
||||||
buffer.append(dataROM[n] >> 0);
|
buffer.append(dataROM[n] >> 0);
|
||||||
buffer.append(dataROM[n] >> 8);
|
buffer.append(dataROM[n] >> 8);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ vector<uint8> NECDSP::firmware() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::serialize(serializer& s) {
|
auto NECDSP::serialize(serializer& s) -> void {
|
||||||
uPD96050::serialize(s);
|
uPD96050::serialize(s);
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,31 +4,30 @@ namespace SuperFamicom {
|
||||||
|
|
||||||
NSS nss;
|
NSS nss;
|
||||||
|
|
||||||
void NSS::init() {
|
auto NSS::init() -> void {
|
||||||
dip = 0x00;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSS::load() {
|
auto NSS::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSS::unload() {
|
auto NSS::unload() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSS::power() {
|
auto NSS::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSS::reset() {
|
auto NSS::reset() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSS::set_dip(uint16 dip) {
|
auto NSS::set_dip(uint16 dip) -> void {
|
||||||
this->dip = dip;
|
this->dip = dip;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NSS::read(unsigned addr) {
|
auto NSS::read(uint addr) -> uint8 {
|
||||||
return dip;
|
return dip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NSS::write(unsigned addr, uint8 data) {
|
auto NSS::write(uint addr, uint8 data) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
struct NSS {
|
struct NSS {
|
||||||
uint8 dip;
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
void init();
|
auto set_dip(uint16 dip) -> void;
|
||||||
void load();
|
auto read(uint addr) -> uint8;
|
||||||
void unload();
|
auto write(uint addr, uint8 data) -> void;
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
void set_dip(uint16 dip);
|
uint8 dip = 0x00;
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NSS nss;
|
extern NSS nss;
|
||||||
|
|
|
@ -5,74 +5,74 @@ namespace SuperFamicom {
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
OBC1 obc1;
|
OBC1 obc1;
|
||||||
|
|
||||||
void OBC1::init() {
|
auto OBC1::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::load() {
|
auto OBC1::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::unload() {
|
auto OBC1::unload() -> void {
|
||||||
ram.reset();
|
ram.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::power() {
|
auto OBC1::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::reset() {
|
auto OBC1::reset() -> void {
|
||||||
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
status.baseptr = (ramRead(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
||||||
status.address = (ram_read(0x1ff6) & 0x7f);
|
status.address = (ramRead(0x1ff6) & 0x7f);
|
||||||
status.shift = (ram_read(0x1ff6) & 3) << 1;
|
status.shift = (ramRead(0x1ff6) & 3) << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 OBC1::read(unsigned addr) {
|
auto OBC1::read(uint addr) -> uint8 {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
|
case 0x1ff0: return ramRead(status.baseptr + (status.address << 2) + 0);
|
||||||
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
|
case 0x1ff1: return ramRead(status.baseptr + (status.address << 2) + 1);
|
||||||
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
|
case 0x1ff2: return ramRead(status.baseptr + (status.address << 2) + 2);
|
||||||
case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3);
|
case 0x1ff3: return ramRead(status.baseptr + (status.address << 2) + 3);
|
||||||
case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
case 0x1ff4: return ramRead(status.baseptr + (status.address >> 2) + 0x200);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ram_read(addr);
|
return ramRead(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::write(unsigned addr, uint8 data) {
|
auto OBC1::write(uint addr, uint8 data) -> void {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); return;
|
case 0x1ff0: ramWrite(status.baseptr + (status.address << 2) + 0, data); return;
|
||||||
case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); return;
|
case 0x1ff1: ramWrite(status.baseptr + (status.address << 2) + 1, data); return;
|
||||||
case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); return;
|
case 0x1ff2: ramWrite(status.baseptr + (status.address << 2) + 2, data); return;
|
||||||
case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); return;
|
case 0x1ff3: ramWrite(status.baseptr + (status.address << 2) + 3, data); return;
|
||||||
case 0x1ff4: {
|
case 0x1ff4: {
|
||||||
uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
uint8 temp = ramRead(status.baseptr + (status.address >> 2) + 0x200);
|
||||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||||
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
ramWrite(status.baseptr + (status.address >> 2) + 0x200, temp);
|
||||||
} return;
|
} return;
|
||||||
case 0x1ff5:
|
case 0x1ff5:
|
||||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||||
ram_write(addr, data);
|
ramWrite(addr, data);
|
||||||
return;
|
return;
|
||||||
case 0x1ff6:
|
case 0x1ff6:
|
||||||
status.address = (data & 0x7f);
|
status.address = (data & 0x7f);
|
||||||
status.shift = (data & 3) << 1;
|
status.shift = (data & 3) << 1;
|
||||||
ram_write(addr, data);
|
ramWrite(addr, data);
|
||||||
return;
|
return;
|
||||||
case 0x1ff7:
|
case 0x1ff7:
|
||||||
ram_write(addr, data);
|
ramWrite(addr, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ram_write(addr, data);
|
return ramWrite(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 OBC1::ram_read(unsigned addr) {
|
auto OBC1::ramRead(uint addr) -> uint8 {
|
||||||
return ram.read(addr & 0x1fff);
|
return ram.read(addr & 0x1fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::ram_write(unsigned addr, uint8 data) {
|
auto OBC1::ramWrite(uint addr, uint8 data) -> void {
|
||||||
ram.write(addr & 0x1fff, data);
|
ram.write(addr & 0x1fff, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
struct OBC1 {
|
struct OBC1 {
|
||||||
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
|
auto read(uint addr) -> uint8;
|
||||||
|
auto write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
MappedRAM ram;
|
MappedRAM ram;
|
||||||
|
|
||||||
void init();
|
|
||||||
void load();
|
|
||||||
void unload();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
void serialize(serializer&);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8 ram_read(unsigned addr);
|
auto ramRead(uint addr) -> uint8;
|
||||||
void ram_write(unsigned addr, uint8 data);
|
auto ramWrite(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16 address;
|
uint16 address;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void OBC1::serialize(serializer& s) {
|
auto OBC1::serialize(serializer& s) -> void {
|
||||||
s.array(ram.data(), ram.size());
|
s.array(ram.data(), ram.size());
|
||||||
|
|
||||||
s.integer(status.address);
|
s.integer(status.address);
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
//ROM / RAM access from the S-CPU
|
//ROM / RAM access from the S-CPU
|
||||||
|
|
||||||
unsigned SA1::CPUIRAM::size() const {
|
auto SA1::CPUIRAM::size() const -> uint {
|
||||||
return sa1.iram.size();
|
return sa1.iram.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::CPUIRAM::read(unsigned addr) {
|
auto SA1::CPUIRAM::read(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
return sa1.iram.read(addr & 0x07ff);
|
return sa1.iram.read(addr & 0x07ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::CPUIRAM::write(unsigned addr, uint8 data) {
|
auto SA1::CPUIRAM::write(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
sa1.iram.write(addr & 0x07ff, data);
|
sa1.iram.write(addr & 0x07ff, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned SA1::CPUBWRAM::size() const {
|
auto SA1::CPUBWRAM::size() const -> uint {
|
||||||
return sa1.bwram.size();
|
return sa1.bwram.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::CPUBWRAM::read(unsigned addr) {
|
auto SA1::CPUBWRAM::read(uint addr) -> uint8 {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
if(dma) return sa1.dma_cc1_read(addr);
|
if(dma) return sa1.dma_cc1_read(addr);
|
||||||
return sa1.bwram.read(addr);
|
return sa1.bwram.read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::CPUBWRAM::write(unsigned addr, uint8 data) {
|
auto SA1::CPUBWRAM::write(uint addr, uint8 data) -> void {
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
sa1.bwram.write(addr, data);
|
sa1.bwram.write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
struct CPUIRAM : Memory {
|
struct CPUIRAM : Memory {
|
||||||
unsigned size() const;
|
auto size() const -> uint;
|
||||||
alwaysinline uint8 read(unsigned);
|
alwaysinline auto read(uint) -> uint8;
|
||||||
alwaysinline void write(unsigned, uint8);
|
alwaysinline auto write(uint, uint8) -> void;
|
||||||
} cpuiram;
|
} cpuiram;
|
||||||
|
|
||||||
struct CPUBWRAM : Memory {
|
struct CPUBWRAM : Memory {
|
||||||
unsigned size() const;
|
auto size() const -> uint;
|
||||||
alwaysinline uint8 read(unsigned);
|
alwaysinline auto read(uint) -> uint8;
|
||||||
alwaysinline void write(unsigned, uint8);
|
alwaysinline auto write(uint, uint8) -> void;
|
||||||
bool dma;
|
bool dma;
|
||||||
} cpubwram;
|
} cpubwram;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//direct data transfer
|
//direct data transfer
|
||||||
//====================
|
//====================
|
||||||
|
|
||||||
void SA1::dma_normal() {
|
auto SA1::dma_normal() -> void {
|
||||||
while(mmio.dtc--) {
|
while(mmio.dtc--) {
|
||||||
uint8 data = regs.mdr;
|
uint8 data = regs.mdr;
|
||||||
uint32 dsa = mmio.dsa++;
|
uint32 dsa = mmio.dsa++;
|
||||||
|
@ -56,7 +56,7 @@ void SA1::dma_normal() {
|
||||||
//type-1 character conversion
|
//type-1 character conversion
|
||||||
//===========================
|
//===========================
|
||||||
|
|
||||||
void SA1::dma_cc1() {
|
auto SA1::dma_cc1() -> void {
|
||||||
cpubwram.dma = true;
|
cpubwram.dma = true;
|
||||||
mmio.chdma_irqfl = true;
|
mmio.chdma_irqfl = true;
|
||||||
if(mmio.chdma_irqen) {
|
if(mmio.chdma_irqen) {
|
||||||
|
@ -65,29 +65,29 @@ void SA1::dma_cc1() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::dma_cc1_read(unsigned addr) {
|
auto SA1::dma_cc1_read(uint addr) -> uint8 {
|
||||||
//16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp)
|
//16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp)
|
||||||
unsigned charmask = (1 << (6 - mmio.dmacb)) - 1;
|
uint charmask = (1 << (6 - mmio.dmacb)) - 1;
|
||||||
|
|
||||||
if((addr & charmask) == 0) {
|
if((addr & charmask) == 0) {
|
||||||
//buffer next character to I-RAM
|
//buffer next character to I-RAM
|
||||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
uint bpp = 2 << (2 - mmio.dmacb);
|
||||||
unsigned bpl = (8 << mmio.dmasize) >> mmio.dmacb;
|
uint bpl = (8 << mmio.dmasize) >> mmio.dmacb;
|
||||||
unsigned bwmask = bwram.size() - 1;
|
uint bwmask = bwram.size() - 1;
|
||||||
unsigned tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb);
|
uint tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb);
|
||||||
unsigned ty = (tile >> mmio.dmasize);
|
uint ty = (tile >> mmio.dmasize);
|
||||||
unsigned tx = tile & ((1 << mmio.dmasize) - 1);
|
uint tx = tile & ((1 << mmio.dmasize) - 1);
|
||||||
unsigned bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp;
|
uint bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp;
|
||||||
|
|
||||||
for(unsigned y = 0; y < 8; y++) {
|
for(auto y : range(8)) {
|
||||||
uint64 data = 0;
|
uint64 data = 0;
|
||||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
for(auto byte : range(bpp)) {
|
||||||
data |= (uint64)bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
data |= (uint64)bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
||||||
}
|
}
|
||||||
bwaddr += bpl;
|
bwaddr += bpl;
|
||||||
|
|
||||||
uint8 out[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
uint8 out[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
for(unsigned x = 0; x < 8; x++) {
|
for(auto x : range(8)) {
|
||||||
out[0] |= (data & 1) << (7 - x); data >>= 1;
|
out[0] |= (data & 1) << (7 - x); data >>= 1;
|
||||||
out[1] |= (data & 1) << (7 - x); data >>= 1;
|
out[1] |= (data & 1) << (7 - x); data >>= 1;
|
||||||
if(mmio.dmacb == 2) continue;
|
if(mmio.dmacb == 2) continue;
|
||||||
|
@ -100,8 +100,8 @@ uint8 SA1::dma_cc1_read(unsigned addr) {
|
||||||
out[7] |= (data & 1) << (7 - x); data >>= 1;
|
out[7] |= (data & 1) << (7 - x); data >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
for(auto byte : range(bpp)) {
|
||||||
unsigned p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1);
|
uint p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1);
|
||||||
iram.write(p & 0x07ff, out[byte]);
|
iram.write(p & 0x07ff, out[byte]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,18 +114,18 @@ uint8 SA1::dma_cc1_read(unsigned addr) {
|
||||||
//type-2 character conversion
|
//type-2 character conversion
|
||||||
//===========================
|
//===========================
|
||||||
|
|
||||||
void SA1::dma_cc2() {
|
auto SA1::dma_cc2() -> void {
|
||||||
//select register file index (0-7 or 8-15)
|
//select register file index (0-7 or 8-15)
|
||||||
const uint8 *brf = &mmio.brf[(dma.line & 1) << 3];
|
const uint8* brf = &mmio.brf[(dma.line & 1) << 3];
|
||||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
uint bpp = 2 << (2 - mmio.dmacb);
|
||||||
unsigned addr = mmio.dda & 0x07ff;
|
uint addr = mmio.dda & 0x07ff;
|
||||||
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
|
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
|
||||||
addr += (dma.line & 8) * bpp;
|
addr += (dma.line & 8) * bpp;
|
||||||
addr += (dma.line & 7) * 2;
|
addr += (dma.line & 7) * 2;
|
||||||
|
|
||||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
for(auto byte : range(bpp)) {
|
||||||
uint8 output = 0;
|
uint8 output = 0;
|
||||||
for(unsigned bit = 0; bit < 8; bit++) {
|
for(auto bit : range(8)) {
|
||||||
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
|
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
|
||||||
}
|
}
|
||||||
iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
|
iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
struct DMA {
|
struct DMA {
|
||||||
enum CDEN { DmaNormal = 0, DmaCharConversion = 1 };
|
enum CDEN : uint { DmaNormal = 0, DmaCharConversion = 1 };
|
||||||
enum SD { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
|
enum SD : uint { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
|
||||||
enum DD { DestIRAM = 0, DestBWRAM = 1 };
|
enum DD : uint { DestIRAM = 0, DestBWRAM = 1 };
|
||||||
unsigned line;
|
uint line;
|
||||||
} dma;
|
} dma;
|
||||||
|
|
||||||
void dma_normal();
|
auto dma_normal() -> void;
|
||||||
void dma_cc1();
|
auto dma_cc1() -> void;
|
||||||
uint8 dma_cc1_read(unsigned addr);
|
auto dma_cc1_read(uint addr) -> uint8;
|
||||||
void dma_cc2();
|
auto dma_cc2() -> void;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
uint8 SA1::bus_read(unsigned addr) {
|
auto SA1::bus_read(uint addr) -> uint8 {
|
||||||
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
|
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
|
||||||
return mmio_read(addr);
|
return mmio_read(addr);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ uint8 SA1::bus_read(unsigned addr) {
|
||||||
return regs.mdr;
|
return regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::bus_write(unsigned addr, uint8 data) {
|
auto SA1::bus_write(uint addr, uint8 data) -> void {
|
||||||
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
|
if((addr & 0x40fe00) == 0x002200) { //$00-3f|80-bf:2200-23ff
|
||||||
return mmio_write(addr, data);
|
return mmio_write(addr, data);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ void SA1::bus_write(unsigned addr, uint8 data) {
|
||||||
//this is used both to keep VBR-reads from accessing MMIO registers, and
|
//this is used both to keep VBR-reads from accessing MMIO registers, and
|
||||||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||||
//these ports.
|
//these ports.
|
||||||
uint8 SA1::vbr_read(unsigned addr) {
|
auto SA1::vbr_read(uint addr) -> uint8 {
|
||||||
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
||||||
return mmcrom_read(addr);
|
return mmcrom_read(addr);
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,8 @@ uint8 SA1::vbr_read(unsigned addr) {
|
||||||
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
|
||||||
return iram.read(addr & 2047);
|
return iram.read(addr & 2047);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
|
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
|
||||||
|
@ -104,23 +106,23 @@ uint8 SA1::vbr_read(unsigned addr) {
|
||||||
//tick() == 2 clock ticks
|
//tick() == 2 clock ticks
|
||||||
//note: bus conflict delays are not emulated at this time
|
//note: bus conflict delays are not emulated at this time
|
||||||
|
|
||||||
void SA1::op_io() {
|
auto SA1::op_io() -> void {
|
||||||
tick();
|
tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::op_read(unsigned addr) {
|
auto SA1::op_read(uint addr) -> uint8 {
|
||||||
tick();
|
tick();
|
||||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||||
return bus_read(addr);
|
return bus_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::op_write(unsigned addr, uint8 data) {
|
auto SA1::op_write(uint addr, uint8 data) -> void {
|
||||||
tick();
|
tick();
|
||||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||||
bus_write(addr, regs.mdr = data);
|
bus_write(addr, regs.mdr = data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::mmcrom_read(unsigned addr) {
|
auto SA1::mmcrom_read(uint addr) -> uint8 {
|
||||||
if((addr & 0xffffe0) == 0x00ffe0) {
|
if((addr & 0xffffe0) == 0x00ffe0) {
|
||||||
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
|
if(addr == 0xffea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
|
||||||
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
|
if(addr == 0xffeb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
|
||||||
|
@ -128,7 +130,7 @@ uint8 SA1::mmcrom_read(unsigned addr) {
|
||||||
if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
|
if(addr == 0xffef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto read = [](unsigned addr) {
|
static auto read = [](uint addr) {
|
||||||
return sa1.rom.read(bus.mirror(addr, sa1.rom.size()));
|
return sa1.rom.read(bus.mirror(addr, sa1.rom.size()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,10 +177,10 @@ uint8 SA1::mmcrom_read(unsigned addr) {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmcrom_write(unsigned addr, uint8 data) {
|
auto SA1::mmcrom_write(uint addr, uint8 data) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::mmcbwram_read(unsigned addr) {
|
auto SA1::mmcbwram_read(uint addr) -> uint8 {
|
||||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||||
|
@ -192,7 +194,7 @@ uint8 SA1::mmcbwram_read(unsigned addr) {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmcbwram_write(unsigned addr, uint8 data) {
|
auto SA1::mmcbwram_write(uint addr, uint8 data) -> void {
|
||||||
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||||
cpu.synchronizeCoprocessors();
|
cpu.synchronizeCoprocessors();
|
||||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||||
|
@ -204,7 +206,7 @@ void SA1::mmcbwram_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::mmc_sa1_read(unsigned addr) {
|
auto SA1::mmc_sa1_read(uint addr) -> uint8 {
|
||||||
synchronize_cpu();
|
synchronize_cpu();
|
||||||
if(mmio.sw46 == 0) {
|
if(mmio.sw46 == 0) {
|
||||||
//$40-43:0000-ffff x 32 projection
|
//$40-43:0000-ffff x 32 projection
|
||||||
|
@ -217,7 +219,7 @@ uint8 SA1::mmc_sa1_read(unsigned addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmc_sa1_write(unsigned addr, uint8 data) {
|
auto SA1::mmc_sa1_write(uint addr, uint8 data) -> void {
|
||||||
synchronize_cpu();
|
synchronize_cpu();
|
||||||
if(mmio.sw46 == 0) {
|
if(mmio.sw46 == 0) {
|
||||||
//$40-43:0000-ffff x 32 projection
|
//$40-43:0000-ffff x 32 projection
|
||||||
|
@ -230,10 +232,10 @@ void SA1::mmc_sa1_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::bitmap_read(unsigned addr) {
|
auto SA1::bitmap_read(uint addr) -> uint8 {
|
||||||
if(mmio.bbf == 0) {
|
if(mmio.bbf == 0) {
|
||||||
//4bpp
|
//4bpp
|
||||||
unsigned shift = addr & 1;
|
uint shift = addr & 1;
|
||||||
addr = (addr >> 1) & (bwram.size() - 1);
|
addr = (addr >> 1) & (bwram.size() - 1);
|
||||||
switch(shift) {
|
switch(shift) {
|
||||||
case 0: return (bwram.read(addr) >> 0) & 15;
|
case 0: return (bwram.read(addr) >> 0) & 15;
|
||||||
|
@ -241,7 +243,7 @@ uint8 SA1::bitmap_read(unsigned addr) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//2bpp
|
//2bpp
|
||||||
unsigned shift = addr & 3;
|
uint shift = addr & 3;
|
||||||
addr = (addr >> 2) & (bwram.size() - 1);
|
addr = (addr >> 2) & (bwram.size() - 1);
|
||||||
switch(shift) {
|
switch(shift) {
|
||||||
case 0: return (bwram.read(addr) >> 0) & 3;
|
case 0: return (bwram.read(addr) >> 0) & 3;
|
||||||
|
@ -252,10 +254,10 @@ uint8 SA1::bitmap_read(unsigned addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::bitmap_write(unsigned addr, uint8 data) {
|
auto SA1::bitmap_write(uint addr, uint8 data) -> void {
|
||||||
if(mmio.bbf == 0) {
|
if(mmio.bbf == 0) {
|
||||||
//4bpp
|
//4bpp
|
||||||
unsigned shift = addr & 1;
|
uint shift = addr & 1;
|
||||||
addr = (addr >> 1) & (bwram.size() - 1);
|
addr = (addr >> 1) & (bwram.size() - 1);
|
||||||
switch(shift) {
|
switch(shift) {
|
||||||
case 0: data = (bwram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
case 0: data = (bwram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||||
|
@ -263,7 +265,7 @@ void SA1::bitmap_write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//2bpp
|
//2bpp
|
||||||
unsigned shift = addr & 3;
|
uint shift = addr & 3;
|
||||||
addr = (addr >> 2) & (bwram.size() - 1);
|
addr = (addr >> 2) & (bwram.size() - 1);
|
||||||
switch(shift) {
|
switch(shift) {
|
||||||
case 0: data = (bwram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
case 0: data = (bwram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
uint8 bus_read(unsigned addr);
|
auto bus_read(uint addr) -> uint8;
|
||||||
void bus_write(unsigned addr, uint8 data);
|
auto bus_write(uint addr, uint8 data) -> void;
|
||||||
uint8 vbr_read(unsigned addr);
|
auto vbr_read(uint addr) -> uint8;
|
||||||
|
|
||||||
alwaysinline void op_io();
|
alwaysinline auto op_io() -> void;
|
||||||
alwaysinline uint8 op_read(unsigned addr);
|
alwaysinline auto op_read(uint addr) -> uint8;
|
||||||
alwaysinline void op_write(unsigned addr, uint8 data);
|
alwaysinline auto op_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
uint8 mmcrom_read(unsigned addr);
|
auto mmcrom_read(uint addr) -> uint8;
|
||||||
void mmcrom_write(unsigned addr, uint8 data);
|
auto mmcrom_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
uint8 mmcbwram_read(unsigned addr);
|
auto mmcbwram_read(uint addr) -> uint8;
|
||||||
void mmcbwram_write(unsigned addr, uint8 data);
|
auto mmcbwram_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
uint8 mmc_sa1_read(unsigned addr);
|
auto mmc_sa1_read(uint addr) -> uint8;
|
||||||
void mmc_sa1_write(unsigned addr, uint8 data);
|
auto mmc_sa1_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
uint8 bitmap_read(unsigned addr);
|
auto bitmap_read(uint addr) -> uint8;
|
||||||
void bitmap_write(unsigned addr, uint8 data);
|
auto bitmap_write(uint addr, uint8 data) -> void;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//(CCNT) SA-1 control
|
//(CCNT) SA-1 control
|
||||||
void SA1::mmio_w2200(uint8 data) {
|
auto SA1::mmio_w2200(uint8 data) -> void {
|
||||||
if(mmio.sa1_resb && !(data & 0x80)) {
|
if(mmio.sa1_resb && !(data & 0x80)) {
|
||||||
//reset SA-1 CPU
|
//reset SA-1 CPU
|
||||||
regs.pc.w = mmio.crv;
|
regs.pc.w = mmio.crv;
|
||||||
|
@ -24,7 +24,7 @@ void SA1::mmio_w2200(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SIE) S-CPU interrupt enable
|
//(SIE) S-CPU interrupt enable
|
||||||
void SA1::mmio_w2201(uint8 data) {
|
auto SA1::mmio_w2201(uint8 data) -> void {
|
||||||
if(!mmio.cpu_irqen && (data & 0x80)) {
|
if(!mmio.cpu_irqen && (data & 0x80)) {
|
||||||
if(mmio.cpu_irqfl) {
|
if(mmio.cpu_irqfl) {
|
||||||
mmio.cpu_irqcl = 0;
|
mmio.cpu_irqcl = 0;
|
||||||
|
@ -44,7 +44,7 @@ void SA1::mmio_w2201(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SIC) S-CPU interrupt clear
|
//(SIC) S-CPU interrupt clear
|
||||||
void SA1::mmio_w2202(uint8 data) {
|
auto SA1::mmio_w2202(uint8 data) -> void {
|
||||||
mmio.cpu_irqcl = (data & 0x80);
|
mmio.cpu_irqcl = (data & 0x80);
|
||||||
mmio.chdma_irqcl = (data & 0x20);
|
mmio.chdma_irqcl = (data & 0x20);
|
||||||
|
|
||||||
|
@ -55,19 +55,19 @@ void SA1::mmio_w2202(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CRV) SA-1 reset vector
|
//(CRV) SA-1 reset vector
|
||||||
void SA1::mmio_w2203(uint8 data) { mmio.crv = (mmio.crv & 0xff00) | data; }
|
auto SA1::mmio_w2203(uint8 data) -> void { mmio.crv = (mmio.crv & 0xff00) | data; }
|
||||||
void SA1::mmio_w2204(uint8 data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
|
auto SA1::mmio_w2204(uint8 data) -> void { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
|
||||||
|
|
||||||
//(CNV) SA-1 NMI vector
|
//(CNV) SA-1 NMI vector
|
||||||
void SA1::mmio_w2205(uint8 data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
|
auto SA1::mmio_w2205(uint8 data) -> void { mmio.cnv = (mmio.cnv & 0xff00) | data; }
|
||||||
void SA1::mmio_w2206(uint8 data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
|
auto SA1::mmio_w2206(uint8 data) -> void { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
|
||||||
|
|
||||||
//(CIV) SA-1 IRQ vector
|
//(CIV) SA-1 IRQ vector
|
||||||
void SA1::mmio_w2207(uint8 data) { mmio.civ = (mmio.civ & 0xff00) | data; }
|
auto SA1::mmio_w2207(uint8 data) -> void { mmio.civ = (mmio.civ & 0xff00) | data; }
|
||||||
void SA1::mmio_w2208(uint8 data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
|
auto SA1::mmio_w2208(uint8 data) -> void { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
|
||||||
|
|
||||||
//(SCNT) S-CPU control
|
//(SCNT) S-CPU control
|
||||||
void SA1::mmio_w2209(uint8 data) {
|
auto SA1::mmio_w2209(uint8 data) -> void {
|
||||||
mmio.cpu_irq = (data & 0x80);
|
mmio.cpu_irq = (data & 0x80);
|
||||||
mmio.cpu_ivsw = (data & 0x40);
|
mmio.cpu_ivsw = (data & 0x40);
|
||||||
mmio.cpu_nvsw = (data & 0x10);
|
mmio.cpu_nvsw = (data & 0x10);
|
||||||
|
@ -83,7 +83,7 @@ void SA1::mmio_w2209(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CIE) SA-1 interrupt enable
|
//(CIE) SA-1 interrupt enable
|
||||||
void SA1::mmio_w220a(uint8 data) {
|
auto SA1::mmio_w220a(uint8 data) -> void {
|
||||||
if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0;
|
if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0;
|
||||||
if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0;
|
if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0;
|
||||||
if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;
|
if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;
|
||||||
|
@ -96,7 +96,7 @@ void SA1::mmio_w220a(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CIC) SA-1 interrupt clear
|
//(CIC) SA-1 interrupt clear
|
||||||
void SA1::mmio_w220b(uint8 data) {
|
auto SA1::mmio_w220b(uint8 data) -> void {
|
||||||
mmio.sa1_irqcl = (data & 0x80);
|
mmio.sa1_irqcl = (data & 0x80);
|
||||||
mmio.timer_irqcl = (data & 0x40);
|
mmio.timer_irqcl = (data & 0x40);
|
||||||
mmio.dma_irqcl = (data & 0x20);
|
mmio.dma_irqcl = (data & 0x20);
|
||||||
|
@ -109,96 +109,96 @@ void SA1::mmio_w220b(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SNV) S-CPU NMI vector
|
//(SNV) S-CPU NMI vector
|
||||||
void SA1::mmio_w220c(uint8 data) { mmio.snv = (mmio.snv & 0xff00) | data; }
|
auto SA1::mmio_w220c(uint8 data) -> void { mmio.snv = (mmio.snv & 0xff00) | data; }
|
||||||
void SA1::mmio_w220d(uint8 data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
|
auto SA1::mmio_w220d(uint8 data) -> void { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
|
||||||
|
|
||||||
//(SIV) S-CPU IRQ vector
|
//(SIV) S-CPU IRQ vector
|
||||||
void SA1::mmio_w220e(uint8 data) { mmio.siv = (mmio.siv & 0xff00) | data; }
|
auto SA1::mmio_w220e(uint8 data) -> void { mmio.siv = (mmio.siv & 0xff00) | data; }
|
||||||
void SA1::mmio_w220f(uint8 data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
|
auto SA1::mmio_w220f(uint8 data) -> void { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
|
||||||
|
|
||||||
//(TMC) H/V timer control
|
//(TMC) H/V timer control
|
||||||
void SA1::mmio_w2210(uint8 data) {
|
auto SA1::mmio_w2210(uint8 data) -> void {
|
||||||
mmio.hvselb = (data & 0x80);
|
mmio.hvselb = (data & 0x80);
|
||||||
mmio.ven = (data & 0x02);
|
mmio.ven = (data & 0x02);
|
||||||
mmio.hen = (data & 0x01);
|
mmio.hen = (data & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CTR) SA-1 timer restart
|
//(CTR) SA-1 timer restart
|
||||||
void SA1::mmio_w2211(uint8 data) {
|
auto SA1::mmio_w2211(uint8 data) -> void {
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
status.hcounter = 0;
|
status.hcounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(HCNT) H-count
|
//(HCNT) H-count
|
||||||
void SA1::mmio_w2212(uint8 data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
|
auto SA1::mmio_w2212(uint8 data) -> void { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
|
||||||
void SA1::mmio_w2213(uint8 data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
|
auto SA1::mmio_w2213(uint8 data) -> void { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
|
||||||
|
|
||||||
//(VCNT) V-count
|
//(VCNT) V-count
|
||||||
void SA1::mmio_w2214(uint8 data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
|
auto SA1::mmio_w2214(uint8 data) -> void { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
|
||||||
void SA1::mmio_w2215(uint8 data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
|
auto SA1::mmio_w2215(uint8 data) -> void { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
|
||||||
|
|
||||||
//(CXB) Super MMC bank C
|
//(CXB) Super MMC bank C
|
||||||
void SA1::mmio_w2220(uint8 data) {
|
auto SA1::mmio_w2220(uint8 data) -> void {
|
||||||
mmio.cbmode = (data & 0x80);
|
mmio.cbmode = (data & 0x80);
|
||||||
mmio.cb = (data & 0x07);
|
mmio.cb = (data & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(DXB) Super MMC bank D
|
//(DXB) Super MMC bank D
|
||||||
void SA1::mmio_w2221(uint8 data) {
|
auto SA1::mmio_w2221(uint8 data) -> void {
|
||||||
mmio.dbmode = (data & 0x80);
|
mmio.dbmode = (data & 0x80);
|
||||||
mmio.db = (data & 0x07);
|
mmio.db = (data & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(EXB) Super MMC bank E
|
//(EXB) Super MMC bank E
|
||||||
void SA1::mmio_w2222(uint8 data) {
|
auto SA1::mmio_w2222(uint8 data) -> void {
|
||||||
mmio.ebmode = (data & 0x80);
|
mmio.ebmode = (data & 0x80);
|
||||||
mmio.eb = (data & 0x07);
|
mmio.eb = (data & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(FXB) Super MMC bank F
|
//(FXB) Super MMC bank F
|
||||||
void SA1::mmio_w2223(uint8 data) {
|
auto SA1::mmio_w2223(uint8 data) -> void {
|
||||||
mmio.fbmode = (data & 0x80);
|
mmio.fbmode = (data & 0x80);
|
||||||
mmio.fb = (data & 0x07);
|
mmio.fb = (data & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(BMAPS) S-CPU BW-RAM address mapping
|
//(BMAPS) S-CPU BW-RAM address mapping
|
||||||
void SA1::mmio_w2224(uint8 data) {
|
auto SA1::mmio_w2224(uint8 data) -> void {
|
||||||
mmio.sbm = (data & 0x1f);
|
mmio.sbm = (data & 0x1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(BMAP) SA-1 BW-RAM address mapping
|
//(BMAP) SA-1 BW-RAM address mapping
|
||||||
void SA1::mmio_w2225(uint8 data) {
|
auto SA1::mmio_w2225(uint8 data) -> void {
|
||||||
mmio.sw46 = (data & 0x80);
|
mmio.sw46 = (data & 0x80);
|
||||||
mmio.cbm = (data & 0x7f);
|
mmio.cbm = (data & 0x7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SWBE) S-CPU BW-RAM write enable
|
//(SWBE) S-CPU BW-RAM write enable
|
||||||
void SA1::mmio_w2226(uint8 data) {
|
auto SA1::mmio_w2226(uint8 data) -> void {
|
||||||
mmio.swen = (data & 0x80);
|
mmio.swen = (data & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CWBE) SA-1 BW-RAM write enable
|
//(CWBE) SA-1 BW-RAM write enable
|
||||||
void SA1::mmio_w2227(uint8 data) {
|
auto SA1::mmio_w2227(uint8 data) -> void {
|
||||||
mmio.cwen = (data & 0x80);
|
mmio.cwen = (data & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(BWPA) BW-RAM write-protected area
|
//(BWPA) BW-RAM write-protected area
|
||||||
void SA1::mmio_w2228(uint8 data) {
|
auto SA1::mmio_w2228(uint8 data) -> void {
|
||||||
mmio.bwp = (data & 0x0f);
|
mmio.bwp = (data & 0x0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SIWP) S-CPU I-RAM write protection
|
//(SIWP) S-CPU I-RAM write protection
|
||||||
void SA1::mmio_w2229(uint8 data) {
|
auto SA1::mmio_w2229(uint8 data) -> void {
|
||||||
mmio.siwp = data;
|
mmio.siwp = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CIWP) SA-1 I-RAM write protection
|
//(CIWP) SA-1 I-RAM write protection
|
||||||
void SA1::mmio_w222a(uint8 data) {
|
auto SA1::mmio_w222a(uint8 data) -> void {
|
||||||
mmio.ciwp = data;
|
mmio.ciwp = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(DCNT) DMA control
|
//(DCNT) DMA control
|
||||||
void SA1::mmio_w2230(uint8 data) {
|
auto SA1::mmio_w2230(uint8 data) -> void {
|
||||||
mmio.dmaen = (data & 0x80);
|
mmio.dmaen = (data & 0x80);
|
||||||
mmio.dprio = (data & 0x40);
|
mmio.dprio = (data & 0x40);
|
||||||
mmio.cden = (data & 0x20);
|
mmio.cden = (data & 0x20);
|
||||||
|
@ -210,7 +210,7 @@ void SA1::mmio_w2230(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CDMA) character conversion DMA parameters
|
//(CDMA) character conversion DMA parameters
|
||||||
void SA1::mmio_w2231(uint8 data) {
|
auto SA1::mmio_w2231(uint8 data) -> void {
|
||||||
mmio.chdend = (data & 0x80);
|
mmio.chdend = (data & 0x80);
|
||||||
mmio.dmasize = (data >> 2) & 7;
|
mmio.dmasize = (data >> 2) & 7;
|
||||||
mmio.dmacb = (data & 0x03);
|
mmio.dmacb = (data & 0x03);
|
||||||
|
@ -221,16 +221,16 @@ void SA1::mmio_w2231(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(SDA) DMA source device start address
|
//(SDA) DMA source device start address
|
||||||
void SA1::mmio_w2232(uint8 data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
|
auto SA1::mmio_w2232(uint8 data) -> void { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
|
||||||
void SA1::mmio_w2233(uint8 data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
|
auto SA1::mmio_w2233(uint8 data) -> void { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
|
||||||
void SA1::mmio_w2234(uint8 data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
|
auto SA1::mmio_w2234(uint8 data) -> void { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
|
||||||
|
|
||||||
//(DDA) DMA destination start address
|
//(DDA) DMA destination start address
|
||||||
void SA1::mmio_w2235(uint8 data) {
|
auto SA1::mmio_w2235(uint8 data) -> void {
|
||||||
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
|
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmio_w2236(uint8 data) {
|
auto SA1::mmio_w2236(uint8 data) -> void {
|
||||||
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
|
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
|
||||||
|
|
||||||
if(mmio.dmaen == true) {
|
if(mmio.dmaen == true) {
|
||||||
|
@ -242,7 +242,7 @@ void SA1::mmio_w2236(uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmio_w2237(uint8 data) {
|
auto SA1::mmio_w2237(uint8 data) -> void {
|
||||||
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
|
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
|
||||||
|
|
||||||
if(mmio.dmaen == true) {
|
if(mmio.dmaen == true) {
|
||||||
|
@ -253,23 +253,23 @@ void SA1::mmio_w2237(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(DTC) DMA terminal counter
|
//(DTC) DMA terminal counter
|
||||||
void SA1::mmio_w2238(uint8 data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
|
auto SA1::mmio_w2238(uint8 data) -> void { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
|
||||||
void SA1::mmio_w2239(uint8 data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
|
auto SA1::mmio_w2239(uint8 data) -> void { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
|
||||||
|
|
||||||
//(BBF) BW-RAM bitmap format
|
//(BBF) BW-RAM bitmap format
|
||||||
void SA1::mmio_w223f(uint8 data) {
|
auto SA1::mmio_w223f(uint8 data) -> void {
|
||||||
mmio.bbf = (data & 0x80);
|
mmio.bbf = (data & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(BRF) bitmap register files
|
//(BRF) bitmap register files
|
||||||
void SA1::mmio_w2240(uint8 data) { mmio.brf[ 0] = data; }
|
auto SA1::mmio_w2240(uint8 data) -> void { mmio.brf[ 0] = data; }
|
||||||
void SA1::mmio_w2241(uint8 data) { mmio.brf[ 1] = data; }
|
auto SA1::mmio_w2241(uint8 data) -> void { mmio.brf[ 1] = data; }
|
||||||
void SA1::mmio_w2242(uint8 data) { mmio.brf[ 2] = data; }
|
auto SA1::mmio_w2242(uint8 data) -> void { mmio.brf[ 2] = data; }
|
||||||
void SA1::mmio_w2243(uint8 data) { mmio.brf[ 3] = data; }
|
auto SA1::mmio_w2243(uint8 data) -> void { mmio.brf[ 3] = data; }
|
||||||
void SA1::mmio_w2244(uint8 data) { mmio.brf[ 4] = data; }
|
auto SA1::mmio_w2244(uint8 data) -> void { mmio.brf[ 4] = data; }
|
||||||
void SA1::mmio_w2245(uint8 data) { mmio.brf[ 5] = data; }
|
auto SA1::mmio_w2245(uint8 data) -> void { mmio.brf[ 5] = data; }
|
||||||
void SA1::mmio_w2246(uint8 data) { mmio.brf[ 6] = data; }
|
auto SA1::mmio_w2246(uint8 data) -> void { mmio.brf[ 6] = data; }
|
||||||
void SA1::mmio_w2247(uint8 data) { mmio.brf[ 7] = data;
|
auto SA1::mmio_w2247(uint8 data) -> void { mmio.brf[ 7] = data;
|
||||||
if(mmio.dmaen == true) {
|
if(mmio.dmaen == true) {
|
||||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||||
dma_cc2();
|
dma_cc2();
|
||||||
|
@ -277,14 +277,14 @@ void SA1::mmio_w2247(uint8 data) { mmio.brf[ 7] = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmio_w2248(uint8 data) { mmio.brf[ 8] = data; }
|
auto SA1::mmio_w2248(uint8 data) -> void { mmio.brf[ 8] = data; }
|
||||||
void SA1::mmio_w2249(uint8 data) { mmio.brf[ 9] = data; }
|
auto SA1::mmio_w2249(uint8 data) -> void { mmio.brf[ 9] = data; }
|
||||||
void SA1::mmio_w224a(uint8 data) { mmio.brf[10] = data; }
|
auto SA1::mmio_w224a(uint8 data) -> void { mmio.brf[10] = data; }
|
||||||
void SA1::mmio_w224b(uint8 data) { mmio.brf[11] = data; }
|
auto SA1::mmio_w224b(uint8 data) -> void { mmio.brf[11] = data; }
|
||||||
void SA1::mmio_w224c(uint8 data) { mmio.brf[12] = data; }
|
auto SA1::mmio_w224c(uint8 data) -> void { mmio.brf[12] = data; }
|
||||||
void SA1::mmio_w224d(uint8 data) { mmio.brf[13] = data; }
|
auto SA1::mmio_w224d(uint8 data) -> void { mmio.brf[13] = data; }
|
||||||
void SA1::mmio_w224e(uint8 data) { mmio.brf[14] = data; }
|
auto SA1::mmio_w224e(uint8 data) -> void { mmio.brf[14] = data; }
|
||||||
void SA1::mmio_w224f(uint8 data) { mmio.brf[15] = data;
|
auto SA1::mmio_w224f(uint8 data) -> void { mmio.brf[15] = data;
|
||||||
if(mmio.dmaen == true) {
|
if(mmio.dmaen == true) {
|
||||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||||
dma_cc2();
|
dma_cc2();
|
||||||
|
@ -293,7 +293,7 @@ void SA1::mmio_w224f(uint8 data) { mmio.brf[15] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MCNT) arithmetic control
|
//(MCNT) arithmetic control
|
||||||
void SA1::mmio_w2250(uint8 data) {
|
auto SA1::mmio_w2250(uint8 data) -> void {
|
||||||
mmio.acm = (data & 0x02);
|
mmio.acm = (data & 0x02);
|
||||||
mmio.md = (data & 0x01);
|
mmio.md = (data & 0x01);
|
||||||
|
|
||||||
|
@ -301,24 +301,24 @@ void SA1::mmio_w2250(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MAL) multiplicand / dividend low
|
//(MAL) multiplicand / dividend low
|
||||||
void SA1::mmio_w2251(uint8 data) {
|
auto SA1::mmio_w2251(uint8 data) -> void {
|
||||||
mmio.ma = (mmio.ma & 0xff00) | data;
|
mmio.ma = (mmio.ma & 0xff00) | data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MAH) multiplicand / dividend high
|
//(MAH) multiplicand / dividend high
|
||||||
void SA1::mmio_w2252(uint8 data) {
|
auto SA1::mmio_w2252(uint8 data) -> void {
|
||||||
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
|
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MBL) multiplier / divisor low
|
//(MBL) multiplier / divisor low
|
||||||
void SA1::mmio_w2253(uint8 data) {
|
auto SA1::mmio_w2253(uint8 data) -> void {
|
||||||
mmio.mb = (mmio.mb & 0xff00) | data;
|
mmio.mb = (mmio.mb & 0xff00) | data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//(MBH) multiplier / divisor high
|
//(MBH) multiplier / divisor high
|
||||||
//multiplication / cumulative sum only resets MB
|
//multiplication / cumulative sum only resets MB
|
||||||
//division resets both MA and MB
|
//division resets both MA and MB
|
||||||
void SA1::mmio_w2254(uint8 data) {
|
auto SA1::mmio_w2254(uint8 data) -> void {
|
||||||
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
|
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
|
||||||
|
|
||||||
if(mmio.acm == 0) {
|
if(mmio.acm == 0) {
|
||||||
|
@ -348,7 +348,7 @@ void SA1::mmio_w2254(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(VBD) variable-length bit processing
|
//(VBD) variable-length bit processing
|
||||||
void SA1::mmio_w2258(uint8 data) {
|
auto SA1::mmio_w2258(uint8 data) -> void {
|
||||||
mmio.hl = (data & 0x80);
|
mmio.hl = (data & 0x80);
|
||||||
mmio.vb = (data & 0x0f);
|
mmio.vb = (data & 0x0f);
|
||||||
if(mmio.vb == 0) mmio.vb = 16;
|
if(mmio.vb == 0) mmio.vb = 16;
|
||||||
|
@ -362,12 +362,12 @@ void SA1::mmio_w2258(uint8 data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(VDA) variable-length bit game pak ROM start address
|
//(VDA) variable-length bit game pak ROM start address
|
||||||
void SA1::mmio_w2259(uint8 data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
|
auto SA1::mmio_w2259(uint8 data) -> void { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
|
||||||
void SA1::mmio_w225a(uint8 data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
|
auto SA1::mmio_w225a(uint8 data) -> void { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
|
||||||
void SA1::mmio_w225b(uint8 data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
|
auto SA1::mmio_w225b(uint8 data) -> void { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
|
||||||
|
|
||||||
//(SFR) S-CPU flag read
|
//(SFR) S-CPU flag read
|
||||||
uint8 SA1::mmio_r2300() {
|
auto SA1::mmio_r2300() -> uint8 {
|
||||||
uint8 data;
|
uint8 data;
|
||||||
data = mmio.cpu_irqfl << 7;
|
data = mmio.cpu_irqfl << 7;
|
||||||
data |= mmio.cpu_ivsw << 6;
|
data |= mmio.cpu_ivsw << 6;
|
||||||
|
@ -378,7 +378,7 @@ uint8 SA1::mmio_r2300() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(CFR) SA-1 flag read
|
//(CFR) SA-1 flag read
|
||||||
uint8 SA1::mmio_r2301() {
|
auto SA1::mmio_r2301() -> uint8 {
|
||||||
uint8 data;
|
uint8 data;
|
||||||
data = mmio.sa1_irqfl << 7;
|
data = mmio.sa1_irqfl << 7;
|
||||||
data |= mmio.timer_irqfl << 6;
|
data |= mmio.timer_irqfl << 6;
|
||||||
|
@ -389,29 +389,33 @@ uint8 SA1::mmio_r2301() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(HCR) hcounter read
|
//(HCR) hcounter read
|
||||||
uint8 SA1::mmio_r2302() {
|
auto SA1::mmio_r2302() -> uint8 {
|
||||||
//latch counters
|
//latch counters
|
||||||
mmio.hcr = status.hcounter >> 2;
|
mmio.hcr = status.hcounter >> 2;
|
||||||
mmio.vcr = status.vcounter;
|
mmio.vcr = status.vcounter;
|
||||||
return mmio.hcr >> 0; }
|
return mmio.hcr >> 0;
|
||||||
uint8 SA1::mmio_r2303() { return mmio.hcr >> 8; }
|
}
|
||||||
|
|
||||||
|
auto SA1::mmio_r2303() -> uint8 {
|
||||||
|
return mmio.hcr >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
//(VCR) vcounter read
|
//(VCR) vcounter read
|
||||||
uint8 SA1::mmio_r2304() { return mmio.vcr >> 0; }
|
auto SA1::mmio_r2304() -> uint8 { return mmio.vcr >> 0; }
|
||||||
uint8 SA1::mmio_r2305() { return mmio.vcr >> 8; }
|
auto SA1::mmio_r2305() -> uint8 { return mmio.vcr >> 8; }
|
||||||
|
|
||||||
//(MR) arithmetic result
|
//(MR) arithmetic result
|
||||||
uint8 SA1::mmio_r2306() { return mmio.mr >> 0; }
|
auto SA1::mmio_r2306() -> uint8 { return mmio.mr >> 0; }
|
||||||
uint8 SA1::mmio_r2307() { return mmio.mr >> 8; }
|
auto SA1::mmio_r2307() -> uint8 { return mmio.mr >> 8; }
|
||||||
uint8 SA1::mmio_r2308() { return mmio.mr >> 16; }
|
auto SA1::mmio_r2308() -> uint8 { return mmio.mr >> 16; }
|
||||||
uint8 SA1::mmio_r2309() { return mmio.mr >> 24; }
|
auto SA1::mmio_r2309() -> uint8 { return mmio.mr >> 24; }
|
||||||
uint8 SA1::mmio_r230a() { return mmio.mr >> 32; }
|
auto SA1::mmio_r230a() -> uint8 { return mmio.mr >> 32; }
|
||||||
|
|
||||||
//(OF) arithmetic overflow flag
|
//(OF) arithmetic overflow flag
|
||||||
uint8 SA1::mmio_r230b() { return mmio.overflow << 7; }
|
auto SA1::mmio_r230b() -> uint8 { return mmio.overflow << 7; }
|
||||||
|
|
||||||
//(VDPL) variable-length data read port low
|
//(VDPL) variable-length data read port low
|
||||||
uint8 SA1::mmio_r230c() {
|
auto SA1::mmio_r230c() -> uint8 {
|
||||||
uint32 data = (vbr_read(mmio.va + 0) << 0)
|
uint32 data = (vbr_read(mmio.va + 0) << 0)
|
||||||
| (vbr_read(mmio.va + 1) << 8)
|
| (vbr_read(mmio.va + 1) << 8)
|
||||||
| (vbr_read(mmio.va + 2) << 16);
|
| (vbr_read(mmio.va + 2) << 16);
|
||||||
|
@ -420,7 +424,7 @@ uint8 SA1::mmio_r230c() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(VDPH) variable-length data read port high
|
//(VDPH) variable-length data read port high
|
||||||
uint8 SA1::mmio_r230d() {
|
auto SA1::mmio_r230d() -> uint8 {
|
||||||
uint32 data = (vbr_read(mmio.va + 0) << 0)
|
uint32 data = (vbr_read(mmio.va + 0) << 0)
|
||||||
| (vbr_read(mmio.va + 1) << 8)
|
| (vbr_read(mmio.va + 1) << 8)
|
||||||
| (vbr_read(mmio.va + 2) << 16);
|
| (vbr_read(mmio.va + 2) << 16);
|
||||||
|
@ -437,11 +441,11 @@ uint8 SA1::mmio_r230d() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//(VC) version code register
|
//(VC) version code register
|
||||||
uint8 SA1::mmio_r230e() {
|
auto SA1::mmio_r230e() -> uint8 {
|
||||||
return 0x01; //true value unknown
|
return 0x01; //true value unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SA1::mmio_read(unsigned addr) {
|
auto SA1::mmio_read(uint addr) -> uint8 {
|
||||||
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronize_cpu());
|
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronize_cpu());
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
@ -466,7 +470,7 @@ uint8 SA1::mmio_read(unsigned addr) {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::mmio_write(unsigned addr, uint8 data) {
|
auto SA1::mmio_write(uint addr, uint8 data) -> void {
|
||||||
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronize_cpu());
|
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronize_cpu());
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
uint8 mmio_read(unsigned addr);
|
auto mmio_read(uint addr) -> uint8;
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
auto mmio_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
struct MMIO {
|
struct MMIO {
|
||||||
//$2200 CCNT
|
//$2200 CCNT
|
||||||
|
@ -63,19 +63,19 @@ struct MMIO {
|
||||||
|
|
||||||
//$2220 CXB
|
//$2220 CXB
|
||||||
bool cbmode;
|
bool cbmode;
|
||||||
unsigned cb;
|
uint cb;
|
||||||
|
|
||||||
//$2221 DXB
|
//$2221 DXB
|
||||||
bool dbmode;
|
bool dbmode;
|
||||||
unsigned db;
|
uint db;
|
||||||
|
|
||||||
//$2222 EXB
|
//$2222 EXB
|
||||||
bool ebmode;
|
bool ebmode;
|
||||||
unsigned eb;
|
uint eb;
|
||||||
|
|
||||||
//$2223 FXB
|
//$2223 FXB
|
||||||
bool fbmode;
|
bool fbmode;
|
||||||
unsigned fb;
|
uint fb;
|
||||||
|
|
||||||
//$2224 BMAPS
|
//$2224 BMAPS
|
||||||
uint8 sbm;
|
uint8 sbm;
|
||||||
|
@ -168,88 +168,88 @@ struct MMIO {
|
||||||
bool overflow;
|
bool overflow;
|
||||||
} mmio;
|
} mmio;
|
||||||
|
|
||||||
void mmio_w2200(uint8); //CCNT
|
auto mmio_w2200(uint8) -> void; //CCNT
|
||||||
void mmio_w2201(uint8); //SIE
|
auto mmio_w2201(uint8) -> void; //SIE
|
||||||
void mmio_w2202(uint8); //SIC
|
auto mmio_w2202(uint8) -> void; //SIC
|
||||||
void mmio_w2203(uint8); //CRVL
|
auto mmio_w2203(uint8) -> void; //CRVL
|
||||||
void mmio_w2204(uint8); //CRVH
|
auto mmio_w2204(uint8) -> void; //CRVH
|
||||||
void mmio_w2205(uint8); //CNVL
|
auto mmio_w2205(uint8) -> void; //CNVL
|
||||||
void mmio_w2206(uint8); //CNVH
|
auto mmio_w2206(uint8) -> void; //CNVH
|
||||||
void mmio_w2207(uint8); //CIVL
|
auto mmio_w2207(uint8) -> void; //CIVL
|
||||||
void mmio_w2208(uint8); //CIVH
|
auto mmio_w2208(uint8) -> void; //CIVH
|
||||||
void mmio_w2209(uint8); //SCNT
|
auto mmio_w2209(uint8) -> void; //SCNT
|
||||||
void mmio_w220a(uint8); //CIE
|
auto mmio_w220a(uint8) -> void; //CIE
|
||||||
void mmio_w220b(uint8); //CIC
|
auto mmio_w220b(uint8) -> void; //CIC
|
||||||
void mmio_w220c(uint8); //SNVL
|
auto mmio_w220c(uint8) -> void; //SNVL
|
||||||
void mmio_w220d(uint8); //SNVH
|
auto mmio_w220d(uint8) -> void; //SNVH
|
||||||
void mmio_w220e(uint8); //SIVL
|
auto mmio_w220e(uint8) -> void; //SIVL
|
||||||
void mmio_w220f(uint8); //SIVH
|
auto mmio_w220f(uint8) -> void; //SIVH
|
||||||
void mmio_w2210(uint8); //TMC
|
auto mmio_w2210(uint8) -> void; //TMC
|
||||||
void mmio_w2211(uint8); //CTR
|
auto mmio_w2211(uint8) -> void; //CTR
|
||||||
void mmio_w2212(uint8); //HCNTL
|
auto mmio_w2212(uint8) -> void; //HCNTL
|
||||||
void mmio_w2213(uint8); //HCNTH
|
auto mmio_w2213(uint8) -> void; //HCNTH
|
||||||
void mmio_w2214(uint8); //VCNTL
|
auto mmio_w2214(uint8) -> void; //VCNTL
|
||||||
void mmio_w2215(uint8); //VCNTH
|
auto mmio_w2215(uint8) -> void; //VCNTH
|
||||||
void mmio_w2220(uint8); //CXB
|
auto mmio_w2220(uint8) -> void; //CXB
|
||||||
void mmio_w2221(uint8); //DXB
|
auto mmio_w2221(uint8) -> void; //DXB
|
||||||
void mmio_w2222(uint8); //EXB
|
auto mmio_w2222(uint8) -> void; //EXB
|
||||||
void mmio_w2223(uint8); //FXB
|
auto mmio_w2223(uint8) -> void; //FXB
|
||||||
void mmio_w2224(uint8); //BMAPS
|
auto mmio_w2224(uint8) -> void; //BMAPS
|
||||||
void mmio_w2225(uint8); //BMAP
|
auto mmio_w2225(uint8) -> void; //BMAP
|
||||||
void mmio_w2226(uint8); //SBWE
|
auto mmio_w2226(uint8) -> void; //SBWE
|
||||||
void mmio_w2227(uint8); //CBWE
|
auto mmio_w2227(uint8) -> void; //CBWE
|
||||||
void mmio_w2228(uint8); //BWPA
|
auto mmio_w2228(uint8) -> void; //BWPA
|
||||||
void mmio_w2229(uint8); //SIWP
|
auto mmio_w2229(uint8) -> void; //SIWP
|
||||||
void mmio_w222a(uint8); //CIWP
|
auto mmio_w222a(uint8) -> void; //CIWP
|
||||||
void mmio_w2230(uint8); //DCNT
|
auto mmio_w2230(uint8) -> void; //DCNT
|
||||||
void mmio_w2231(uint8); //CDMA
|
auto mmio_w2231(uint8) -> void; //CDMA
|
||||||
void mmio_w2232(uint8); //SDAL
|
auto mmio_w2232(uint8) -> void; //SDAL
|
||||||
void mmio_w2233(uint8); //SDAH
|
auto mmio_w2233(uint8) -> void; //SDAH
|
||||||
void mmio_w2234(uint8); //SDAB
|
auto mmio_w2234(uint8) -> void; //SDAB
|
||||||
void mmio_w2235(uint8); //DDAL
|
auto mmio_w2235(uint8) -> void; //DDAL
|
||||||
void mmio_w2236(uint8); //DDAH
|
auto mmio_w2236(uint8) -> void; //DDAH
|
||||||
void mmio_w2237(uint8); //DDAB
|
auto mmio_w2237(uint8) -> void; //DDAB
|
||||||
void mmio_w2238(uint8); //DTCL
|
auto mmio_w2238(uint8) -> void; //DTCL
|
||||||
void mmio_w2239(uint8); //DTCH
|
auto mmio_w2239(uint8) -> void; //DTCH
|
||||||
void mmio_w223f(uint8); //BBF
|
auto mmio_w223f(uint8) -> void; //BBF
|
||||||
void mmio_w2240(uint8); //BRF0
|
auto mmio_w2240(uint8) -> void; //BRF0
|
||||||
void mmio_w2241(uint8); //BRF1
|
auto mmio_w2241(uint8) -> void; //BRF1
|
||||||
void mmio_w2242(uint8); //BRF2
|
auto mmio_w2242(uint8) -> void; //BRF2
|
||||||
void mmio_w2243(uint8); //BRF3
|
auto mmio_w2243(uint8) -> void; //BRF3
|
||||||
void mmio_w2244(uint8); //BRF4
|
auto mmio_w2244(uint8) -> void; //BRF4
|
||||||
void mmio_w2245(uint8); //BRF5
|
auto mmio_w2245(uint8) -> void; //BRF5
|
||||||
void mmio_w2246(uint8); //BRF6
|
auto mmio_w2246(uint8) -> void; //BRF6
|
||||||
void mmio_w2247(uint8); //BRF7
|
auto mmio_w2247(uint8) -> void; //BRF7
|
||||||
void mmio_w2248(uint8); //BRF8
|
auto mmio_w2248(uint8) -> void; //BRF8
|
||||||
void mmio_w2249(uint8); //BRF9
|
auto mmio_w2249(uint8) -> void; //BRF9
|
||||||
void mmio_w224a(uint8); //BRFA
|
auto mmio_w224a(uint8) -> void; //BRFA
|
||||||
void mmio_w224b(uint8); //BRFB
|
auto mmio_w224b(uint8) -> void; //BRFB
|
||||||
void mmio_w224c(uint8); //BRFC
|
auto mmio_w224c(uint8) -> void; //BRFC
|
||||||
void mmio_w224d(uint8); //BRFD
|
auto mmio_w224d(uint8) -> void; //BRFD
|
||||||
void mmio_w224e(uint8); //BRFE
|
auto mmio_w224e(uint8) -> void; //BRFE
|
||||||
void mmio_w224f(uint8); //BRFF
|
auto mmio_w224f(uint8) -> void; //BRFF
|
||||||
void mmio_w2250(uint8); //MCNT
|
auto mmio_w2250(uint8) -> void; //MCNT
|
||||||
void mmio_w2251(uint8); //MAL
|
auto mmio_w2251(uint8) -> void; //MAL
|
||||||
void mmio_w2252(uint8); //MAH
|
auto mmio_w2252(uint8) -> void; //MAH
|
||||||
void mmio_w2253(uint8); //MBL
|
auto mmio_w2253(uint8) -> void; //MBL
|
||||||
void mmio_w2254(uint8); //MBH
|
auto mmio_w2254(uint8) -> void; //MBH
|
||||||
void mmio_w2258(uint8); //VBD
|
auto mmio_w2258(uint8) -> void; //VBD
|
||||||
void mmio_w2259(uint8); //VDAL
|
auto mmio_w2259(uint8) -> void; //VDAL
|
||||||
void mmio_w225a(uint8); //VDAH
|
auto mmio_w225a(uint8) -> void; //VDAH
|
||||||
void mmio_w225b(uint8); //VDAB
|
auto mmio_w225b(uint8) -> void; //VDAB
|
||||||
|
|
||||||
uint8 mmio_r2300(); //SFR
|
auto mmio_r2300() -> uint8; //SFR
|
||||||
uint8 mmio_r2301(); //CFR
|
auto mmio_r2301() -> uint8; //CFR
|
||||||
uint8 mmio_r2302(); //HCRL
|
auto mmio_r2302() -> uint8; //HCRL
|
||||||
uint8 mmio_r2303(); //HCRH
|
auto mmio_r2303() -> uint8; //HCRH
|
||||||
uint8 mmio_r2304(); //VCRL
|
auto mmio_r2304() -> uint8; //VCRL
|
||||||
uint8 mmio_r2305(); //VCRH
|
auto mmio_r2305() -> uint8; //VCRH
|
||||||
uint8 mmio_r2306(); //MR [00-07]
|
auto mmio_r2306() -> uint8; //MR [00-07]
|
||||||
uint8 mmio_r2307(); //MR [08-15]
|
auto mmio_r2307() -> uint8; //MR [08-15]
|
||||||
uint8 mmio_r2308(); //MR [16-23]
|
auto mmio_r2308() -> uint8; //MR [16-23]
|
||||||
uint8 mmio_r2309(); //MR [24-31]
|
auto mmio_r2309() -> uint8; //MR [24-31]
|
||||||
uint8 mmio_r230a(); //MR [32-40]
|
auto mmio_r230a() -> uint8; //MR [32-40]
|
||||||
uint8 mmio_r230b(); //OF
|
auto mmio_r230b() -> uint8; //OF
|
||||||
uint8 mmio_r230c(); //VDPL
|
auto mmio_r230c() -> uint8; //VDPL
|
||||||
uint8 mmio_r230d(); //VDPH
|
auto mmio_r230d() -> uint8; //VDPH
|
||||||
uint8 mmio_r230e(); //VC
|
auto mmio_r230e() -> uint8; //VC
|
||||||
|
|
|
@ -10,9 +10,9 @@ SA1 sa1;
|
||||||
#include "memory/memory.cpp"
|
#include "memory/memory.cpp"
|
||||||
#include "mmio/mmio.cpp"
|
#include "mmio/mmio.cpp"
|
||||||
|
|
||||||
void SA1::Enter() { sa1.enter(); }
|
auto SA1::Enter() -> void { sa1.enter(); }
|
||||||
|
|
||||||
void SA1::enter() {
|
auto SA1::enter() -> void {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
|
@ -35,7 +35,7 @@ void SA1::enter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::op_irq() {
|
auto SA1::op_irq() -> void {
|
||||||
op_read(regs.pc.d);
|
op_read(regs.pc.d);
|
||||||
op_io();
|
op_io();
|
||||||
if(!regs.e) op_writestack(regs.pc.b);
|
if(!regs.e) op_writestack(regs.pc.b);
|
||||||
|
@ -48,7 +48,7 @@ void SA1::op_irq() {
|
||||||
regs.p.d = 0;
|
regs.p.d = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::last_cycle() {
|
auto SA1::last_cycle() -> void {
|
||||||
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
|
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
|
||||||
status.interrupt_pending = true;
|
status.interrupt_pending = true;
|
||||||
regs.vector = mmio.cnv;
|
regs.vector = mmio.cnv;
|
||||||
|
@ -75,11 +75,11 @@ void SA1::last_cycle() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SA1::interrupt_pending() {
|
auto SA1::interrupt_pending() -> bool {
|
||||||
return status.interrupt_pending;
|
return status.interrupt_pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::tick() {
|
auto SA1::tick() -> void {
|
||||||
step(2);
|
step(2);
|
||||||
if(++status.tick_counter == 0) synchronize_cpu();
|
if(++status.tick_counter == 0) synchronize_cpu();
|
||||||
|
|
||||||
|
@ -110,33 +110,33 @@ void SA1::tick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::trigger_irq() {
|
auto SA1::trigger_irq() -> void {
|
||||||
mmio.timer_irqfl = true;
|
mmio.timer_irqfl = true;
|
||||||
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
|
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::init() {
|
auto SA1::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::load() {
|
auto SA1::load() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::unload() {
|
auto SA1::unload() -> void {
|
||||||
rom.reset();
|
rom.reset();
|
||||||
iram.reset();
|
iram.reset();
|
||||||
bwram.reset();
|
bwram.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::power() {
|
auto SA1::power() -> void {
|
||||||
regs.a = regs.x = regs.y = 0x0000;
|
regs.a = regs.x = regs.y = 0x0000;
|
||||||
regs.s = 0x01ff;
|
regs.s = 0x01ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SA1::reset() {
|
auto SA1::reset() -> void {
|
||||||
create(SA1::Enter, system.cpuFrequency());
|
create(SA1::Enter, system.cpuFrequency());
|
||||||
|
|
||||||
cpubwram.dma = false;
|
cpubwram.dma = false;
|
||||||
for(unsigned addr = 0; addr < iram.size(); addr++) {
|
for(auto addr : range(iram.size())) {
|
||||||
iram.write(addr, 0x00);
|
iram.write(addr, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
struct SA1 : Processor::R65816, public Coprocessor {
|
struct SA1 : Processor::R65816, public Coprocessor {
|
||||||
MappedRAM rom;
|
|
||||||
MappedRAM iram;
|
|
||||||
MappedRAM bwram;
|
|
||||||
|
|
||||||
#include "bus/bus.hpp"
|
#include "bus/bus.hpp"
|
||||||
#include "dma/dma.hpp"
|
#include "dma/dma.hpp"
|
||||||
#include "memory/memory.hpp"
|
#include "memory/memory.hpp"
|
||||||
|
@ -18,22 +14,26 @@ struct SA1 : Processor::R65816, public Coprocessor {
|
||||||
uint16 hcounter;
|
uint16 hcounter;
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
static void Enter();
|
static auto Enter() -> void;
|
||||||
void enter();
|
auto enter() -> void;
|
||||||
void tick();
|
auto tick() -> void;
|
||||||
void op_irq();
|
auto op_irq() -> void;
|
||||||
|
|
||||||
alwaysinline void trigger_irq();
|
alwaysinline auto trigger_irq() -> void;
|
||||||
alwaysinline void last_cycle();
|
alwaysinline auto last_cycle() -> void;
|
||||||
alwaysinline bool interrupt_pending();
|
alwaysinline auto interrupt_pending() -> bool;
|
||||||
|
|
||||||
void init();
|
auto init() -> void;
|
||||||
void load();
|
auto load() -> void;
|
||||||
void unload();
|
auto unload() -> void;
|
||||||
void power();
|
auto power() -> void;
|
||||||
void reset();
|
auto reset() -> void;
|
||||||
|
|
||||||
void serialize(serializer&);
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
|
MappedRAM rom;
|
||||||
|
MappedRAM iram;
|
||||||
|
MappedRAM bwram;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SA1 sa1;
|
extern SA1 sa1;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void SA1::serialize(serializer& s) {
|
auto SA1::serialize(serializer& s) -> void {
|
||||||
R65816::serialize(s);
|
R65816::serialize(s);
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
|
|
||||||
//input manager
|
//input manager
|
||||||
|
|
||||||
void SDD1::Decomp::IM::init(unsigned offset_) {
|
auto SDD1::Decomp::IM::init(uint offset_) -> void {
|
||||||
offset = offset_;
|
offset = offset_;
|
||||||
bit_count = 4;
|
bit_count = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::Decomp::IM::get_codeword(uint8 code_length) {
|
auto SDD1::Decomp::IM::get_codeword(uint8 code_length) -> uint8 {
|
||||||
uint8 codeword;
|
uint8 codeword;
|
||||||
uint8 comp_count;
|
uint8 comp_count;
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ const uint8 SDD1::Decomp::GCD::run_count[] = {
|
||||||
0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
|
0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
void SDD1::Decomp::GCD::get_run_count(uint8 code_number, uint8& mps_count, bool& lps_index) {
|
auto SDD1::Decomp::GCD::get_run_count(uint8 code_number, uint8& mps_count, bool& lps_index) -> void {
|
||||||
uint8 codeword = self.im.get_codeword(code_number);
|
uint8 codeword = self.im.get_codeword(code_number);
|
||||||
|
|
||||||
if(codeword & 0x80) {
|
if(codeword & 0x80) {
|
||||||
|
@ -83,12 +83,12 @@ void SDD1::Decomp::GCD::get_run_count(uint8 code_number, uint8& mps_count, bool&
|
||||||
|
|
||||||
//bits generator
|
//bits generator
|
||||||
|
|
||||||
void SDD1::Decomp::BG::init() {
|
auto SDD1::Decomp::BG::init() -> void {
|
||||||
mps_count = 0;
|
mps_count = 0;
|
||||||
lps_index = 0;
|
lps_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::Decomp::BG::get_bit(bool& end_of_run) {
|
auto SDD1::Decomp::BG::get_bit(bool& end_of_run) -> uint8 {
|
||||||
if(!(mps_count || lps_index)) self.gcd.get_run_count(code_number, mps_count, lps_index);
|
if(!(mps_count || lps_index)) self.gcd.get_run_count(code_number, mps_count, lps_index);
|
||||||
|
|
||||||
uint8 bit;
|
uint8 bit;
|
||||||
|
@ -142,14 +142,14 @@ const SDD1::Decomp::PEM::State SDD1::Decomp::PEM::evolution_table[33] = {
|
||||||
{7, 24, 22},
|
{7, 24, 22},
|
||||||
};
|
};
|
||||||
|
|
||||||
void SDD1::Decomp::PEM::init() {
|
auto SDD1::Decomp::PEM::init() -> void {
|
||||||
for(unsigned i = 0; i < 32; i++) {
|
for(auto n : range(32)) {
|
||||||
context_info[i].status = 0;
|
context_info[n].status = 0;
|
||||||
context_info[i].mps = 0;
|
context_info[n].mps = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::Decomp::PEM::get_bit(uint8 context) {
|
auto SDD1::Decomp::PEM::get_bit(uint8 context) -> uint8 {
|
||||||
ContextInfo& info = context_info[context];
|
ContextInfo& info = context_info[context];
|
||||||
uint8 current_status = info.status;
|
uint8 current_status = info.status;
|
||||||
uint8 current_mps = info.mps;
|
uint8 current_mps = info.mps;
|
||||||
|
@ -182,11 +182,11 @@ uint8 SDD1::Decomp::PEM::get_bit(uint8 context) {
|
||||||
|
|
||||||
//context model
|
//context model
|
||||||
|
|
||||||
void SDD1::Decomp::CM::init(unsigned offset) {
|
auto SDD1::Decomp::CM::init(uint offset) -> void {
|
||||||
bitplanes_info = sdd1.mmc_read(offset) & 0xc0;
|
bitplanes_info = sdd1.mmc_read(offset) & 0xc0;
|
||||||
context_bits_info = sdd1.mmc_read(offset) & 0x30;
|
context_bits_info = sdd1.mmc_read(offset) & 0x30;
|
||||||
bit_number = 0;
|
bit_number = 0;
|
||||||
for(unsigned i = 0; i < 8; i++) previous_bitplane_bits[i] = 0;
|
for(auto n : range(8)) previous_bitplane_bits[n] = 0;
|
||||||
switch(bitplanes_info) {
|
switch(bitplanes_info) {
|
||||||
case 0x00: current_bitplane = 1; break;
|
case 0x00: current_bitplane = 1; break;
|
||||||
case 0x40: current_bitplane = 7; break;
|
case 0x40: current_bitplane = 7; break;
|
||||||
|
@ -194,7 +194,7 @@ void SDD1::Decomp::CM::init(unsigned offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::Decomp::CM::get_bit() {
|
auto SDD1::Decomp::CM::get_bit() -> uint8 {
|
||||||
switch(bitplanes_info) {
|
switch(bitplanes_info) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
current_bitplane ^= 0x01;
|
current_bitplane ^= 0x01;
|
||||||
|
@ -230,12 +230,12 @@ uint8 SDD1::Decomp::CM::get_bit() {
|
||||||
|
|
||||||
//output logic
|
//output logic
|
||||||
|
|
||||||
void SDD1::Decomp::OL::init(unsigned offset) {
|
auto SDD1::Decomp::OL::init(uint offset) -> void {
|
||||||
bitplanes_info = sdd1.mmc_read(offset) & 0xc0;
|
bitplanes_info = sdd1.mmc_read(offset) & 0xc0;
|
||||||
r0 = 0x01;
|
r0 = 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::Decomp::OL::decompress() {
|
auto SDD1::Decomp::OL::decompress() -> uint8 {
|
||||||
switch(bitplanes_info) {
|
switch(bitplanes_info) {
|
||||||
case 0x00: case 0x40: case 0x80:
|
case 0x00: case 0x40: case 0x80:
|
||||||
if(r0 == 0) {
|
if(r0 == 0) {
|
||||||
|
@ -257,7 +257,14 @@ uint8 SDD1::Decomp::OL::decompress() {
|
||||||
|
|
||||||
//core
|
//core
|
||||||
|
|
||||||
void SDD1::Decomp::init(unsigned offset) {
|
SDD1::Decomp::Decomp():
|
||||||
|
im(*this), gcd(*this),
|
||||||
|
bg0(*this, 0), bg1(*this, 1), bg2(*this, 2), bg3(*this, 3),
|
||||||
|
bg4(*this, 4), bg5(*this, 5), bg6(*this, 6), bg7(*this, 7),
|
||||||
|
pem(*this), cm(*this), ol(*this) {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SDD1::Decomp::init(uint offset) -> void {
|
||||||
im.init(offset);
|
im.init(offset);
|
||||||
bg0.init();
|
bg0.init();
|
||||||
bg1.init();
|
bg1.init();
|
||||||
|
@ -272,13 +279,6 @@ void SDD1::Decomp::init(unsigned offset) {
|
||||||
ol.init(offset);
|
ol.init(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::Decomp::read() {
|
auto SDD1::Decomp::read() -> uint8 {
|
||||||
return ol.decompress();
|
return ol.decompress();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDD1::Decomp::Decomp():
|
|
||||||
im(*this), gcd(*this),
|
|
||||||
bg0(*this, 0), bg1(*this, 1), bg2(*this, 2), bg3(*this, 3),
|
|
||||||
bg4(*this, 4), bg5(*this, 5), bg6(*this, 6), bg7(*this, 7),
|
|
||||||
pem(*this), cm(*this), ol(*this) {
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,38 +1,43 @@
|
||||||
struct Decomp {
|
struct Decomp {
|
||||||
struct IM { //input manager
|
struct IM { //input manager
|
||||||
Decomp& self;
|
|
||||||
void init(unsigned offset);
|
|
||||||
uint8 get_codeword(uint8 code_length);
|
|
||||||
IM(SDD1::Decomp& self) : self(self) {}
|
IM(SDD1::Decomp& self) : self(self) {}
|
||||||
|
auto init(uint offset) -> void;
|
||||||
|
auto get_codeword(uint8 code_length) -> uint8;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned offset;
|
Decomp& self;
|
||||||
unsigned bit_count;
|
uint offset;
|
||||||
|
uint bit_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GCD { //golomb-code decoder
|
struct GCD { //golomb-code decoder
|
||||||
|
GCD(SDD1::Decomp& self) : self(self) {}
|
||||||
|
auto get_run_count(uint8 code_number, uint8& mps_count, bool& lps_index) -> void;
|
||||||
|
|
||||||
|
private:
|
||||||
Decomp& self;
|
Decomp& self;
|
||||||
static const uint8 run_count[256];
|
static const uint8 run_count[256];
|
||||||
void get_run_count(uint8 code_number, uint8& mps_count, bool& lps_index);
|
|
||||||
GCD(SDD1::Decomp& self) : self(self) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BG { //bits generator
|
struct BG { //bits generator
|
||||||
Decomp& self;
|
|
||||||
void init();
|
|
||||||
uint8 get_bit(bool& end_of_run);
|
|
||||||
BG(SDD1::Decomp& self, uint8 code_number) : self(self), code_number(code_number) {}
|
BG(SDD1::Decomp& self, uint8 code_number) : self(self), code_number(code_number) {}
|
||||||
|
auto init() -> void;
|
||||||
|
auto get_bit(bool& end_of_run) -> uint8;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Decomp& self;
|
||||||
const uint8 code_number;
|
const uint8 code_number;
|
||||||
uint8 mps_count;
|
uint8 mps_count;
|
||||||
bool lps_index;
|
bool lps_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PEM { //probability estimation module
|
struct PEM { //probability estimation module
|
||||||
Decomp& self;
|
|
||||||
void init();
|
|
||||||
uint8 get_bit(uint8 context);
|
|
||||||
PEM(SDD1::Decomp& self) : self(self) {}
|
PEM(SDD1::Decomp& self) : self(self) {}
|
||||||
|
auto init() -> void;
|
||||||
|
auto get_bit(uint8 context) -> uint8;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Decomp& self;
|
||||||
struct State {
|
struct State {
|
||||||
uint8 code_number;
|
uint8 code_number;
|
||||||
uint8 next_if_mps;
|
uint8 next_if_mps;
|
||||||
|
@ -46,11 +51,12 @@ struct Decomp {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CM { //context model
|
struct CM { //context model
|
||||||
Decomp& self;
|
|
||||||
void init(unsigned offset);
|
|
||||||
uint8 get_bit();
|
|
||||||
CM(SDD1::Decomp& self) : self(self) {}
|
CM(SDD1::Decomp& self) : self(self) {}
|
||||||
|
auto init(uint offset) -> void;
|
||||||
|
uint8 get_bit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Decomp& self;
|
||||||
uint8 bitplanes_info;
|
uint8 bitplanes_info;
|
||||||
uint8 context_bits_info;
|
uint8 context_bits_info;
|
||||||
uint8 bit_number;
|
uint8 bit_number;
|
||||||
|
@ -59,18 +65,19 @@ struct Decomp {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OL { //output logic
|
struct OL { //output logic
|
||||||
Decomp& self;
|
|
||||||
void init(unsigned offset);
|
|
||||||
uint8 decompress();
|
|
||||||
OL(SDD1::Decomp& self) : self(self) {}
|
OL(SDD1::Decomp& self) : self(self) {}
|
||||||
|
auto init(uint offset) -> void;
|
||||||
|
auto decompress() -> uint8;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Decomp& self;
|
||||||
uint8 bitplanes_info;
|
uint8 bitplanes_info;
|
||||||
uint8 r0, r1, r2;
|
uint8 r0, r1, r2;
|
||||||
};
|
};
|
||||||
|
|
||||||
void init(unsigned offset);
|
|
||||||
uint8 read();
|
|
||||||
Decomp();
|
Decomp();
|
||||||
|
auto init(uint offset) -> void;
|
||||||
|
auto read() -> uint8;
|
||||||
|
|
||||||
IM im;
|
IM im;
|
||||||
GCD gcd;
|
GCD gcd;
|
||||||
|
|
|
@ -7,7 +7,7 @@ SDD1 sdd1;
|
||||||
#include "decomp.cpp"
|
#include "decomp.cpp"
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
|
|
||||||
void SDD1::init() {
|
auto SDD1::init() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::load() {
|
void SDD1::load() {
|
||||||
|
@ -17,15 +17,15 @@ void SDD1::load() {
|
||||||
bus.map({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}, 0x80, 0xbf, 0x4300, 0x437f);
|
bus.map({&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}, 0x80, 0xbf, 0x4300, 0x437f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::unload() {
|
auto SDD1::unload() -> void {
|
||||||
rom.reset();
|
rom.reset();
|
||||||
ram.reset();
|
ram.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::power() {
|
auto SDD1::power() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::reset() {
|
auto SDD1::reset() -> void {
|
||||||
sdd1_enable = 0x00;
|
sdd1_enable = 0x00;
|
||||||
xfer_enable = 0x00;
|
xfer_enable = 0x00;
|
||||||
dma_ready = false;
|
dma_ready = false;
|
||||||
|
@ -35,13 +35,13 @@ void SDD1::reset() {
|
||||||
mmc[2] = 2 << 20;
|
mmc[2] = 2 << 20;
|
||||||
mmc[3] = 3 << 20;
|
mmc[3] = 3 << 20;
|
||||||
|
|
||||||
for(unsigned i = 0; i < 8; i++) {
|
for(auto n : range(8)) {
|
||||||
dma[i].addr = 0;
|
dma[n].addr = 0;
|
||||||
dma[i].size = 0;
|
dma[n].size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::read(unsigned addr) {
|
auto SDD1::read(uint addr) -> uint8 {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if((addr & 0x4380) == 0x4300) {
|
if((addr & 0x4380) == 0x4300) {
|
||||||
|
@ -58,11 +58,11 @@ uint8 SDD1::read(unsigned addr) {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::write(unsigned addr, uint8 data) {
|
auto SDD1::write(uint addr, uint8 data) -> void {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if((addr & 0x4380) == 0x4300) {
|
if((addr & 0x4380) == 0x4300) {
|
||||||
unsigned channel = (addr >> 4) & 7;
|
uint channel = (addr >> 4) & 7;
|
||||||
switch(addr & 15) {
|
switch(addr & 15) {
|
||||||
case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
|
case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
|
||||||
case 3: dma[channel].addr = (dma[channel].addr & 0xff00ff) + (data << 8); break;
|
case 3: dma[channel].addr = (dma[channel].addr & 0xff00ff) + (data << 8); break;
|
||||||
|
@ -85,7 +85,7 @@ void SDD1::write(unsigned addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::mmc_read(unsigned addr) {
|
auto SDD1::mmc_read(uint addr) -> uint8 {
|
||||||
return rom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
|
return rom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ uint8 SDD1::mmc_read(unsigned addr) {
|
||||||
//
|
//
|
||||||
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
|
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
|
||||||
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
|
//one transfer per $420b write (for spooling purposes). however, this is not known for certain.
|
||||||
uint8 SDD1::mcurom_read(unsigned addr) {
|
auto SDD1::mcurom_read(uint addr) -> uint8 {
|
||||||
if(addr < 0x400000) { //(addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
if(addr < 0x400000) { //(addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
|
||||||
return rom.read(addr);
|
return rom.read(addr);
|
||||||
//addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
|
//addr = ((addr & 0x7f0000) >> 1) | (addr & 0x7fff);
|
||||||
|
@ -117,10 +117,10 @@ uint8 SDD1::mcurom_read(unsigned addr) {
|
||||||
//$40-7f|c0-ff:0000-ffff (MMC)
|
//$40-7f|c0-ff:0000-ffff (MMC)
|
||||||
if(sdd1_enable & xfer_enable) {
|
if(sdd1_enable & xfer_enable) {
|
||||||
//at least one channel has S-DD1 decompression enabled ...
|
//at least one channel has S-DD1 decompression enabled ...
|
||||||
for(unsigned i = 0; i < 8; i++) {
|
for(auto n : range(8)) {
|
||||||
if(sdd1_enable & xfer_enable & (1 << i)) {
|
if(sdd1_enable & xfer_enable & (1 << n)) {
|
||||||
//S-DD1 always uses fixed transfer mode, so address will not change during transfer
|
//S-DD1 always uses fixed transfer mode, so address will not change during transfer
|
||||||
if(addr == dma[i].addr) {
|
if(addr == dma[n].addr) {
|
||||||
if(!dma_ready) {
|
if(!dma_ready) {
|
||||||
//prepare streaming decompression
|
//prepare streaming decompression
|
||||||
decomp.init(addr);
|
decomp.init(addr);
|
||||||
|
@ -129,9 +129,9 @@ uint8 SDD1::mcurom_read(unsigned addr) {
|
||||||
|
|
||||||
//fetch a decompressed byte; once finished, disable channel and invalidate buffer
|
//fetch a decompressed byte; once finished, disable channel and invalidate buffer
|
||||||
uint8 data = decomp.read();
|
uint8 data = decomp.read();
|
||||||
if(--dma[i].size == 0) {
|
if(--dma[n].size == 0) {
|
||||||
dma_ready = false;
|
dma_ready = false;
|
||||||
xfer_enable &= ~(1 << i);
|
xfer_enable &= ~(1 << n);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -144,10 +144,10 @@ uint8 SDD1::mcurom_read(unsigned addr) {
|
||||||
return mmc_read(addr);
|
return mmc_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::mcurom_write(unsigned addr, uint8 data) {
|
auto SDD1::mcurom_write(uint addr, uint8 data) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SDD1::mcuram_read(unsigned addr) {
|
auto SDD1::mcuram_read(uint addr) -> uint8 {
|
||||||
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||||
return ram.read(addr & 0x1fff);
|
return ram.read(addr & 0x1fff);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ uint8 SDD1::mcuram_read(unsigned addr) {
|
||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDD1::mcuram_write(unsigned addr, uint8 data) {
|
auto SDD1::mcuram_write(uint addr, uint8 data) -> void {
|
||||||
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
if((addr & 0x60e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
|
||||||
return ram.write(addr & 0x1fff, data);
|
return ram.write(addr & 0x1fff, data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
struct SDD1 {
|
struct SDD1 {
|
||||||
|
auto init() -> void;
|
||||||
|
auto load() -> void;
|
||||||
|
auto unload() -> void;
|
||||||
|
auto power() -> void;
|
||||||
|
auto reset() -> void;
|
||||||
|
|
||||||
|
auto read(uint addr) -> uint8;
|
||||||
|
auto write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto mmc_read(uint addr) -> uint8;
|
||||||
|
|
||||||
|
auto mcurom_read(uint addr) -> uint8;
|
||||||
|
auto mcurom_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto mcuram_read(uint addr) -> uint8;
|
||||||
|
auto mcuram_write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
MappedRAM rom;
|
MappedRAM rom;
|
||||||
MappedRAM ram;
|
MappedRAM ram;
|
||||||
|
|
||||||
void init();
|
|
||||||
void load();
|
|
||||||
void unload();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
uint8 mmc_read(unsigned addr);
|
|
||||||
|
|
||||||
uint8 mcurom_read(unsigned addr);
|
|
||||||
void mcurom_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
uint8 mcuram_read(unsigned addr);
|
|
||||||
void mcuram_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
void serialize(serializer&);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8 sdd1_enable; //channel bit-mask
|
uint8 sdd1_enable; //channel bit-mask
|
||||||
uint8 xfer_enable; //channel bit-mask
|
uint8 xfer_enable; //channel bit-mask
|
||||||
bool dma_ready; //used to initialize decompression module
|
bool dma_ready; //used to initialize decompression module
|
||||||
unsigned mmc[4]; //memory map controller ROM indices
|
uint mmc[4]; //memory map controller ROM indices
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned addr; //$43x2-$43x4 -- DMA transfer address
|
uint addr; //$43x2-$43x4 -- DMA transfer address
|
||||||
uint16 size; //$43x5-$43x6 -- DMA transfer size
|
uint16 size; //$43x5-$43x6 -- DMA transfer size
|
||||||
} dma[8];
|
} dma[8];
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void SDD1::serialize(serializer& s) {
|
auto SDD1::serialize(serializer& s) -> void {
|
||||||
s.array(ram.data(), ram.size());
|
s.array(ram.data(), ram.size());
|
||||||
|
|
||||||
s.integer(sdd1_enable);
|
s.integer(sdd1_enable);
|
||||||
|
@ -6,7 +6,7 @@ void SDD1::serialize(serializer& s) {
|
||||||
s.integer(dma_ready);
|
s.integer(dma_ready);
|
||||||
s.array(mmc);
|
s.array(mmc);
|
||||||
|
|
||||||
for(unsigned n = 0; n < 8; n++) {
|
for(auto n : range(8)) {
|
||||||
s.integer(dma[n].addr);
|
s.integer(dma[n].addr);
|
||||||
s.integer(dma[n].size);
|
s.integer(dma[n].size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
uint4 SharpRTC::rtc_read(uint4 addr) {
|
auto SharpRTC::rtc_read(uint4 addr) -> uint4 {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0: return second % 10;
|
case 0: return second % 10;
|
||||||
case 1: return second / 10;
|
case 1: return second / 10;
|
||||||
|
@ -17,7 +17,7 @@ uint4 SharpRTC::rtc_read(uint4 addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::rtc_write(uint4 addr, uint4 data) {
|
auto SharpRTC::rtc_write(uint4 addr, uint4 data) -> void {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0: second = second / 10 * 10 + data; break;
|
case 0: second = second / 10 * 10 + data; break;
|
||||||
case 1: second = data * 10 + second % 10; break;
|
case 1: second = data * 10 + second % 10; break;
|
||||||
|
@ -35,14 +35,14 @@ void SharpRTC::rtc_write(uint4 addr, uint4 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::load(const uint8* data) {
|
auto SharpRTC::load(const uint8* data) -> void {
|
||||||
for(unsigned byte = 0; byte < 8; byte++) {
|
for(auto byte : range(8)) {
|
||||||
rtc_write(byte * 2 + 0, data[byte] >> 0);
|
rtc_write(byte * 2 + 0, data[byte] >> 0);
|
||||||
rtc_write(byte * 2 + 1, data[byte] >> 4);
|
rtc_write(byte * 2 + 1, data[byte] >> 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 timestamp = 0;
|
uint64 timestamp = 0;
|
||||||
for(unsigned byte = 0; byte < 8; byte++) {
|
for(auto byte : range(8)) {
|
||||||
timestamp |= data[8 + byte] << (byte * 8);
|
timestamp |= data[8 + byte] << (byte * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,14 +53,14 @@ void SharpRTC::load(const uint8* data) {
|
||||||
while(diff--) tick_second();
|
while(diff--) tick_second();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::save(uint8* data) {
|
auto SharpRTC::save(uint8* data) -> void {
|
||||||
for(unsigned byte = 0; byte < 8; byte++) {
|
for(auto byte : range(8)) {
|
||||||
data[byte] = rtc_read(byte * 2 + 0) << 0;
|
data[byte] = rtc_read(byte * 2 + 0) << 0;
|
||||||
data[byte] |= rtc_read(byte * 2 + 1) << 4;
|
data[byte] |= rtc_read(byte * 2 + 1) << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 timestamp = (uint64)time(0);
|
uint64 timestamp = (uint64)time(nullptr);
|
||||||
for(unsigned byte = 0; byte < 8; byte++) {
|
for(auto byte : range(8)) {
|
||||||
data[8 + byte] = timestamp;
|
data[8 + byte] = timestamp;
|
||||||
timestamp >>= 8;
|
timestamp >>= 8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
void SharpRTC::serialize(serializer& s) {
|
auto SharpRTC::serialize(serializer& s) -> void {
|
||||||
Thread::serialize(s);
|
Thread::serialize(s);
|
||||||
|
|
||||||
s.integer((unsigned&)rtc_state);
|
s.integer((uint&)rtc_state);
|
||||||
s.integer(rtc_index);
|
s.integer(rtc_index);
|
||||||
|
|
||||||
s.integer(second);
|
s.integer(second);
|
||||||
|
|
|
@ -1,47 +1,47 @@
|
||||||
struct SharpRTC : Coprocessor {
|
struct SharpRTC : Coprocessor {
|
||||||
static void Enter();
|
static auto Enter() -> void;
|
||||||
void enter();
|
auto enter() -> void;
|
||||||
|
|
||||||
void init();
|
auto init() -> void;
|
||||||
void load();
|
auto load() -> void;
|
||||||
void unload();
|
auto unload() -> void;
|
||||||
void power();
|
auto power() -> void;
|
||||||
void reset();
|
auto reset() -> void;
|
||||||
void sync();
|
auto sync() -> void;
|
||||||
|
|
||||||
uint8 read(unsigned addr);
|
auto read(uint addr) -> uint8;
|
||||||
void write(unsigned addr, uint8 data);
|
auto write(uint addr, uint8 data) -> void;
|
||||||
|
|
||||||
void serialize(serializer&);
|
auto serialize(serializer&) -> void;
|
||||||
|
|
||||||
enum class State : unsigned { Ready, Command, Read, Write } rtc_state;
|
enum class State : uint { Ready, Command, Read, Write } rtc_state;
|
||||||
signed rtc_index;
|
int rtc_index;
|
||||||
|
|
||||||
unsigned second;
|
uint second;
|
||||||
unsigned minute;
|
uint minute;
|
||||||
unsigned hour;
|
uint hour;
|
||||||
unsigned day;
|
uint day;
|
||||||
unsigned month;
|
uint month;
|
||||||
unsigned year;
|
uint year;
|
||||||
unsigned weekday;
|
uint weekday;
|
||||||
|
|
||||||
//memory.cpp
|
//memory.cpp
|
||||||
uint4 rtc_read(uint4 addr);
|
auto rtc_read(uint4 addr) -> uint4;
|
||||||
void rtc_write(uint4 addr, uint4 data);
|
auto rtc_write(uint4 addr, uint4 data) -> void;
|
||||||
|
|
||||||
void load(const uint8* data);
|
auto load(const uint8* data) -> void;
|
||||||
void save(uint8* data);
|
auto save(uint8* data) -> void;
|
||||||
|
|
||||||
//time.cpp
|
//time.cpp
|
||||||
static const unsigned daysinmonth[12];
|
static const uint daysinmonth[12];
|
||||||
void tick_second();
|
auto tick_second() -> void;
|
||||||
void tick_minute();
|
auto tick_minute() -> void;
|
||||||
void tick_hour();
|
auto tick_hour() -> void;
|
||||||
void tick_day();
|
auto tick_day() -> void;
|
||||||
void tick_month();
|
auto tick_month() -> void;
|
||||||
void tick_year();
|
auto tick_year() -> void;
|
||||||
|
|
||||||
unsigned calculate_weekday(unsigned year, unsigned month, unsigned day);
|
auto calculate_weekday(uint year, uint month, uint day) -> uint;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SharpRTC sharprtc;
|
extern SharpRTC sharprtc;
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
const unsigned SharpRTC::daysinmonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
const uint SharpRTC::daysinmonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
|
||||||
void SharpRTC::tick_second() {
|
auto SharpRTC::tick_second() -> void {
|
||||||
if(++second < 60) return;
|
if(++second < 60) return;
|
||||||
second = 0;
|
second = 0;
|
||||||
tick_minute();
|
tick_minute();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::tick_minute() {
|
auto SharpRTC::tick_minute() -> void {
|
||||||
if(++minute < 60) return;
|
if(++minute < 60) return;
|
||||||
minute = 0;
|
minute = 0;
|
||||||
tick_hour();
|
tick_hour();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::tick_hour() {
|
auto SharpRTC::tick_hour() -> void {
|
||||||
if(++hour < 24) return;
|
if(++hour < 24) return;
|
||||||
hour = 0;
|
hour = 0;
|
||||||
tick_day();
|
tick_day();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::tick_day() {
|
auto SharpRTC::tick_day() -> void {
|
||||||
unsigned days = daysinmonth[month % 12];
|
uint days = daysinmonth[month % 12];
|
||||||
|
|
||||||
//add one day for leap years
|
//add one day for leap years
|
||||||
if(year % 400 == 0) days++;
|
if(year % 400 == 0) days++;
|
||||||
|
@ -31,13 +31,13 @@ void SharpRTC::tick_day() {
|
||||||
tick_month();
|
tick_month();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::tick_month() {
|
auto SharpRTC::tick_month() -> void {
|
||||||
if(month++ < 12) return;
|
if(month++ < 12) return;
|
||||||
month = 1;
|
month = 1;
|
||||||
tick_year();
|
tick_year();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharpRTC::tick_year() {
|
auto SharpRTC::tick_year() -> void {
|
||||||
year++;
|
year++;
|
||||||
year = (uint12)year;
|
year = (uint12)year;
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,9 @@ void SharpRTC::tick_year() {
|
||||||
//returns day of week for specified date
|
//returns day of week for specified date
|
||||||
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
||||||
//usage: calculate_weekday(2008, 1, 1) returns weekday of January 1st, 2008
|
//usage: calculate_weekday(2008, 1, 1) returns weekday of January 1st, 2008
|
||||||
unsigned SharpRTC::calculate_weekday(unsigned year, unsigned month, unsigned day) {
|
auto SharpRTC::calculate_weekday(uint year, uint month, uint day) -> uint {
|
||||||
unsigned y = 1000, m = 1; //SharpRTC epoch is 1000-01-01
|
uint y = 1000, m = 1; //SharpRTC epoch is 1000-01-01
|
||||||
unsigned sum = 0; //number of days passed since epoch
|
uint sum = 0; //number of days passed since epoch
|
||||||
|
|
||||||
year = max(1000, year);
|
year = max(1000, year);
|
||||||
month = max(1, min(12, month));
|
month = max(1, min(12, month));
|
||||||
|
@ -64,7 +64,7 @@ unsigned SharpRTC::calculate_weekday(unsigned year, unsigned month, unsigned day
|
||||||
}
|
}
|
||||||
|
|
||||||
while(m < month) {
|
while(m < month) {
|
||||||
unsigned days = daysinmonth[m - 1];
|
uint days = daysinmonth[m - 1];
|
||||||
bool leapyearmonth = false;
|
bool leapyearmonth = false;
|
||||||
if(days == 28) {
|
if(days == 28) {
|
||||||
if(y % 4 == 0) {
|
if(y % 4 == 0) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue