mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v048 release.
The biggest feature of this new release is the addition of save state support. Note that this is only currently supported for normal games, and the SPC7110 and OBC-1 co-processors. Other special chips, such as the SuperFX and SA-1, cannot currently save and load state files. I will be adding support for other co-processors little by little in future releases. Changelog: - Added save state support - Added SPC7110 and OBC1 save state support - Added new tools group, with new cheat code and save state managers - Lots of new UI shortcuts: quick save state, quick load state, show state manager, etc - Escape key will now close both the settings and tools group windows - Added major speed-ups to both SuperFX and SA-1 emulation; both now run ~15-25% faster than v047 - Added new video filter, LQ2x; it's as fast as Scale2x while being almost as smooth as HQ2x - Re-wrote HQ2x algorithm; code size was reduced to less than 10% of its original size with virtually no speed loss - Corrected SuperFX2 cache access timing; fixes Stunt Race FX menus and slowdown in other titles - Relaxed palette write limitations for PGA Tour Golf [Jonas Quinn] - Fixed a slight timing issue that was breaking 'An Americal Tail - Feivel Goes West' - Turned off auto-save of SRAM as it was causing slowdowns when writing to flash memory; can be re-enabled via bsnes.cfg -> system.autoSaveMemory = true - Added bsnes.cfg -> system.autoHideMenus, defaults to false; when true, menu and status bars will be hidden upon entering fullscreen mode - Added skeletons for ST011 and ST018 support. Both Quick-move titles get in-game now - Re-wrote S-CPU and S-SMP processor cores to use templates, removed custom pre-processor - Split PPUcounter into a base class inherited by both PPU and CPU; allows both cores to run out-of-order - Split inline header functions to separate files, allows headers to be included in any order now
This commit is contained in:
parent
7b0e484c18
commit
c26f9d912a
|
@ -79,7 +79,8 @@ link += $(call ifhas,input.rawinput,$(ruby),-ldinput8 -ldxguid)
|
|||
objects := libco ruby libreader libfilter
|
||||
objects += system cartridge cheat
|
||||
objects += memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu
|
||||
objects += sgb superfx sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
objects += sgb superfx sa1
|
||||
objects += bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 st011 st018
|
||||
|
||||
ifeq ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
|
@ -192,6 +193,8 @@ obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
|
|||
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.o : chip/st010/st010.cpp chip/st010/*
|
||||
obj/st011.o : chip/st011/st011.cpp chip/st011/*
|
||||
obj/st018.o : chip/st018/st018.cpp chip/st018/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define BSNES_VERSION "0.047"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
static const char bsnesVersion[] = "0.048";
|
||||
static const char bsnesTitle[] = "bsnes";
|
||||
|
||||
#define BUSCORE sBus
|
||||
#define CPUCORE sCPU
|
||||
|
@ -22,11 +22,14 @@
|
|||
#include <nall/detect.hpp>
|
||||
#include <nall/dl.hpp>
|
||||
#include <nall/endian.hpp>
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/moduloarray.hpp>
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/priorityqueue.hpp>
|
||||
#include <nall/property.hpp>
|
||||
#include <nall/serializer.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
@ -36,8 +39,10 @@ using namespace nall;
|
|||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
typedef int64_t int64;
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
#include "interface.hpp"
|
||||
|
|
BIN
src/bsnes.lnk
BIN
src/bsnes.lnk
Binary file not shown.
|
@ -1,4 +1,5 @@
|
|||
#include <../base.hpp>
|
||||
#include <nall/crc32.hpp>
|
||||
|
||||
#define CARTRIDGE_CPP
|
||||
namespace SNES {
|
||||
|
@ -57,6 +58,18 @@ void Cartridge::load(Mode cartridge_mode) {
|
|||
memory::gbrom.write_protect(true);
|
||||
memory::gbram.write_protect(false);
|
||||
|
||||
unsigned checksum = ~0;
|
||||
for(unsigned n = 0; n < memory::cartrom.size(); n++) checksum = crc32_adjust(checksum, memory::cartrom[n]);
|
||||
if(memory::bsxflash.size() != 0 && memory::bsxflash.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::bsxflash.size(); n++) checksum = crc32_adjust(checksum, memory::bsxflash[n]);
|
||||
if(memory::stArom.size() != 0 && memory::stArom.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::stArom.size(); n++) checksum = crc32_adjust(checksum, memory::stArom[n]);
|
||||
if(memory::stBrom.size() != 0 && memory::stBrom.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::stBrom.size(); n++) checksum = crc32_adjust(checksum, memory::stBrom[n]);
|
||||
if(memory::gbrom.size() != 0 && memory::gbrom.size() != ~0)
|
||||
for(unsigned n = 0; n < memory::gbrom.size(); n++) checksum = crc32_adjust(checksum, memory::gbrom[n]);
|
||||
set(crc32, ~checksum);
|
||||
|
||||
bus.load_cart();
|
||||
set(loaded, true);
|
||||
}
|
||||
|
@ -86,6 +99,36 @@ Cartridge::Type Cartridge::detect_image_type(uint8_t *data, unsigned size) const
|
|||
return info.type;
|
||||
}
|
||||
|
||||
void Cartridge::serialize(serializer &s) {
|
||||
if(memory::cartram.size() != 0 && memory::cartram.size() != ~0) {
|
||||
s.array(memory::cartram.data(), memory::cartram.size());
|
||||
}
|
||||
|
||||
if(memory::cartrtc.size() != 0 && memory::cartrtc.size() != ~0) {
|
||||
s.array(memory::cartrtc.data(), memory::cartrtc.size());
|
||||
}
|
||||
|
||||
if(memory::bsxram.size() != 0 && memory::bsxram.size() != ~0) {
|
||||
s.array(memory::bsxram.data(), memory::bsxram.size());
|
||||
}
|
||||
|
||||
if(memory::bsxpram.size() != 0 && memory::bsxpram.size() != ~0) {
|
||||
s.array(memory::bsxpram.data(), memory::bsxpram.size());
|
||||
}
|
||||
|
||||
if(memory::stAram.size() != 0 && memory::stAram.size() != ~0) {
|
||||
s.array(memory::stAram.data(), memory::stAram.size());
|
||||
}
|
||||
|
||||
if(memory::stBram.size() != 0 && memory::stBram.size() != ~0) {
|
||||
s.array(memory::stBram.data(), memory::stBram.size());
|
||||
}
|
||||
|
||||
if(memory::gbram.size() != 0 && memory::gbram.size() != ~0) {
|
||||
s.array(memory::gbram.data(), memory::gbram.size());
|
||||
}
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
set(loaded, false);
|
||||
unload();
|
||||
|
|
|
@ -50,10 +50,11 @@ public:
|
|||
//warning: if loaded() == false, no other property is considered valid!
|
||||
|
||||
property_t<bool> loaded; //is a base cartridge inserted?
|
||||
property_t<unsigned> crc32; //crc32 of all files sans headers
|
||||
|
||||
property_t<Mode> mode;
|
||||
property_t<Region> region;
|
||||
property_t<MemoryMapper> mapper;
|
||||
property_t<Mode> mode;
|
||||
property_t<Region> region;
|
||||
property_t<MemoryMapper> mapper;
|
||||
property_t<DSP1MemoryMapper> dsp1_mapper;
|
||||
|
||||
property_t<bool> has_bsx_slot;
|
||||
|
@ -69,11 +70,10 @@ public:
|
|||
|
||||
//main interface
|
||||
void load(Mode);
|
||||
//void read();
|
||||
//void load();
|
||||
void unload();
|
||||
Type detect_image_type(uint8_t *data, unsigned size) const;
|
||||
|
||||
void serialize(serializer&);
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
unsigned Cheat::count() const { return code.size(); }
|
||||
bool Cheat::active() const { return cheat_enabled; }
|
||||
bool Cheat::exists(unsigned addr) const { return mask[addr >> 3] & 1 << (addr & 7); }
|
|
@ -32,14 +32,20 @@ bool Cheat::decode(const char *s, Cheat::cheat_t &item) const {
|
|||
item.enabled = false;
|
||||
item.count = 0;
|
||||
|
||||
string code = s;
|
||||
code.replace(" ", "");
|
||||
|
||||
lstring list;
|
||||
list.split("+", s);
|
||||
list.split("+", code);
|
||||
|
||||
for(unsigned n = 0; n < list.size(); n++) {
|
||||
unsigned addr;
|
||||
uint8_t data;
|
||||
type_t type;
|
||||
if(decode(list[n], addr, data, type) == false) return false;
|
||||
if(decode(list[n], addr, data, type) == false) {
|
||||
item.count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
item.addr[item.count] = addr;
|
||||
item.data[item.count] = data;
|
||||
|
@ -95,9 +101,9 @@ void Cheat::disable() {
|
|||
//cheat list manipulation routines
|
||||
//================================
|
||||
|
||||
bool Cheat::add(bool enable, const char *code_, const char *desc_) {
|
||||
void Cheat::add(bool enable, const char *code_, const char *desc_) {
|
||||
cheat_t item;
|
||||
if(decode(code_, item) == false) return false;
|
||||
decode(code_, item);
|
||||
|
||||
unsigned i = code.size();
|
||||
code[i] = item;
|
||||
|
@ -108,12 +114,11 @@ bool Cheat::add(bool enable, const char *code_, const char *desc_) {
|
|||
update(code[i]);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::edit(unsigned i, bool enable, const char *code_, const char *desc_) {
|
||||
void Cheat::edit(unsigned i, bool enable, const char *code_, const char *desc_) {
|
||||
cheat_t item;
|
||||
if(decode(code_, item) == false) return false;
|
||||
decode(code_, item);
|
||||
|
||||
//disable current code and clear from code lookup table
|
||||
code[i].enabled = false;
|
||||
|
@ -127,7 +132,6 @@ bool Cheat::edit(unsigned i, bool enable, const char *code_, const char *desc_)
|
|||
update(code[i]);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::remove(unsigned i) {
|
||||
|
|
|
@ -25,12 +25,12 @@ public:
|
|||
void enable();
|
||||
void disable();
|
||||
|
||||
inline unsigned count() const { return code.size(); }
|
||||
inline bool active() const { return cheat_enabled; }
|
||||
inline bool exists(unsigned addr) const { return mask[addr >> 3] & 1 << (addr & 7); }
|
||||
inline unsigned count() const;
|
||||
inline bool active() const;
|
||||
inline bool exists(unsigned addr) const;
|
||||
|
||||
bool add(bool enable, const char *code, const char *desc);
|
||||
bool edit(unsigned i, bool enable, const char *code, const char *desc);
|
||||
void add(bool enable, const char *code, const char *desc);
|
||||
void edit(unsigned i, bool enable, const char *code, const char *desc);
|
||||
bool remove(unsigned i);
|
||||
bool get(unsigned i, cheat_t &item) const;
|
||||
|
||||
|
|
|
@ -12,3 +12,5 @@
|
|||
#include "dsp4/dsp4.hpp"
|
||||
#include "obc1/obc1.hpp"
|
||||
#include "st010/st010.hpp"
|
||||
#include "st011/st011.hpp"
|
||||
#include "st018/st018.hpp"
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
C4 emulation
|
||||
|
||||
Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
*/
|
||||
//=============
|
||||
//Cx4 emulation
|
||||
//=============
|
||||
//Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
//Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
|
||||
#include <../base.hpp>
|
||||
|
||||
|
@ -17,24 +16,31 @@ Cx4 cx4;
|
|||
#include "cx4oam.cpp"
|
||||
#include "cx4ops.cpp"
|
||||
|
||||
void Cx4::init() {}
|
||||
void Cx4::enable() {}
|
||||
void Cx4::init() {
|
||||
}
|
||||
|
||||
void Cx4::enable() {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
}
|
||||
|
||||
uint32 Cx4::ldr(uint8 r) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr + 0] << 0)
|
||||
| (reg[addr + 1] << 8)
|
||||
| (reg[addr + 2] << 16);
|
||||
}
|
||||
|
||||
void Cx4::str(uint8 r, uint32 data) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr ] = (data);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr + 0] = (data >> 0);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
reg[addr + 2] = (data >> 16);
|
||||
}
|
||||
|
||||
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||
int64_t rx = x & 0xffffff;
|
||||
int64_t ry = y & 0xffffff;
|
||||
int64 rx = x & 0xffffff;
|
||||
int64 ry = y & 0xffffff;
|
||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||
if(ry & 0x800000)ry |= ~0x7fffff;
|
||||
|
||||
|
@ -71,8 +77,9 @@ void Cx4::immediate_reg(uint32 start) {
|
|||
}
|
||||
|
||||
void Cx4::transfer_data() {
|
||||
uint32 src;
|
||||
uint16 dest, count;
|
||||
uint32 src;
|
||||
uint16 dest, count;
|
||||
|
||||
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
|
||||
count = (reg[0x43]) | (reg[0x44] << 8);
|
||||
dest = (reg[0x45]) | (reg[0x46] << 8);
|
||||
|
@ -86,29 +93,29 @@ void Cx4::write(unsigned addr, uint8 data) {
|
|||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
//ram
|
||||
//ram
|
||||
ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr < 0x1f00) {
|
||||
//unmapped
|
||||
//unmapped
|
||||
return;
|
||||
}
|
||||
|
||||
//command register
|
||||
//command register
|
||||
reg[addr & 0xff] = data;
|
||||
|
||||
if(addr == 0x1f47) {
|
||||
//memory transfer
|
||||
//memory transfer
|
||||
transfer_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x1f4f) {
|
||||
//c4 command
|
||||
//c4 command
|
||||
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
|
||||
//c4 test command
|
||||
//c4 test command
|
||||
reg[0x80] = data >> 2;
|
||||
return;
|
||||
}
|
||||
|
@ -154,12 +161,12 @@ void Cx4::writeb(uint16 addr, uint8 data) {
|
|||
}
|
||||
|
||||
void Cx4::writew(uint16 addr, uint16 data) {
|
||||
write(addr, data);
|
||||
write(addr + 0, data >> 0);
|
||||
write(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void Cx4::writel(uint16 addr, uint32 data) {
|
||||
write(addr, data);
|
||||
write(addr + 0, data >> 0);
|
||||
write(addr + 1, data >> 8);
|
||||
write(addr + 2, data >> 16);
|
||||
}
|
||||
|
@ -198,5 +205,5 @@ void Cx4::reset() {
|
|||
memset(ram, 0, 0x0c00);
|
||||
memset(reg, 0, 0x0100);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -14,22 +14,22 @@ void Cx4::C4TransfWireFrame() {
|
|||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal - 0x95;
|
||||
|
||||
//Rotate X
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
}
|
||||
|
@ -56,35 +56,36 @@ void Cx4::C4TransfWireFrame2() {
|
|||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal;
|
||||
|
||||
//Rotate X
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
||||
}
|
||||
|
||||
void Cx4::C4DrawWireFrame() {
|
||||
uint32 line = readl(0x1f80);
|
||||
uint32 point1, point2;
|
||||
int16 X1, Y1, Z1;
|
||||
int16 X2, Y2, Z2;
|
||||
uint8 Color;
|
||||
uint32 line = readl(0x1f80);
|
||||
uint32 point1, point2;
|
||||
int16 X1, Y1, Z1;
|
||||
int16 X2, Y2, Z2;
|
||||
uint8 Color;
|
||||
|
||||
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
|
||||
if(bus.read(line) == 0xff && bus.read(line + 1) == 0xff) {
|
||||
int32 tmp = line - 5;
|
||||
int32 tmp = line - 5;
|
||||
while(bus.read(tmp + 2) == 0xff && bus.read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
||||
point1 = (read(0x1f82) << 16) | (bus.read(tmp + 2) << 8) | bus.read(tmp + 3);
|
||||
} else {
|
||||
|
@ -104,7 +105,7 @@ uint8 Color;
|
|||
}
|
||||
|
||||
void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
||||
//Transform coordinates
|
||||
//Transform coordinates
|
||||
C4WFXVal = (int16)X1;
|
||||
C4WFYVal = (int16)Y1;
|
||||
C4WFZVal = Z1;
|
||||
|
@ -123,7 +124,7 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
|||
X2 = (C4WFXVal + 48) << 8;
|
||||
Y2 = (C4WFYVal + 48) << 8;
|
||||
|
||||
//Get line info
|
||||
//Get line info
|
||||
C4WFXVal = (int16)(X1 >> 8);
|
||||
C4WFYVal = (int16)(Y1 >> 8);
|
||||
C4WFX2Val = (int16)(X2 >> 8);
|
||||
|
@ -132,11 +133,11 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
|||
X2 = (int16)C4WFXVal;
|
||||
Y2 = (int16)C4WFYVal;
|
||||
|
||||
//Render line
|
||||
//Render line
|
||||
for(int32 i = C4WFDist ? C4WFDist : 1; i > 0; i--) {
|
||||
if(X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) {
|
||||
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
|
||||
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
|
||||
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
|
||||
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
|
||||
ram[addr + 0x300] &= ~bit;
|
||||
ram[addr + 0x301] &= ~bit;
|
||||
if(Color & 1) { ram[addr + 0x300] |= bit; }
|
||||
|
@ -148,11 +149,12 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
|
|||
}
|
||||
|
||||
void Cx4::C4DoScaleRotate(int row_padding) {
|
||||
int16 A, B, C, D;
|
||||
int16 A, B, C, D;
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
if(XScale & 0x8000)XScale = 0x7fff;
|
||||
if(YScale & 0x8000)YScale = 0x7fff;
|
||||
|
||||
|
@ -183,28 +185,29 @@ int32 YScale = readw(0x1f92);
|
|||
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
|
||||
}
|
||||
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
|
||||
//Clear the output RAM
|
||||
//Clear the output RAM
|
||||
memset(ram, 0, (w + row_padding / 4) * h / 2);
|
||||
|
||||
int32 Cx = (int16)readw(0x1f83);
|
||||
int32 Cy = (int16)readw(0x1f86);
|
||||
int32 Cx = (int16)readw(0x1f83);
|
||||
int32 Cy = (int16)readw(0x1f86);
|
||||
|
||||
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
|
||||
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
|
||||
//the function. We do Cx*A etc normally because the matrix parameters
|
||||
//already have the fractional parts.
|
||||
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
|
||||
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
|
||||
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
|
||||
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
|
||||
//the function. We do Cx*A etc normally because the matrix parameters
|
||||
//already have the fractional parts.
|
||||
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
|
||||
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
for(int32 y = 0; y < h; y++) {
|
||||
X = LineX;
|
||||
Y = LineY;
|
||||
|
@ -212,12 +215,12 @@ uint8 bit = 0x80;
|
|||
if((X >> 12) >= w || (Y >> 12) >= h) {
|
||||
byte = 0;
|
||||
} else {
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
byte = read(0x600 + (addr >> 1));
|
||||
if(addr & 1) { byte >>= 4; }
|
||||
}
|
||||
|
||||
//De-bitplanify
|
||||
//De-bitplanify
|
||||
if(byte & 1) { ram[outidx ] |= bit; }
|
||||
if(byte & 2) { ram[outidx + 1] |= bit; }
|
||||
if(byte & 4) { ram[outidx + 16] |= bit; }
|
||||
|
|
|
@ -2,17 +2,18 @@
|
|||
|
||||
//Build OAM
|
||||
void Cx4::op00_00() {
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
|
||||
//clear oam-to-be
|
||||
//clear oam-to-be
|
||||
if(i >= 0)ram[i] = 0xe0;
|
||||
}
|
||||
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
|
||||
globalx = readw(0x621);
|
||||
globaly = readw(0x623);
|
||||
oamptr2 = 0x200 + (ram[0x626] >> 2);
|
||||
|
@ -20,17 +21,18 @@ uint8 sprcount;
|
|||
if(!ram[0x620])return;
|
||||
|
||||
sprcount = 128 - ram[0x626];
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
uint32 srcptr = 0x220;
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
uint32 srcptr = 0x220;
|
||||
|
||||
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
|
||||
sprx = readw(srcptr) - globalx;
|
||||
spry = readw(srcptr + 2) - globaly;
|
||||
sprname = ram[srcptr + 5];
|
||||
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
|
||||
|
||||
uint32 spraddr = readl(srcptr + 7);
|
||||
uint32 spraddr = readl(srcptr + 7);
|
||||
if(bus.read(spraddr)) {
|
||||
int16 x, y;
|
||||
int16 x, y;
|
||||
for(int sprcnt = bus.read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
|
||||
x = (int8)bus.read(spraddr + 1);
|
||||
if(sprattr & 0x40) {
|
||||
|
@ -94,7 +96,7 @@ uint32 ptr = 0;
|
|||
C4WFZVal = readw(ptr + 9);
|
||||
C4TransfWireFrame();
|
||||
|
||||
//Displace
|
||||
//Displace
|
||||
writew(ptr + 1, C4WFXVal + 0x80);
|
||||
writew(ptr + 5, C4WFYVal + 0x50);
|
||||
}
|
||||
|
@ -107,7 +109,8 @@ uint32 ptr = 0;
|
|||
writew(0x605 + 8, 0x40);
|
||||
|
||||
ptr = 0xb02;
|
||||
uint32 ptr2 = 0;
|
||||
uint32 ptr2 = 0;
|
||||
|
||||
for(int32 i = readw(0xb00); i > 0; i--, ptr += 2, ptr2 += 8) {
|
||||
C4WFXVal = readw((read(ptr + 0) << 4) + 1);
|
||||
C4WFYVal = readw((read(ptr + 0) << 4) + 5);
|
||||
|
@ -132,13 +135,14 @@ void Cx4::op00_08() {
|
|||
|
||||
//Disintegrate
|
||||
void Cx4::op00_0b() {
|
||||
uint8 width, height;
|
||||
uint32 startx, starty;
|
||||
uint32 srcptr;
|
||||
uint32 x, y;
|
||||
int32 scalex, scaley;
|
||||
int32 cx, cy;
|
||||
int32 i, j;
|
||||
uint8 width, height;
|
||||
uint32 startx, starty;
|
||||
uint32 srcptr;
|
||||
uint32 x, y;
|
||||
int32 scalex, scaley;
|
||||
int32 cx, cy;
|
||||
int32 i, j;
|
||||
|
||||
width = read(0x1f89);
|
||||
height = read(0x1f8c);
|
||||
cx = readw(0x1f80);
|
||||
|
@ -157,9 +161,10 @@ int32 i, j;
|
|||
for(y = starty, i = 0;i < height; i++, y += scaley) {
|
||||
for(x = startx, j = 0;j < width; j++, x += scalex) {
|
||||
if((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) {
|
||||
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
|
||||
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
|
||||
uint8 mask = 0x80 >> ((x >> 8) & 7);
|
||||
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
|
||||
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
|
||||
uint8 mask = 0x80 >> ((x >> 8) & 7);
|
||||
|
||||
if(pixel & 1)ram[index ] |= mask;
|
||||
if(pixel & 2)ram[index + 1] |= mask;
|
||||
if(pixel & 4)ram[index + 16] |= mask;
|
||||
|
@ -172,16 +177,16 @@ int32 i, j;
|
|||
|
||||
//Bitplane Wave
|
||||
void Cx4::op00_0c() {
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
|
||||
for(int j = 0; j < 0x10; j++) {
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa00 + height * 2);
|
||||
|
@ -199,9 +204,9 @@ uint16 mask2 = 0x3f3f;
|
|||
destptr += 16;
|
||||
|
||||
do {
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
|
||||
for(int i = 0; i < 40; i++) {
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
uint16 temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa10 + height * 2);
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
//Sprite Functions
|
||||
void Cx4::op00() {
|
||||
switch(reg[0x4d]) {
|
||||
case 0x00:op00_00();break;
|
||||
case 0x03:op00_03();break;
|
||||
case 0x05:op00_05();break;
|
||||
case 0x07:op00_07();break;
|
||||
case 0x08:op00_08();break;
|
||||
case 0x0b:op00_0b();break;
|
||||
case 0x0c:op00_0c();break;
|
||||
case 0x00: op00_00(); break;
|
||||
case 0x03: op00_03(); break;
|
||||
case 0x05: op00_05(); break;
|
||||
case 0x07: op00_07(); break;
|
||||
case 0x08: op00_08(); break;
|
||||
case 0x0b: op00_0b(); break;
|
||||
case 0x0c: op00_0c(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ void Cx4::op01() {
|
|||
|
||||
//Propulsion
|
||||
void Cx4::op05() {
|
||||
int32 temp = 0x10000;
|
||||
int32 temp = 0x10000;
|
||||
if(readw(0x1f83)) {
|
||||
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
||||
}
|
||||
|
@ -116,12 +116,13 @@ void Cx4::op1f() {
|
|||
|
||||
//Trapezoid
|
||||
void Cx4::op22() {
|
||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||
int32 tan1 = Tan(angle1);
|
||||
int32 tan2 = Tan(angle2);
|
||||
int16 y = readw(0x1f83) - readw(0x1f89);
|
||||
int16 left, right;
|
||||
int16 angle1 = readw(0x1f8c) & 0x1ff;
|
||||
int16 angle2 = readw(0x1f8f) & 0x1ff;
|
||||
int32 tan1 = Tan(angle1);
|
||||
int32 tan2 = Tan(angle2);
|
||||
int16 y = readw(0x1f83) - readw(0x1f89);
|
||||
int16 left, right;
|
||||
|
||||
for(int32 j = 0; j < 225; j++, y++) {
|
||||
if(y >= 0) {
|
||||
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
|
||||
|
|
|
@ -7,8 +7,27 @@ DSP1 dsp1;
|
|||
|
||||
#include "dsp1emu.cpp"
|
||||
|
||||
void DSP1::init() {}
|
||||
void DSP1::enable() {}
|
||||
void DSP1::init() {
|
||||
}
|
||||
|
||||
void DSP1::enable() {
|
||||
switch(cartridge.dsp1_mapper()) {
|
||||
case Cartridge::DSP1LoROM1MB: {
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xffff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, *this);
|
||||
} break;
|
||||
|
||||
case Cartridge::DSP1LoROM2MB: {
|
||||
bus.map(Bus::MapDirect, 0x60, 0x6f, 0x0000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0xe0, 0xef, 0x0000, 0x7fff, *this);
|
||||
} break;
|
||||
|
||||
case Cartridge::DSP1HiROM: {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x1f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0x9f, 0x6000, 0x7fff, *this);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void DSP1::power() {
|
||||
reset();
|
||||
|
|
|
@ -7,8 +7,15 @@ DSP2 dsp2;
|
|||
|
||||
#include "dsp2_op.cpp"
|
||||
|
||||
void DSP2::init() {}
|
||||
void DSP2::enable() {}
|
||||
void DSP2::init() {
|
||||
}
|
||||
|
||||
void DSP2::enable() {
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xbfff, *this);
|
||||
}
|
||||
|
||||
void DSP2::power() {
|
||||
reset();
|
||||
|
|
|
@ -15,6 +15,8 @@ void DSP3::init() {
|
|||
}
|
||||
|
||||
void DSP3::enable() {
|
||||
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xffff, *this);
|
||||
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, *this);
|
||||
}
|
||||
|
||||
void DSP3::power() {
|
||||
|
|
|
@ -5,6 +5,14 @@ namespace SNES {
|
|||
|
||||
DSP4 dsp4;
|
||||
|
||||
void DSP4::init() {
|
||||
}
|
||||
|
||||
void DSP4::enable() {
|
||||
bus.map(Bus::MapDirect, 0x30, 0x3f, 0x8000, 0xffff, *this);
|
||||
bus.map(Bus::MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, *this);
|
||||
}
|
||||
|
||||
namespace DSP4i {
|
||||
inline uint16 READ_WORD(uint8 *addr) {
|
||||
return (addr[0]) + (addr[1] << 8);
|
||||
|
@ -24,12 +32,6 @@ namespace DSP4i {
|
|||
#undef bool8
|
||||
};
|
||||
|
||||
void DSP4::init() {
|
||||
}
|
||||
|
||||
void DSP4::enable() {
|
||||
}
|
||||
|
||||
void DSP4::power() {
|
||||
reset();
|
||||
}
|
||||
|
|
|
@ -5,8 +5,15 @@ namespace SNES {
|
|||
|
||||
OBC1 obc1;
|
||||
|
||||
void OBC1::init() {}
|
||||
void OBC1::enable() {}
|
||||
#include "serialization.cpp"
|
||||
|
||||
void OBC1::init() {
|
||||
}
|
||||
|
||||
void OBC1::enable() {
|
||||
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
|
||||
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
|
||||
}
|
||||
|
||||
void OBC1::power() {
|
||||
reset();
|
||||
|
|
|
@ -8,6 +8,7 @@ public:
|
|||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
OBC1();
|
||||
~OBC1();
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#ifdef OBC1_CPP
|
||||
|
||||
void OBC1::serialize(serializer &s) {
|
||||
s.integer(status.address);
|
||||
s.integer(status.baseptr);
|
||||
s.integer(status.shift);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,38 +1,62 @@
|
|||
#ifdef SA1_CPP
|
||||
|
||||
VBRBus vbrbus;
|
||||
SA1Bus sa1bus;
|
||||
|
||||
namespace memory {
|
||||
static VectorSelectionPage vectorsp;
|
||||
static StaticRAM iram(2048);
|
||||
static MappedRAM &bwram = memory::cartram;
|
||||
static CC1BWRAM cc1bwram;
|
||||
static BitmapRAM bitmapram;
|
||||
//accessed by:
|
||||
static VectorSelectionPage vectorsp; //S-CPU + SA-1
|
||||
static CPUIRAM cpuiram; //S-CPU
|
||||
static SA1IRAM sa1iram; //SA-1
|
||||
static SA1BWRAM sa1bwram; //SA-1
|
||||
static CC1BWRAM cc1bwram; //S-CPU
|
||||
static BitmapRAM bitmapram; //SA-1
|
||||
}
|
||||
|
||||
//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.
|
||||
//this is used both to avoid VBR-reads from accessing MMIO registers, and
|
||||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||
//these ports.
|
||||
//(* eg, memory::cartram is used directly, as memory::sa1bwram syncs to the S-CPU)
|
||||
void VBRBus::init() {
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cartram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cartram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cartram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
}
|
||||
|
||||
void SA1Bus::init() {
|
||||
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
|
||||
for(uint16_t i = 0x2200; i <= 0x23ff; i++) memory::mmio.map(i, sa1);
|
||||
for(unsigned i = 0x2200; i <= 0x23ff; i++) memory::mmio.map(i, sa1);
|
||||
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::sa1iram);
|
||||
map(MapDirect, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
|
||||
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::sa1iram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram);
|
||||
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bwram);
|
||||
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::sa1bwram);
|
||||
map(MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::sa1iram);
|
||||
map(MapDirect, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
|
||||
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::sa1iram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram);
|
||||
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::cpuiram);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
|
||||
bus.map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::cpuiram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram);
|
||||
bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
|
||||
bus.map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
|
||||
|
@ -54,7 +78,7 @@ void SA1Bus::init() {
|
|||
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
|
||||
//all other addresses return original mapped data.
|
||||
|
||||
uint8_t VectorSelectionPage::read(unsigned addr) {
|
||||
uint8 VectorSelectionPage::read(unsigned addr) {
|
||||
switch(0xff00 | (addr & 0xff)) {
|
||||
case 0xffea: case 0xffeb: {
|
||||
if(sa1.mmio.cpu_nvsw == true) return (sa1.mmio.snv >> ((addr & 1) << 3));
|
||||
|
@ -68,7 +92,7 @@ uint8_t VectorSelectionPage::read(unsigned addr) {
|
|||
return access->read(addr);
|
||||
}
|
||||
|
||||
void VectorSelectionPage::write(unsigned addr, uint8_t data) {
|
||||
void VectorSelectionPage::write(unsigned addr, uint8 data) {
|
||||
return access->write(addr, data);
|
||||
}
|
||||
|
||||
|
@ -85,6 +109,60 @@ void VectorSelectionPage::sync() {
|
|||
}
|
||||
}
|
||||
|
||||
//=======
|
||||
//SA1IRAM
|
||||
//=======
|
||||
|
||||
unsigned SA1IRAM::size() const {
|
||||
return memory::iram.size();
|
||||
}
|
||||
|
||||
uint8 SA1IRAM::read(unsigned addr) {
|
||||
scheduler.sync_copcpu();
|
||||
return memory::iram.read(addr);
|
||||
}
|
||||
|
||||
void SA1IRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_copcpu();
|
||||
memory::iram.write(addr, data);
|
||||
}
|
||||
|
||||
//=======
|
||||
//CPUIRAM
|
||||
//=======
|
||||
|
||||
unsigned CPUIRAM::size() const {
|
||||
return memory::iram.size();
|
||||
}
|
||||
|
||||
uint8 CPUIRAM::read(unsigned addr) {
|
||||
scheduler.sync_cpucop();
|
||||
return memory::iram.read(addr);
|
||||
}
|
||||
|
||||
void CPUIRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_cpucop();
|
||||
memory::iram.write(addr, data);
|
||||
}
|
||||
|
||||
//========
|
||||
//SA1BWRAM
|
||||
//========
|
||||
|
||||
unsigned SA1BWRAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8 SA1BWRAM::read(unsigned addr) {
|
||||
scheduler.sync_copcpu();
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SA1BWRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_copcpu();
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
//========
|
||||
//CC1BWRAM
|
||||
//========
|
||||
|
@ -93,12 +171,14 @@ unsigned CC1BWRAM::size() const {
|
|||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t CC1BWRAM::read(unsigned addr) {
|
||||
uint8 CC1BWRAM::read(unsigned addr) {
|
||||
scheduler.sync_cpucop();
|
||||
if(dma) return sa1.dma_cc1_read(addr);
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void CC1BWRAM::write(unsigned addr, uint8_t data) {
|
||||
void CC1BWRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_cpucop();
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
|
@ -110,7 +190,9 @@ unsigned BitmapRAM::size() const {
|
|||
return 0x100000;
|
||||
}
|
||||
|
||||
uint8_t BitmapRAM::read(unsigned addr) {
|
||||
uint8 BitmapRAM::read(unsigned addr) {
|
||||
scheduler.sync_copcpu();
|
||||
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
unsigned shift = addr & 1;
|
||||
|
@ -132,10 +214,12 @@ uint8_t BitmapRAM::read(unsigned addr) {
|
|||
}
|
||||
}
|
||||
|
||||
void BitmapRAM::write(unsigned addr, uint8_t data) {
|
||||
void BitmapRAM::write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_copcpu();
|
||||
|
||||
if(sa1.mmio.bbf == 0) {
|
||||
//4bpp
|
||||
uint8_t shift = addr & 1;
|
||||
unsigned shift = addr & 1;
|
||||
addr = (addr >> 1) & (memory::cartram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (memory::cartram.read(addr) & 0xf0) | ((data & 15) << 0); break;
|
||||
|
@ -143,7 +227,7 @@ void BitmapRAM::write(unsigned addr, uint8_t data) {
|
|||
}
|
||||
} else {
|
||||
//2bpp
|
||||
uint8_t shift = addr & 3;
|
||||
unsigned shift = addr & 3;
|
||||
addr = (addr >> 2) & (memory::cartram.size() - 1);
|
||||
switch(shift) { default:
|
||||
case 0: data = (memory::cartram.read(addr) & 0xfc) | ((data & 3) << 0); break;
|
||||
|
|
|
@ -1,23 +1,45 @@
|
|||
struct VBRBus : Bus {
|
||||
void init();
|
||||
};
|
||||
|
||||
struct SA1Bus : Bus {
|
||||
void init();
|
||||
};
|
||||
|
||||
struct VectorSelectionPage : Memory {
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
void sync();
|
||||
Memory *access;
|
||||
};
|
||||
|
||||
struct CPUIRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SA1IRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SA1BWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct CC1BWRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
bool dma;
|
||||
};
|
||||
|
||||
struct BitmapRAM : Memory {
|
||||
unsigned size() const;
|
||||
alwaysinline uint8_t read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8_t);
|
||||
alwaysinline uint8 read(unsigned);
|
||||
alwaysinline void write(unsigned, uint8);
|
||||
};
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
void SA1::dma_normal() {
|
||||
while(mmio.dtc--) {
|
||||
uint8_t data = regs.mdr;
|
||||
uint32_t dsa = mmio.dsa++;
|
||||
uint32_t dda = mmio.dda++;
|
||||
uint8 data = regs.mdr;
|
||||
uint32 dsa = mmio.dsa++;
|
||||
uint32 dda = mmio.dda++;
|
||||
|
||||
//source and destination cannot be the same
|
||||
if(mmio.sd == DMA::SourceBWRAM && mmio.dd == DMA::DestBWRAM) continue;
|
||||
|
@ -67,7 +67,7 @@ void SA1::dma_cc1() {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t SA1::dma_cc1_read(unsigned addr) {
|
||||
uint8 SA1::dma_cc1_read(unsigned addr) {
|
||||
//16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp)
|
||||
unsigned charmask = (1 << (6 - mmio.dmacb)) - 1;
|
||||
|
||||
|
@ -75,20 +75,20 @@ uint8_t SA1::dma_cc1_read(unsigned addr) {
|
|||
//buffer next character to I-RAM
|
||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
||||
unsigned bpl = (8 << mmio.dmasize) >> mmio.dmacb;
|
||||
unsigned bwmask = memory::bwram.size() - 1;
|
||||
unsigned bwmask = memory::cartram.size() - 1;
|
||||
unsigned tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb);
|
||||
unsigned ty = (tile >> mmio.dmasize);
|
||||
unsigned tx = tile & ((1 << mmio.dmasize) - 1);
|
||||
unsigned bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp;
|
||||
|
||||
for(unsigned y = 0; y < 8; y++) {
|
||||
uint64_t data = 0;
|
||||
uint64 data = 0;
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
data |= (uint64_t)memory::bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
||||
data |= (uint64)memory::cartram.read((bwaddr + byte) & bwmask) << (byte << 3);
|
||||
}
|
||||
bwaddr += bpl;
|
||||
|
||||
uint8_t 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++) {
|
||||
out[0] |= (data & 1) << (7 - x); data >>= 1;
|
||||
out[1] |= (data & 1) << (7 - x); data >>= 1;
|
||||
|
@ -118,7 +118,7 @@ uint8_t SA1::dma_cc1_read(unsigned addr) {
|
|||
|
||||
void SA1::dma_cc2() {
|
||||
//select register file index (0-7 or 8-15)
|
||||
const uint8_t *brf = &mmio.brf[(dma.line & 1) << 3];
|
||||
const uint8 *brf = &mmio.brf[(dma.line & 1) << 3];
|
||||
unsigned bpp = 2 << (2 - mmio.dmacb);
|
||||
unsigned addr = mmio.dda & 0x07ff;
|
||||
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
|
||||
|
@ -126,7 +126,7 @@ void SA1::dma_cc2() {
|
|||
addr += (dma.line & 7) * 2;
|
||||
|
||||
for(unsigned byte = 0; byte < bpp; byte++) {
|
||||
uint8_t output = 0;
|
||||
uint8 output = 0;
|
||||
for(unsigned bit = 0; bit < 8; bit++) {
|
||||
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ struct DMA {
|
|||
|
||||
void dma_normal();
|
||||
void dma_cc1();
|
||||
uint8_t dma_cc1_read(unsigned addr);
|
||||
uint8 dma_cc1_read(unsigned addr);
|
||||
void dma_cc2();
|
||||
|
|
|
@ -1,39 +1,24 @@
|
|||
#ifdef SA1_CPP
|
||||
|
||||
//==========================
|
||||
//SA-1 opcode core functions
|
||||
//==========================
|
||||
|
||||
void SA1::op_io() {
|
||||
tick();
|
||||
if(regs.wai) scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
|
||||
//BW-RAM is accessed at ~5.37MHz (4 clock ticks)
|
||||
//tick() == 2 clock ticks
|
||||
//note: bus conflict delays are not emulated at this time
|
||||
|
||||
#define is_bwram(addr) (\
|
||||
((addr & 0x40e000) == 0x006000) \
|
||||
|| ((addr & 0xf00000) == 0x400000) \
|
||||
|| ((addr & 0xf00000) == 0x600000) \
|
||||
)
|
||||
|
||||
uint8_t SA1::op_read(unsigned addr) {
|
||||
void SA1::op_io() {
|
||||
tick();
|
||||
if(is_bwram(addr)) tick();
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
uint8 SA1::op_read(unsigned addr) {
|
||||
tick();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
return sa1bus.read(addr);
|
||||
}
|
||||
|
||||
void SA1::op_write(unsigned addr, uint8_t data) {
|
||||
void SA1::op_write(unsigned addr, uint8 data) {
|
||||
tick();
|
||||
if(is_bwram(addr)) tick();
|
||||
scheduler.sync_copcpu();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
sa1bus.write(addr, data);
|
||||
}
|
||||
|
||||
#undef is_bwram
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
alwaysinline void op_io();
|
||||
alwaysinline uint8_t op_read(unsigned addr);
|
||||
alwaysinline void op_write(unsigned addr, uint8_t data);
|
||||
alwaysinline unsigned bus_speed(unsigned addr);
|
||||
alwaysinline uint8 op_read(unsigned addr);
|
||||
alwaysinline void op_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8_t vbr_read(unsigned addr);
|
||||
|
|
|
@ -9,7 +9,7 @@ Memory& SA1::mmio_access(unsigned &addr) {
|
|||
}
|
||||
|
||||
//(CCNT) SA-1 control
|
||||
void SA1::mmio_w2200(uint8_t data) {
|
||||
void SA1::mmio_w2200(uint8 data) {
|
||||
if(mmio.sa1_resb && !(data & 0x80)) {
|
||||
//reset SA-1 CPU
|
||||
regs.pc.w = mmio.crv;
|
||||
|
@ -34,7 +34,7 @@ void SA1::mmio_w2200(uint8_t data) {
|
|||
}
|
||||
|
||||
//(SIE) S-CPU interrupt enable
|
||||
void SA1::mmio_w2201(uint8_t data) {
|
||||
void SA1::mmio_w2201(uint8 data) {
|
||||
if(!mmio.cpu_irqen && (data & 0x80)) {
|
||||
if(mmio.cpu_irqfl) {
|
||||
mmio.cpu_irqcl = 0;
|
||||
|
@ -54,7 +54,7 @@ void SA1::mmio_w2201(uint8_t data) {
|
|||
}
|
||||
|
||||
//(SIC) S-CPU interrupt clear
|
||||
void SA1::mmio_w2202(uint8_t data) {
|
||||
void SA1::mmio_w2202(uint8 data) {
|
||||
mmio.cpu_irqcl = (data & 0x80);
|
||||
mmio.chdma_irqcl = (data & 0x20);
|
||||
|
||||
|
@ -65,19 +65,19 @@ void SA1::mmio_w2202(uint8_t data) {
|
|||
}
|
||||
|
||||
//(CRV) SA-1 reset vector
|
||||
void SA1::mmio_w2203(uint8_t data) { mmio.crv = (mmio.crv & 0xff00) | data; }
|
||||
void SA1::mmio_w2204(uint8_t data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
|
||||
void SA1::mmio_w2203(uint8 data) { mmio.crv = (mmio.crv & 0xff00) | data; }
|
||||
void SA1::mmio_w2204(uint8 data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
|
||||
|
||||
//(CNV) SA-1 NMI vector
|
||||
void SA1::mmio_w2205(uint8_t data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
|
||||
void SA1::mmio_w2206(uint8_t data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
|
||||
void SA1::mmio_w2205(uint8 data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
|
||||
void SA1::mmio_w2206(uint8 data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
|
||||
|
||||
//(CIV) SA-1 IRQ vector
|
||||
void SA1::mmio_w2207(uint8_t data) { mmio.civ = (mmio.civ & 0xff00) | data; }
|
||||
void SA1::mmio_w2208(uint8_t data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
|
||||
void SA1::mmio_w2207(uint8 data) { mmio.civ = (mmio.civ & 0xff00) | data; }
|
||||
void SA1::mmio_w2208(uint8 data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
|
||||
|
||||
//(SCNT) S-CPU control
|
||||
void SA1::mmio_w2209(uint8_t data) {
|
||||
void SA1::mmio_w2209(uint8 data) {
|
||||
mmio.cpu_irq = (data & 0x80);
|
||||
mmio.cpu_ivsw = (data & 0x40);
|
||||
mmio.cpu_nvsw = (data & 0x10);
|
||||
|
@ -93,7 +93,7 @@ void SA1::mmio_w2209(uint8_t data) {
|
|||
}
|
||||
|
||||
//(CIE) SA-1 interrupt enable
|
||||
void SA1::mmio_w220a(uint8_t data) {
|
||||
void SA1::mmio_w220a(uint8 data) {
|
||||
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.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;
|
||||
|
@ -106,7 +106,7 @@ void SA1::mmio_w220a(uint8_t data) {
|
|||
}
|
||||
|
||||
//(CIC) SA-1 interrupt clear
|
||||
void SA1::mmio_w220b(uint8_t data) {
|
||||
void SA1::mmio_w220b(uint8 data) {
|
||||
mmio.sa1_irqcl = (data & 0x80);
|
||||
mmio.timer_irqcl = (data & 0x40);
|
||||
mmio.dma_irqcl = (data & 0x20);
|
||||
|
@ -119,36 +119,36 @@ void SA1::mmio_w220b(uint8_t data) {
|
|||
}
|
||||
|
||||
//(SNV) S-CPU NMI vector
|
||||
void SA1::mmio_w220c(uint8_t data) { mmio.snv = (mmio.snv & 0xff00) | data; }
|
||||
void SA1::mmio_w220d(uint8_t data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
|
||||
void SA1::mmio_w220c(uint8 data) { mmio.snv = (mmio.snv & 0xff00) | data; }
|
||||
void SA1::mmio_w220d(uint8 data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
|
||||
|
||||
//(SIV) S-CPU IRQ vector
|
||||
void SA1::mmio_w220e(uint8_t data) { mmio.siv = (mmio.siv & 0xff00) | data; }
|
||||
void SA1::mmio_w220f(uint8_t data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
|
||||
void SA1::mmio_w220e(uint8 data) { mmio.siv = (mmio.siv & 0xff00) | data; }
|
||||
void SA1::mmio_w220f(uint8 data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
|
||||
|
||||
//(TMC) H/V timer control
|
||||
void SA1::mmio_w2210(uint8_t data) {
|
||||
void SA1::mmio_w2210(uint8 data) {
|
||||
mmio.hvselb = (data & 0x80);
|
||||
mmio.ven = (data & 0x02);
|
||||
mmio.hen = (data & 0x01);
|
||||
}
|
||||
|
||||
//(CTR) SA-1 timer restart
|
||||
void SA1::mmio_w2211(uint8_t data) {
|
||||
void SA1::mmio_w2211(uint8 data) {
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
}
|
||||
|
||||
//(HCNT) H-count
|
||||
void SA1::mmio_w2212(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2213(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
|
||||
void SA1::mmio_w2212(uint8 data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2213(uint8 data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
|
||||
|
||||
//(VCNT) V-count
|
||||
void SA1::mmio_w2214(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2215(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
|
||||
void SA1::mmio_w2214(uint8 data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2215(uint8 data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
|
||||
|
||||
//(CXB) Super MMC bank C
|
||||
void SA1::mmio_w2220(uint8_t data) {
|
||||
void SA1::mmio_w2220(uint8 data) {
|
||||
mmio.cbmode = (data & 0x80);
|
||||
mmio.cb = (data & 0x07);
|
||||
|
||||
|
@ -170,7 +170,7 @@ void SA1::mmio_w2220(uint8_t data) {
|
|||
}
|
||||
|
||||
//(DXB) Super MMC bank D
|
||||
void SA1::mmio_w2221(uint8_t data) {
|
||||
void SA1::mmio_w2221(uint8 data) {
|
||||
mmio.dbmode = (data & 0x80);
|
||||
mmio.db = (data & 0x07);
|
||||
|
||||
|
@ -190,7 +190,7 @@ void SA1::mmio_w2221(uint8_t data) {
|
|||
}
|
||||
|
||||
//(EXB) Super MMC bank E
|
||||
void SA1::mmio_w2222(uint8_t data) {
|
||||
void SA1::mmio_w2222(uint8 data) {
|
||||
mmio.ebmode = (data & 0x80);
|
||||
mmio.eb = (data & 0x07);
|
||||
|
||||
|
@ -210,7 +210,7 @@ void SA1::mmio_w2222(uint8_t data) {
|
|||
}
|
||||
|
||||
//(FXB) Super MMC bank F
|
||||
void SA1::mmio_w2223(uint8_t data) {
|
||||
void SA1::mmio_w2223(uint8 data) {
|
||||
mmio.fbmode = (data & 0x80);
|
||||
mmio.fb = (data & 0x07);
|
||||
|
||||
|
@ -230,7 +230,7 @@ void SA1::mmio_w2223(uint8_t data) {
|
|||
}
|
||||
|
||||
//(BMAPS) S-CPU BW-RAM address mapping
|
||||
void SA1::mmio_w2224(uint8_t data) {
|
||||
void SA1::mmio_w2224(uint8 data) {
|
||||
mmio.sbm = (data & 0x1f);
|
||||
|
||||
bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
|
||||
|
@ -238,14 +238,14 @@ void SA1::mmio_w2224(uint8_t data) {
|
|||
}
|
||||
|
||||
//(BMAP) SA-1 BW-RAM address mapping
|
||||
void SA1::mmio_w2225(uint8_t data) {
|
||||
void SA1::mmio_w2225(uint8 data) {
|
||||
mmio.sw46 = (data & 0x80);
|
||||
mmio.cbm = (data & 0x7f);
|
||||
|
||||
if(mmio.sw46 == 0) {
|
||||
//$[40-43]:[0000-ffff] x 32 projection
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
|
||||
} else {
|
||||
//$[60-6f]:[0000-ffff] x 128 projection
|
||||
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
|
||||
|
@ -254,32 +254,32 @@ void SA1::mmio_w2225(uint8_t data) {
|
|||
}
|
||||
|
||||
//(SWBE) S-CPU BW-RAM write enable
|
||||
void SA1::mmio_w2226(uint8_t data) {
|
||||
void SA1::mmio_w2226(uint8 data) {
|
||||
mmio.swen = (data & 0x80);
|
||||
}
|
||||
|
||||
//(CWBE) SA-1 BW-RAM write enable
|
||||
void SA1::mmio_w2227(uint8_t data) {
|
||||
void SA1::mmio_w2227(uint8 data) {
|
||||
mmio.cwen = (data & 0x80);
|
||||
}
|
||||
|
||||
//(BWPA) BW-RAM write-protected area
|
||||
void SA1::mmio_w2228(uint8_t data) {
|
||||
void SA1::mmio_w2228(uint8 data) {
|
||||
mmio.bwp = (data & 0x0f);
|
||||
}
|
||||
|
||||
//(SIWP) S-CPU I-RAM write protection
|
||||
void SA1::mmio_w2229(uint8_t data) {
|
||||
void SA1::mmio_w2229(uint8 data) {
|
||||
mmio.siwp = data;
|
||||
}
|
||||
|
||||
//(CIWP) SA-1 I-RAM write protection
|
||||
void SA1::mmio_w222a(uint8_t data) {
|
||||
void SA1::mmio_w222a(uint8 data) {
|
||||
mmio.ciwp = data;
|
||||
}
|
||||
|
||||
//(DCNT) DMA control
|
||||
void SA1::mmio_w2230(uint8_t data) {
|
||||
void SA1::mmio_w2230(uint8 data) {
|
||||
mmio.dmaen = (data & 0x80);
|
||||
mmio.dprio = (data & 0x40);
|
||||
mmio.cden = (data & 0x20);
|
||||
|
@ -291,7 +291,7 @@ void SA1::mmio_w2230(uint8_t data) {
|
|||
}
|
||||
|
||||
//(CDMA) character conversion DMA parameters
|
||||
void SA1::mmio_w2231(uint8_t data) {
|
||||
void SA1::mmio_w2231(uint8 data) {
|
||||
mmio.chdend = (data & 0x80);
|
||||
mmio.dmasize = (data >> 2) & 7;
|
||||
mmio.dmacb = (data & 0x03);
|
||||
|
@ -302,16 +302,16 @@ void SA1::mmio_w2231(uint8_t data) {
|
|||
}
|
||||
|
||||
//(SDA) DMA source device start address
|
||||
void SA1::mmio_w2232(uint8_t data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w2233(uint8_t data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w2234(uint8_t data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
|
||||
void SA1::mmio_w2232(uint8 data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w2233(uint8 data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w2234(uint8 data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
|
||||
|
||||
//(DDA) DMA destination start address
|
||||
void SA1::mmio_w2235(uint8_t data) {
|
||||
void SA1::mmio_w2235(uint8 data) {
|
||||
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
|
||||
}
|
||||
|
||||
void SA1::mmio_w2236(uint8_t data) {
|
||||
void SA1::mmio_w2236(uint8 data) {
|
||||
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
|
||||
|
||||
if(mmio.dmaen == true) {
|
||||
|
@ -323,7 +323,7 @@ void SA1::mmio_w2236(uint8_t data) {
|
|||
}
|
||||
}
|
||||
|
||||
void SA1::mmio_w2237(uint8_t data) {
|
||||
void SA1::mmio_w2237(uint8 data) {
|
||||
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
|
||||
|
||||
if(mmio.dmaen == true) {
|
||||
|
@ -334,23 +334,23 @@ void SA1::mmio_w2237(uint8_t data) {
|
|||
}
|
||||
|
||||
//(DTC) DMA terminal counter
|
||||
void SA1::mmio_w2238(uint8_t data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2239(uint8_t data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
|
||||
void SA1::mmio_w2238(uint8 data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
|
||||
void SA1::mmio_w2239(uint8 data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
|
||||
|
||||
//(BBF) BW-RAM bitmap format
|
||||
void SA1::mmio_w223f(uint8_t data) {
|
||||
void SA1::mmio_w223f(uint8 data) {
|
||||
mmio.bbf = (data & 0x80);
|
||||
}
|
||||
|
||||
//(BRF) bitmap register files
|
||||
void SA1::mmio_w2240(uint8_t data) { mmio.brf[ 0] = data; }
|
||||
void SA1::mmio_w2241(uint8_t data) { mmio.brf[ 1] = data; }
|
||||
void SA1::mmio_w2242(uint8_t data) { mmio.brf[ 2] = data; }
|
||||
void SA1::mmio_w2243(uint8_t data) { mmio.brf[ 3] = data; }
|
||||
void SA1::mmio_w2244(uint8_t data) { mmio.brf[ 4] = data; }
|
||||
void SA1::mmio_w2245(uint8_t data) { mmio.brf[ 5] = data; }
|
||||
void SA1::mmio_w2246(uint8_t data) { mmio.brf[ 6] = data; }
|
||||
void SA1::mmio_w2247(uint8_t data) { mmio.brf[ 7] = data;
|
||||
void SA1::mmio_w2240(uint8 data) { mmio.brf[ 0] = data; }
|
||||
void SA1::mmio_w2241(uint8 data) { mmio.brf[ 1] = data; }
|
||||
void SA1::mmio_w2242(uint8 data) { mmio.brf[ 2] = data; }
|
||||
void SA1::mmio_w2243(uint8 data) { mmio.brf[ 3] = data; }
|
||||
void SA1::mmio_w2244(uint8 data) { mmio.brf[ 4] = data; }
|
||||
void SA1::mmio_w2245(uint8 data) { mmio.brf[ 5] = data; }
|
||||
void SA1::mmio_w2246(uint8 data) { mmio.brf[ 6] = data; }
|
||||
void SA1::mmio_w2247(uint8 data) { mmio.brf[ 7] = data;
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||
dma_cc2();
|
||||
|
@ -358,14 +358,14 @@ void SA1::mmio_w2247(uint8_t data) { mmio.brf[ 7] = data;
|
|||
}
|
||||
}
|
||||
|
||||
void SA1::mmio_w2248(uint8_t data) { mmio.brf[ 8] = data; }
|
||||
void SA1::mmio_w2249(uint8_t data) { mmio.brf[ 9] = data; }
|
||||
void SA1::mmio_w224a(uint8_t data) { mmio.brf[10] = data; }
|
||||
void SA1::mmio_w224b(uint8_t data) { mmio.brf[11] = data; }
|
||||
void SA1::mmio_w224c(uint8_t data) { mmio.brf[12] = data; }
|
||||
void SA1::mmio_w224d(uint8_t data) { mmio.brf[13] = data; }
|
||||
void SA1::mmio_w224e(uint8_t data) { mmio.brf[14] = data; }
|
||||
void SA1::mmio_w224f(uint8_t data) { mmio.brf[15] = data;
|
||||
void SA1::mmio_w2248(uint8 data) { mmio.brf[ 8] = data; }
|
||||
void SA1::mmio_w2249(uint8 data) { mmio.brf[ 9] = data; }
|
||||
void SA1::mmio_w224a(uint8 data) { mmio.brf[10] = data; }
|
||||
void SA1::mmio_w224b(uint8 data) { mmio.brf[11] = data; }
|
||||
void SA1::mmio_w224c(uint8 data) { mmio.brf[12] = data; }
|
||||
void SA1::mmio_w224d(uint8 data) { mmio.brf[13] = data; }
|
||||
void SA1::mmio_w224e(uint8 data) { mmio.brf[14] = data; }
|
||||
void SA1::mmio_w224f(uint8 data) { mmio.brf[15] = data;
|
||||
if(mmio.dmaen == true) {
|
||||
if(mmio.cden == 1 && mmio.cdsel == 0) {
|
||||
dma_cc2();
|
||||
|
@ -374,7 +374,7 @@ void SA1::mmio_w224f(uint8_t data) { mmio.brf[15] = data;
|
|||
}
|
||||
|
||||
//(MCNT) arithmetic control
|
||||
void SA1::mmio_w2250(uint8_t data) {
|
||||
void SA1::mmio_w2250(uint8 data) {
|
||||
mmio.acm = (data & 0x02);
|
||||
mmio.md = (data & 0x01);
|
||||
|
||||
|
@ -382,38 +382,38 @@ void SA1::mmio_w2250(uint8_t data) {
|
|||
}
|
||||
|
||||
//(MAL) multiplicand / dividend low
|
||||
void SA1::mmio_w2251(uint8_t data) {
|
||||
void SA1::mmio_w2251(uint8 data) {
|
||||
mmio.ma = (mmio.ma & 0xff00) | data;
|
||||
}
|
||||
|
||||
//(MAH) multiplicand / dividend high
|
||||
void SA1::mmio_w2252(uint8_t data) {
|
||||
void SA1::mmio_w2252(uint8 data) {
|
||||
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
|
||||
}
|
||||
|
||||
//(MBL) multiplier / divisor low
|
||||
void SA1::mmio_w2253(uint8_t data) {
|
||||
void SA1::mmio_w2253(uint8 data) {
|
||||
mmio.mb = (mmio.mb & 0xff00) | data;
|
||||
}
|
||||
|
||||
//(MBH) multiplier / divisor high
|
||||
//multiplication / cumulative sum only resets MB
|
||||
//division resets both MA and MB
|
||||
void SA1::mmio_w2254(uint8_t data) {
|
||||
void SA1::mmio_w2254(uint8 data) {
|
||||
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
|
||||
|
||||
if(mmio.acm == 0) {
|
||||
if(mmio.md == 0) {
|
||||
//signed multiplication
|
||||
mmio.mr = (int16_t)mmio.ma * (int16_t)mmio.mb;
|
||||
mmio.mr = (int16)mmio.ma * (int16)mmio.mb;
|
||||
mmio.mb = 0;
|
||||
} else {
|
||||
//unsigned division
|
||||
if(mmio.mb == 0) {
|
||||
mmio.mr = 0;
|
||||
} else {
|
||||
int16_t quotient = (int16_t)mmio.ma / (uint16_t)mmio.mb;
|
||||
uint16_t remainder = (int16_t)mmio.ma % (uint16_t)mmio.mb;
|
||||
int16 quotient = (int16)mmio.ma / (uint16)mmio.mb;
|
||||
uint16 remainder = (int16)mmio.ma % (uint16)mmio.mb;
|
||||
mmio.mr = (remainder << 16) | quotient;
|
||||
}
|
||||
mmio.ma = 0;
|
||||
|
@ -421,7 +421,7 @@ void SA1::mmio_w2254(uint8_t data) {
|
|||
}
|
||||
} else {
|
||||
//sigma (accumulative multiplication)
|
||||
mmio.mr += (int16_t)mmio.ma * (int16_t)mmio.mb;
|
||||
mmio.mr += (int16)mmio.ma * (int16)mmio.mb;
|
||||
mmio.overflow = (mmio.mr >= (1ULL << 40));
|
||||
mmio.mr &= (1ULL << 40) - 1;
|
||||
mmio.mb = 0;
|
||||
|
@ -429,7 +429,7 @@ void SA1::mmio_w2254(uint8_t data) {
|
|||
}
|
||||
|
||||
//(VBD) variable-length bit processing
|
||||
void SA1::mmio_w2258(uint8_t data) {
|
||||
void SA1::mmio_w2258(uint8 data) {
|
||||
mmio.hl = (data & 0x80);
|
||||
mmio.vb = (data & 0x0f);
|
||||
if(mmio.vb == 0) mmio.vb = 16;
|
||||
|
@ -443,13 +443,13 @@ void SA1::mmio_w2258(uint8_t data) {
|
|||
}
|
||||
|
||||
//(VDA) variable-length bit game pak ROM start address
|
||||
void SA1::mmio_w2259(uint8_t data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w225a(uint8_t data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w225b(uint8_t data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
|
||||
void SA1::mmio_w2259(uint8 data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
|
||||
void SA1::mmio_w225a(uint8 data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
|
||||
void SA1::mmio_w225b(uint8 data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
|
||||
|
||||
//(SFR) S-CPU flag read
|
||||
uint8_t SA1::mmio_r2300() {
|
||||
uint8_t data;
|
||||
uint8 SA1::mmio_r2300() {
|
||||
uint8 data;
|
||||
data = mmio.cpu_irqfl << 7;
|
||||
data |= mmio.cpu_ivsw << 6;
|
||||
data |= mmio.chdma_irqfl << 5;
|
||||
|
@ -459,8 +459,8 @@ uint8_t SA1::mmio_r2300() {
|
|||
}
|
||||
|
||||
//(CFR) SA-1 flag read
|
||||
uint8_t SA1::mmio_r2301() {
|
||||
uint8_t data;
|
||||
uint8 SA1::mmio_r2301() {
|
||||
uint8 data;
|
||||
data = mmio.sa1_irqfl << 7;
|
||||
data |= mmio.timer_irqfl << 6;
|
||||
data |= mmio.dma_irqfl << 5;
|
||||
|
@ -470,41 +470,41 @@ uint8_t SA1::mmio_r2301() {
|
|||
}
|
||||
|
||||
//(HCR) hcounter read
|
||||
uint8_t SA1::mmio_r2302() {
|
||||
uint8 SA1::mmio_r2302() {
|
||||
//latch counters
|
||||
mmio.hcr = status.hcounter >> 2;
|
||||
mmio.vcr = status.vcounter;
|
||||
return mmio.hcr >> 0; }
|
||||
uint8_t SA1::mmio_r2303() { return mmio.hcr >> 8; }
|
||||
uint8 SA1::mmio_r2303() { return mmio.hcr >> 8; }
|
||||
|
||||
//(VCR) vcounter read
|
||||
uint8_t SA1::mmio_r2304() { return mmio.vcr >> 0; }
|
||||
uint8_t SA1::mmio_r2305() { return mmio.vcr >> 8; }
|
||||
uint8 SA1::mmio_r2304() { return mmio.vcr >> 0; }
|
||||
uint8 SA1::mmio_r2305() { return mmio.vcr >> 8; }
|
||||
|
||||
//(MR) arithmetic result
|
||||
uint8_t SA1::mmio_r2306() { return mmio.mr >> 0; }
|
||||
uint8_t SA1::mmio_r2307() { return mmio.mr >> 8; }
|
||||
uint8_t SA1::mmio_r2308() { return mmio.mr >> 16; }
|
||||
uint8_t SA1::mmio_r2309() { return mmio.mr >> 24; }
|
||||
uint8_t SA1::mmio_r230a() { return mmio.mr >> 32; }
|
||||
uint8 SA1::mmio_r2306() { return mmio.mr >> 0; }
|
||||
uint8 SA1::mmio_r2307() { return mmio.mr >> 8; }
|
||||
uint8 SA1::mmio_r2308() { return mmio.mr >> 16; }
|
||||
uint8 SA1::mmio_r2309() { return mmio.mr >> 24; }
|
||||
uint8 SA1::mmio_r230a() { return mmio.mr >> 32; }
|
||||
|
||||
//(OF) arithmetic overflow flag
|
||||
uint8_t SA1::mmio_r230b() { return mmio.overflow << 7; }
|
||||
uint8 SA1::mmio_r230b() { return mmio.overflow << 7; }
|
||||
|
||||
//(VDPL) variable-length data read port low
|
||||
uint8_t SA1::mmio_r230c() {
|
||||
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
|
||||
| (sa1bus.read(mmio.va + 1) << 8)
|
||||
| (sa1bus.read(mmio.va + 2) << 16);
|
||||
uint8 SA1::mmio_r230c() {
|
||||
uint32 data = (vbrbus.read(mmio.va + 0) << 0)
|
||||
| (vbrbus.read(mmio.va + 1) << 8)
|
||||
| (vbrbus.read(mmio.va + 2) << 16);
|
||||
data >>= mmio.vbit;
|
||||
return data >> 0;
|
||||
}
|
||||
|
||||
//(VDPH) variable-length data read port high
|
||||
uint8_t SA1::mmio_r230d() {
|
||||
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
|
||||
| (sa1bus.read(mmio.va + 1) << 8)
|
||||
| (sa1bus.read(mmio.va + 2) << 16);
|
||||
uint8 SA1::mmio_r230d() {
|
||||
uint32 data = (vbrbus.read(mmio.va + 0) << 0)
|
||||
| (vbrbus.read(mmio.va + 1) << 8)
|
||||
| (vbrbus.read(mmio.va + 2) << 16);
|
||||
data >>= mmio.vbit;
|
||||
|
||||
if(mmio.hl == 1) {
|
||||
|
@ -518,11 +518,12 @@ uint8_t SA1::mmio_r230d() {
|
|||
}
|
||||
|
||||
//(VC) version code register
|
||||
uint8_t SA1::mmio_r230e() {
|
||||
uint8 SA1::mmio_r230e() {
|
||||
return 0x01; //true value unknown
|
||||
}
|
||||
|
||||
uint8_t SA1::mmio_read(unsigned addr) {
|
||||
uint8 SA1::mmio_read(unsigned addr) {
|
||||
(co_active() == scheduler.thread_cpu ? scheduler.sync_cpucop() : scheduler.sync_copcpu());
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
|
@ -546,7 +547,8 @@ uint8_t SA1::mmio_read(unsigned addr) {
|
|||
return 0x00;
|
||||
}
|
||||
|
||||
void SA1::mmio_write(unsigned addr, uint8_t data) {
|
||||
void SA1::mmio_write(unsigned addr, uint8 data) {
|
||||
(co_active() == scheduler.thread_cpu ? scheduler.sync_cpucop() : scheduler.sync_copcpu());
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
uint8_t mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8_t data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
Memory& mmio_access(unsigned &addr);
|
||||
|
||||
struct MMIO {
|
||||
|
@ -8,7 +8,7 @@ struct MMIO {
|
|||
bool sa1_rdyb;
|
||||
bool sa1_resb;
|
||||
bool sa1_nmi;
|
||||
uint8_t smeg;
|
||||
uint8 smeg;
|
||||
|
||||
//$2201 SIE
|
||||
bool cpu_irqen;
|
||||
|
@ -19,19 +19,19 @@ struct MMIO {
|
|||
bool chdma_irqcl;
|
||||
|
||||
//$2203,$2204 CRV
|
||||
uint16_t crv;
|
||||
uint16 crv;
|
||||
|
||||
//$2205,$2206 CNV
|
||||
uint16_t cnv;
|
||||
uint16 cnv;
|
||||
|
||||
//$2207,$2208 CIV
|
||||
uint16_t civ;
|
||||
uint16 civ;
|
||||
|
||||
//$2209 SCNT
|
||||
bool cpu_irq;
|
||||
bool cpu_ivsw;
|
||||
bool cpu_nvsw;
|
||||
uint8_t cmeg;
|
||||
uint8 cmeg;
|
||||
|
||||
//$220a CIE
|
||||
bool sa1_irqen;
|
||||
|
@ -46,10 +46,10 @@ struct MMIO {
|
|||
bool sa1_nmicl;
|
||||
|
||||
//$220c,$220d SNV
|
||||
uint16_t snv;
|
||||
uint16 snv;
|
||||
|
||||
//$220e,$220f SIV
|
||||
uint16_t siv;
|
||||
uint16 siv;
|
||||
|
||||
//$2210 TMC
|
||||
bool hvselb;
|
||||
|
@ -57,33 +57,33 @@ struct MMIO {
|
|||
bool hen;
|
||||
|
||||
//$2212,$2213
|
||||
uint16_t hcnt;
|
||||
uint16 hcnt;
|
||||
|
||||
//$2214,$2215
|
||||
uint16_t vcnt;
|
||||
uint16 vcnt;
|
||||
|
||||
//$2220 CXB
|
||||
bool cbmode;
|
||||
uint8_t cb;
|
||||
uint8 cb;
|
||||
|
||||
//$2221 DXB
|
||||
bool dbmode;
|
||||
uint8_t db;
|
||||
uint8 db;
|
||||
|
||||
//$2222 EXB
|
||||
bool ebmode;
|
||||
uint8_t eb;
|
||||
uint8 eb;
|
||||
|
||||
//$2223 FXB
|
||||
bool fbmode;
|
||||
uint8_t fb;
|
||||
uint8 fb;
|
||||
|
||||
//$2224 BMAPS
|
||||
uint8_t sbm;
|
||||
uint8 sbm;
|
||||
|
||||
//$2225 BMAP
|
||||
bool sw46;
|
||||
uint8_t cbm;
|
||||
uint8 cbm;
|
||||
|
||||
//$2226 SBWE
|
||||
bool swen;
|
||||
|
@ -92,13 +92,13 @@ struct MMIO {
|
|||
bool cwen;
|
||||
|
||||
//$2228 BWPA
|
||||
uint8_t bwp;
|
||||
uint8 bwp;
|
||||
|
||||
//$2229 SIWP
|
||||
uint8_t siwp;
|
||||
uint8 siwp;
|
||||
|
||||
//$222a CIWP
|
||||
uint8_t ciwp;
|
||||
uint8 ciwp;
|
||||
|
||||
//$2230 DCNT
|
||||
bool dmaen;
|
||||
|
@ -106,45 +106,45 @@ struct MMIO {
|
|||
bool cden;
|
||||
bool cdsel;
|
||||
bool dd;
|
||||
uint8_t sd;
|
||||
uint8 sd;
|
||||
|
||||
//$2231 CDMA
|
||||
bool chdend;
|
||||
uint8_t dmasize;
|
||||
uint8_t dmacb;
|
||||
uint8 dmasize;
|
||||
uint8 dmacb;
|
||||
|
||||
//$2232-$2234 SDA
|
||||
uint32_t dsa;
|
||||
uint32 dsa;
|
||||
|
||||
//$2235-$2237 DDA
|
||||
uint32_t dda;
|
||||
uint32 dda;
|
||||
|
||||
//$2238,$2239 DTC
|
||||
uint16_t dtc;
|
||||
uint16 dtc;
|
||||
|
||||
//$223f BBF
|
||||
bool bbf;
|
||||
|
||||
//$2240-224f BRF
|
||||
uint8_t brf[16];
|
||||
uint8 brf[16];
|
||||
|
||||
//$2250 MCNT
|
||||
bool acm;
|
||||
bool md;
|
||||
|
||||
//$2251,$2252 MA
|
||||
uint16_t ma;
|
||||
uint16 ma;
|
||||
|
||||
//$2253,$2254 MB
|
||||
uint16_t mb;
|
||||
uint16 mb;
|
||||
|
||||
//$2258 VBD
|
||||
bool hl;
|
||||
uint8_t vb;
|
||||
uint8 vb;
|
||||
|
||||
//$2259-$225b VDA
|
||||
uint32_t va;
|
||||
uint8_t vbit;
|
||||
uint32 va;
|
||||
uint8 vbit;
|
||||
|
||||
//$2300 SFR
|
||||
bool cpu_irqfl;
|
||||
|
@ -157,100 +157,100 @@ struct MMIO {
|
|||
bool sa1_nmifl;
|
||||
|
||||
//$2302,$2303 HCR
|
||||
uint16_t hcr;
|
||||
uint16 hcr;
|
||||
|
||||
//$2304,$2305 VCR
|
||||
uint16_t vcr;
|
||||
uint16 vcr;
|
||||
|
||||
//$2306-230a MR
|
||||
uint64_t mr;
|
||||
uint64 mr;
|
||||
|
||||
//$230b OF
|
||||
bool overflow;
|
||||
} mmio;
|
||||
|
||||
void mmio_w2200(uint8_t); //CCNT
|
||||
void mmio_w2201(uint8_t); //SIE
|
||||
void mmio_w2202(uint8_t); //SIC
|
||||
void mmio_w2203(uint8_t); //CRVL
|
||||
void mmio_w2204(uint8_t); //CRVH
|
||||
void mmio_w2205(uint8_t); //CNVL
|
||||
void mmio_w2206(uint8_t); //CNVH
|
||||
void mmio_w2207(uint8_t); //CIVL
|
||||
void mmio_w2208(uint8_t); //CIVH
|
||||
void mmio_w2209(uint8_t); //SCNT
|
||||
void mmio_w220a(uint8_t); //CIE
|
||||
void mmio_w220b(uint8_t); //CIC
|
||||
void mmio_w220c(uint8_t); //SNVL
|
||||
void mmio_w220d(uint8_t); //SNVH
|
||||
void mmio_w220e(uint8_t); //SIVL
|
||||
void mmio_w220f(uint8_t); //SIVH
|
||||
void mmio_w2210(uint8_t); //TMC
|
||||
void mmio_w2211(uint8_t); //CTR
|
||||
void mmio_w2212(uint8_t); //HCNTL
|
||||
void mmio_w2213(uint8_t); //HCNTH
|
||||
void mmio_w2214(uint8_t); //VCNTL
|
||||
void mmio_w2215(uint8_t); //VCNTH
|
||||
void mmio_w2220(uint8_t); //CXB
|
||||
void mmio_w2221(uint8_t); //DXB
|
||||
void mmio_w2222(uint8_t); //EXB
|
||||
void mmio_w2223(uint8_t); //FXB
|
||||
void mmio_w2224(uint8_t); //BMAPS
|
||||
void mmio_w2225(uint8_t); //BMAP
|
||||
void mmio_w2226(uint8_t); //SBWE
|
||||
void mmio_w2227(uint8_t); //CBWE
|
||||
void mmio_w2228(uint8_t); //BWPA
|
||||
void mmio_w2229(uint8_t); //SIWP
|
||||
void mmio_w222a(uint8_t); //CIWP
|
||||
void mmio_w2230(uint8_t); //DCNT
|
||||
void mmio_w2231(uint8_t); //CDMA
|
||||
void mmio_w2232(uint8_t); //SDAL
|
||||
void mmio_w2233(uint8_t); //SDAH
|
||||
void mmio_w2234(uint8_t); //SDAB
|
||||
void mmio_w2235(uint8_t); //DDAL
|
||||
void mmio_w2236(uint8_t); //DDAH
|
||||
void mmio_w2237(uint8_t); //DDAB
|
||||
void mmio_w2238(uint8_t); //DTCL
|
||||
void mmio_w2239(uint8_t); //DTCH
|
||||
void mmio_w223f(uint8_t); //BBF
|
||||
void mmio_w2240(uint8_t); //BRF0
|
||||
void mmio_w2241(uint8_t); //BRF1
|
||||
void mmio_w2242(uint8_t); //BRF2
|
||||
void mmio_w2243(uint8_t); //BRF3
|
||||
void mmio_w2244(uint8_t); //BRF4
|
||||
void mmio_w2245(uint8_t); //BRF5
|
||||
void mmio_w2246(uint8_t); //BRF6
|
||||
void mmio_w2247(uint8_t); //BRF7
|
||||
void mmio_w2248(uint8_t); //BRF8
|
||||
void mmio_w2249(uint8_t); //BRF9
|
||||
void mmio_w224a(uint8_t); //BRFA
|
||||
void mmio_w224b(uint8_t); //BRFB
|
||||
void mmio_w224c(uint8_t); //BRFC
|
||||
void mmio_w224d(uint8_t); //BRFD
|
||||
void mmio_w224e(uint8_t); //BRFE
|
||||
void mmio_w224f(uint8_t); //BRFF
|
||||
void mmio_w2250(uint8_t); //MCNT
|
||||
void mmio_w2251(uint8_t); //MAL
|
||||
void mmio_w2252(uint8_t); //MAH
|
||||
void mmio_w2253(uint8_t); //MBL
|
||||
void mmio_w2254(uint8_t); //MBH
|
||||
void mmio_w2258(uint8_t); //VBD
|
||||
void mmio_w2259(uint8_t); //VDAL
|
||||
void mmio_w225a(uint8_t); //VDAH
|
||||
void mmio_w225b(uint8_t); //VDAB
|
||||
void mmio_w2200(uint8); //CCNT
|
||||
void mmio_w2201(uint8); //SIE
|
||||
void mmio_w2202(uint8); //SIC
|
||||
void mmio_w2203(uint8); //CRVL
|
||||
void mmio_w2204(uint8); //CRVH
|
||||
void mmio_w2205(uint8); //CNVL
|
||||
void mmio_w2206(uint8); //CNVH
|
||||
void mmio_w2207(uint8); //CIVL
|
||||
void mmio_w2208(uint8); //CIVH
|
||||
void mmio_w2209(uint8); //SCNT
|
||||
void mmio_w220a(uint8); //CIE
|
||||
void mmio_w220b(uint8); //CIC
|
||||
void mmio_w220c(uint8); //SNVL
|
||||
void mmio_w220d(uint8); //SNVH
|
||||
void mmio_w220e(uint8); //SIVL
|
||||
void mmio_w220f(uint8); //SIVH
|
||||
void mmio_w2210(uint8); //TMC
|
||||
void mmio_w2211(uint8); //CTR
|
||||
void mmio_w2212(uint8); //HCNTL
|
||||
void mmio_w2213(uint8); //HCNTH
|
||||
void mmio_w2214(uint8); //VCNTL
|
||||
void mmio_w2215(uint8); //VCNTH
|
||||
void mmio_w2220(uint8); //CXB
|
||||
void mmio_w2221(uint8); //DXB
|
||||
void mmio_w2222(uint8); //EXB
|
||||
void mmio_w2223(uint8); //FXB
|
||||
void mmio_w2224(uint8); //BMAPS
|
||||
void mmio_w2225(uint8); //BMAP
|
||||
void mmio_w2226(uint8); //SBWE
|
||||
void mmio_w2227(uint8); //CBWE
|
||||
void mmio_w2228(uint8); //BWPA
|
||||
void mmio_w2229(uint8); //SIWP
|
||||
void mmio_w222a(uint8); //CIWP
|
||||
void mmio_w2230(uint8); //DCNT
|
||||
void mmio_w2231(uint8); //CDMA
|
||||
void mmio_w2232(uint8); //SDAL
|
||||
void mmio_w2233(uint8); //SDAH
|
||||
void mmio_w2234(uint8); //SDAB
|
||||
void mmio_w2235(uint8); //DDAL
|
||||
void mmio_w2236(uint8); //DDAH
|
||||
void mmio_w2237(uint8); //DDAB
|
||||
void mmio_w2238(uint8); //DTCL
|
||||
void mmio_w2239(uint8); //DTCH
|
||||
void mmio_w223f(uint8); //BBF
|
||||
void mmio_w2240(uint8); //BRF0
|
||||
void mmio_w2241(uint8); //BRF1
|
||||
void mmio_w2242(uint8); //BRF2
|
||||
void mmio_w2243(uint8); //BRF3
|
||||
void mmio_w2244(uint8); //BRF4
|
||||
void mmio_w2245(uint8); //BRF5
|
||||
void mmio_w2246(uint8); //BRF6
|
||||
void mmio_w2247(uint8); //BRF7
|
||||
void mmio_w2248(uint8); //BRF8
|
||||
void mmio_w2249(uint8); //BRF9
|
||||
void mmio_w224a(uint8); //BRFA
|
||||
void mmio_w224b(uint8); //BRFB
|
||||
void mmio_w224c(uint8); //BRFC
|
||||
void mmio_w224d(uint8); //BRFD
|
||||
void mmio_w224e(uint8); //BRFE
|
||||
void mmio_w224f(uint8); //BRFF
|
||||
void mmio_w2250(uint8); //MCNT
|
||||
void mmio_w2251(uint8); //MAL
|
||||
void mmio_w2252(uint8); //MAH
|
||||
void mmio_w2253(uint8); //MBL
|
||||
void mmio_w2254(uint8); //MBH
|
||||
void mmio_w2258(uint8); //VBD
|
||||
void mmio_w2259(uint8); //VDAL
|
||||
void mmio_w225a(uint8); //VDAH
|
||||
void mmio_w225b(uint8); //VDAB
|
||||
|
||||
uint8_t mmio_r2300(); //SFR
|
||||
uint8_t mmio_r2301(); //CFR
|
||||
uint8_t mmio_r2302(); //HCRL
|
||||
uint8_t mmio_r2303(); //HCRH
|
||||
uint8_t mmio_r2304(); //VCRL
|
||||
uint8_t mmio_r2305(); //VCRH
|
||||
uint8_t mmio_r2306(); //MR [00-07]
|
||||
uint8_t mmio_r2307(); //MR [08-15]
|
||||
uint8_t mmio_r2308(); //MR [16-23]
|
||||
uint8_t mmio_r2309(); //MR [24-31]
|
||||
uint8_t mmio_r230a(); //MR [32-40]
|
||||
uint8_t mmio_r230b(); //OF
|
||||
uint8_t mmio_r230c(); //VDPL
|
||||
uint8_t mmio_r230d(); //VDPH
|
||||
uint8_t mmio_r230e(); //VC
|
||||
uint8 mmio_r2300(); //SFR
|
||||
uint8 mmio_r2301(); //CFR
|
||||
uint8 mmio_r2302(); //HCRL
|
||||
uint8 mmio_r2303(); //HCRH
|
||||
uint8 mmio_r2304(); //VCRL
|
||||
uint8 mmio_r2305(); //VCRH
|
||||
uint8 mmio_r2306(); //MR [00-07]
|
||||
uint8 mmio_r2307(); //MR [08-15]
|
||||
uint8 mmio_r2308(); //MR [16-23]
|
||||
uint8 mmio_r2309(); //MR [24-31]
|
||||
uint8 mmio_r230a(); //MR [32-40]
|
||||
uint8 mmio_r230b(); //OF
|
||||
uint8 mmio_r230c(); //VDPL
|
||||
uint8 mmio_r230d(); //VDPH
|
||||
uint8 mmio_r230e(); //VC
|
||||
|
|
|
@ -54,7 +54,7 @@ void SA1::last_cycle() {
|
|||
}
|
||||
}
|
||||
|
||||
void SA1::interrupt(uint16_t vector) {
|
||||
void SA1::interrupt(uint16 vector) {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
|
@ -73,6 +73,7 @@ bool SA1::interrupt_pending() {
|
|||
|
||||
void SA1::tick() {
|
||||
scheduler.addclocks_cop(2);
|
||||
if(++status.tick_counter == 0) scheduler.sync_copcpu();
|
||||
|
||||
//adjust counters:
|
||||
//note that internally, status counters are in clocks;
|
||||
|
@ -125,6 +126,7 @@ void SA1::reset() {
|
|||
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
|
||||
memory::iram.write(addr, 0x00);
|
||||
}
|
||||
vbrbus.init();
|
||||
sa1bus.init();
|
||||
|
||||
regs.pc.d = 0x000000;
|
||||
|
@ -139,6 +141,8 @@ void SA1::reset() {
|
|||
regs.wai = false;
|
||||
update_table();
|
||||
|
||||
status.tick_counter = 0;
|
||||
|
||||
status.interrupt_pending = false;
|
||||
status.interrupt_vector = 0x0000;
|
||||
|
||||
|
|
|
@ -7,16 +7,18 @@ public:
|
|||
#include "mmio/mmio.hpp"
|
||||
|
||||
struct Status {
|
||||
bool interrupt_pending;
|
||||
uint16_t interrupt_vector;
|
||||
uint8 tick_counter;
|
||||
|
||||
uint16_t scanlines;
|
||||
uint16_t vcounter;
|
||||
uint16_t hcounter;
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
|
||||
uint16 scanlines;
|
||||
uint16 vcounter;
|
||||
uint16 hcounter;
|
||||
} status;
|
||||
|
||||
void enter();
|
||||
void interrupt(uint16_t vector);
|
||||
void interrupt(uint16 vector);
|
||||
void tick();
|
||||
|
||||
alwaysinline void trigger_irq();
|
||||
|
|
|
@ -30,6 +30,7 @@ understood.
|
|||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8 bool8;
|
||||
#define SDD1_read(__addr) (sdd1.read(__addr))
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -28,7 +28,7 @@ understood.
|
|||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8_t bool8;
|
||||
#define bool8 uint8
|
||||
|
||||
class SDD1_IM { //Input Manager
|
||||
|
||||
|
@ -160,3 +160,5 @@ class SDD1emu {
|
|||
SDD1_OL OL;
|
||||
|
||||
};
|
||||
|
||||
#undef bool8
|
||||
|
|
|
@ -4,6 +4,7 @@ public:
|
|||
void init(unsigned mode, unsigned offset, unsigned index);
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
SPC7110Decomp();
|
||||
~SPC7110Decomp();
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#ifdef SPC7110_CPP
|
||||
|
||||
void SPC7110Decomp::serialize(serializer &s) {
|
||||
s.integer(decomp_mode);
|
||||
s.integer(decomp_offset);
|
||||
|
||||
s.array(decomp_buffer, decomp_buffer_size);
|
||||
s.integer(decomp_buffer_rdoffset);
|
||||
s.integer(decomp_buffer_wroffset);
|
||||
s.integer(decomp_buffer_length);
|
||||
|
||||
for(unsigned n = 0; n < 32; n++) {
|
||||
s.integer(context[n].index);
|
||||
s.integer(context[n].invert);
|
||||
}
|
||||
}
|
||||
|
||||
void SPC7110::serialize(serializer &s) {
|
||||
s.integer(r4801);
|
||||
s.integer(r4802);
|
||||
s.integer(r4803);
|
||||
s.integer(r4804);
|
||||
s.integer(r4805);
|
||||
s.integer(r4806);
|
||||
s.integer(r4807);
|
||||
s.integer(r4808);
|
||||
s.integer(r4809);
|
||||
s.integer(r480a);
|
||||
s.integer(r480b);
|
||||
s.integer(r480c);
|
||||
decomp.serialize(s);
|
||||
|
||||
s.integer(r4811);
|
||||
s.integer(r4812);
|
||||
s.integer(r4813);
|
||||
s.integer(r4814);
|
||||
s.integer(r4815);
|
||||
s.integer(r4816);
|
||||
s.integer(r4817);
|
||||
s.integer(r4818);
|
||||
s.integer(r481x);
|
||||
s.integer(r4814_latch);
|
||||
s.integer(r4815_latch);
|
||||
|
||||
s.integer(r4820);
|
||||
s.integer(r4821);
|
||||
s.integer(r4822);
|
||||
s.integer(r4823);
|
||||
s.integer(r4824);
|
||||
s.integer(r4825);
|
||||
s.integer(r4826);
|
||||
s.integer(r4827);
|
||||
s.integer(r4828);
|
||||
s.integer(r4829);
|
||||
s.integer(r482a);
|
||||
s.integer(r482b);
|
||||
s.integer(r482c);
|
||||
s.integer(r482d);
|
||||
s.integer(r482e);
|
||||
s.integer(r482f);
|
||||
|
||||
s.integer(r4830);
|
||||
s.integer(r4831);
|
||||
s.integer(r4832);
|
||||
s.integer(r4833);
|
||||
s.integer(r4834);
|
||||
|
||||
s.integer(dx_offset);
|
||||
s.integer(ex_offset);
|
||||
s.integer(fx_offset);
|
||||
|
||||
s.integer(r4840);
|
||||
s.integer(r4841);
|
||||
s.integer(r4842);
|
||||
|
||||
s.integer(rtc_state);
|
||||
s.integer(rtc_mode);
|
||||
s.integer(rtc_index);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@ namespace SNES {
|
|||
|
||||
SPC7110 spc7110;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "decomp.cpp"
|
||||
|
||||
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
|
|
@ -35,48 +35,49 @@ public:
|
|||
void update_time(int offset = 0);
|
||||
time_t create_time();
|
||||
|
||||
uint8 mmio_read (unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 read (unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
//spc7110decomp
|
||||
void decomp_init();
|
||||
uint8 decomp_read();
|
||||
|
||||
void serialize(serializer&);
|
||||
SPC7110();
|
||||
|
||||
private:
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
uint8 r4801; //compression table low
|
||||
uint8 r4802; //compression table high
|
||||
uint8 r4803; //compression table bank
|
||||
uint8 r4804; //compression table index
|
||||
uint8 r4805; //decompression buffer index low
|
||||
uint8 r4806; //decompression buffer index high
|
||||
uint8 r4807; //???
|
||||
uint8 r4808; //???
|
||||
uint8 r4809; //compression length low
|
||||
uint8 r480a; //compression length high
|
||||
uint8 r480b; //decompression control register
|
||||
uint8 r480c; //decompression status
|
||||
uint8 r4801; //compression table low
|
||||
uint8 r4802; //compression table high
|
||||
uint8 r4803; //compression table bank
|
||||
uint8 r4804; //compression table index
|
||||
uint8 r4805; //decompression buffer index low
|
||||
uint8 r4806; //decompression buffer index high
|
||||
uint8 r4807; //???
|
||||
uint8 r4808; //???
|
||||
uint8 r4809; //compression length low
|
||||
uint8 r480a; //compression length high
|
||||
uint8 r480b; //decompression control register
|
||||
uint8 r480c; //decompression status
|
||||
|
||||
SPC7110Decomp decomp;
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
uint8 r4811; //data pointer low
|
||||
uint8 r4812; //data pointer high
|
||||
uint8 r4813; //data pointer bank
|
||||
uint8 r4814; //data adjust low
|
||||
uint8 r4815; //data adjust high
|
||||
uint8 r4816; //data increment low
|
||||
uint8 r4817; //data increment high
|
||||
uint8 r4818; //data port control register
|
||||
uint8 r4811; //data pointer low
|
||||
uint8 r4812; //data pointer high
|
||||
uint8 r4813; //data pointer bank
|
||||
uint8 r4814; //data adjust low
|
||||
uint8 r4815; //data adjust high
|
||||
uint8 r4816; //data increment low
|
||||
uint8 r4817; //data increment high
|
||||
uint8 r4818; //data port control register
|
||||
|
||||
uint8 r481x;
|
||||
|
||||
|
@ -86,31 +87,31 @@ private:
|
|||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||
uint8 r4822; //32-bit dividend B2
|
||||
uint8 r4823; //32-bit dividend B3
|
||||
uint8 r4824; //16-bit multiplier B0
|
||||
uint8 r4825; //16-bit multiplier B1
|
||||
uint8 r4826; //16-bit divisor B0
|
||||
uint8 r4827; //16-bit divisor B1
|
||||
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||
uint8 r482c; //16-bit remainder B0
|
||||
uint8 r482d; //16-bit remainder B1
|
||||
uint8 r482e; //math control register
|
||||
uint8 r482f; //math status
|
||||
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||
uint8 r4822; //32-bit dividend B2
|
||||
uint8 r4823; //32-bit dividend B3
|
||||
uint8 r4824; //16-bit multiplier B0
|
||||
uint8 r4825; //16-bit multiplier B1
|
||||
uint8 r4826; //16-bit divisor B0
|
||||
uint8 r4827; //16-bit divisor B1
|
||||
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||
uint8 r482c; //16-bit remainder B0
|
||||
uint8 r482d; //16-bit remainder B1
|
||||
uint8 r482e; //math control register
|
||||
uint8 r482f; //math status
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
uint8 r4830; //SRAM write enable
|
||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||
uint8 r4834; //???
|
||||
uint8 r4830; //SRAM write enable
|
||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||
uint8 r4834; //???
|
||||
|
||||
unsigned dx_offset;
|
||||
unsigned ex_offset;
|
||||
|
@ -119,12 +120,14 @@ private:
|
|||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
uint8 r4840; //RTC latch
|
||||
uint8 r4841; //RTC index/data port
|
||||
uint8 r4842; //RTC status
|
||||
uint8 r4840; //RTC latch
|
||||
uint8 r4841; //RTC index/data port
|
||||
uint8 r4842; //RTC status
|
||||
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state;
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode;
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write };
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c };
|
||||
unsigned rtc_state;
|
||||
unsigned rtc_mode;
|
||||
unsigned rtc_index;
|
||||
|
||||
static const unsigned months[12];
|
||||
|
|
|
@ -5,6 +5,14 @@ namespace SNES {
|
|||
|
||||
ST010 st010;
|
||||
|
||||
void ST010::init() {
|
||||
}
|
||||
|
||||
void ST010::enable() {
|
||||
bus.map(Bus::MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, *this);
|
||||
bus.map(Bus::MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, *this);
|
||||
}
|
||||
|
||||
#include "st010_data.hpp"
|
||||
#include "st010_op.cpp"
|
||||
|
||||
|
@ -37,25 +45,19 @@ void ST010::writeb(uint16 addr, uint8 data) {
|
|||
}
|
||||
|
||||
void ST010::writew(uint16 addr, uint16 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 0, data >> 0);
|
||||
writeb(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void ST010::writed(uint16 addr, uint32 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 1, data >> 8);
|
||||
writeb(addr + 0, data >> 0);
|
||||
writeb(addr + 1, data >> 8);
|
||||
writeb(addr + 2, data >> 16);
|
||||
writeb(addr + 3, data >> 24);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void ST010::init() {
|
||||
}
|
||||
|
||||
void ST010::enable() {
|
||||
}
|
||||
|
||||
void ST010::power() {
|
||||
reset();
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ public:
|
|||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
private:
|
||||
uint8 ram[0x1000];
|
||||
|
@ -14,11 +14,11 @@ private:
|
|||
static const int16 mode7_scale[176];
|
||||
static const uint8 arctan[32][32];
|
||||
|
||||
//interfaces to sin table
|
||||
//interfaces to sin table
|
||||
int16 sin(int16 theta);
|
||||
int16 cos(int16 theta);
|
||||
|
||||
//interfaces to ram buffer
|
||||
//interfaces to ram buffer
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
uint32 readd (uint16 addr);
|
||||
|
@ -26,7 +26,7 @@ private:
|
|||
void writew(uint16 addr, uint16 data);
|
||||
void writed(uint16 addr, uint32 data);
|
||||
|
||||
//opcodes
|
||||
//opcodes
|
||||
void op_01();
|
||||
void op_02();
|
||||
void op_03();
|
||||
|
|
|
@ -35,26 +35,26 @@ void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int
|
|||
//
|
||||
|
||||
void ST010::op_01() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 x1, y1, quadrant, theta;
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 x1, y1, quadrant, theta;
|
||||
|
||||
op_01(x0, y0, x1, y1, quadrant, theta);
|
||||
|
||||
writew(0x0000, x1);
|
||||
writew(0x0002, y1);
|
||||
writew(0x0004, quadrant);
|
||||
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||
writew(0x0010, theta);
|
||||
}
|
||||
|
||||
void ST010::op_02() {
|
||||
int16 positions = readw(0x0024);
|
||||
uint16 *places = (uint16*)(ram + 0x0040);
|
||||
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||
int16 positions = readw(0x0024);
|
||||
uint16 *places = (uint16*)(ram + 0x0040);
|
||||
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||
|
||||
bool sorted;
|
||||
uint16 temp;
|
||||
bool sorted;
|
||||
uint16 temp;
|
||||
if(positions > 1) {
|
||||
do {
|
||||
sorted = true;
|
||||
|
@ -77,10 +77,10 @@ uint16 temp;
|
|||
}
|
||||
|
||||
void ST010::op_03() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 multiplier = readw(0x0004);
|
||||
int32 x1, y1;
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 multiplier = readw(0x0004);
|
||||
int32 x1, y1;
|
||||
|
||||
x1 = x0 * multiplier << 1;
|
||||
y1 = y0 * multiplier << 1;
|
||||
|
@ -90,121 +90,121 @@ int32 x1, y1;
|
|||
}
|
||||
|
||||
void ST010::op_04() {
|
||||
int16 x = readw(0x0000);
|
||||
int16 y = readw(0x0002);
|
||||
int16 square;
|
||||
//calculate the vector length of (x,y)
|
||||
int16 x = readw(0x0000);
|
||||
int16 y = readw(0x0002);
|
||||
int16 square;
|
||||
//calculate the vector length of (x,y)
|
||||
square = (int16)sqrt((double)(y * y + x * x));
|
||||
|
||||
writew(0x0010, square);
|
||||
}
|
||||
|
||||
void ST010::op_05() {
|
||||
int32 dx, dy;
|
||||
int16 a1, b1, c1;
|
||||
uint16 o1;
|
||||
bool wrap = false;
|
||||
int32 dx, dy;
|
||||
int16 a1, b1, c1;
|
||||
uint16 o1;
|
||||
bool wrap = false;
|
||||
|
||||
//target (x,y) coordinates
|
||||
int16 ypos_max = readw(0x00c0);
|
||||
int16 xpos_max = readw(0x00c2);
|
||||
//target (x,y) coordinates
|
||||
int16 ypos_max = readw(0x00c0);
|
||||
int16 xpos_max = readw(0x00c2);
|
||||
|
||||
//current coordinates and direction
|
||||
int32 ypos = readd(0x00c4);
|
||||
int32 xpos = readd(0x00c8);
|
||||
uint16 rot = readw(0x00cc);
|
||||
//current coordinates and direction
|
||||
int32 ypos = readd(0x00c4);
|
||||
int32 xpos = readd(0x00c8);
|
||||
uint16 rot = readw(0x00cc);
|
||||
|
||||
//physics
|
||||
uint16 speed = readw(0x00d4);
|
||||
uint16 accel = readw(0x00d6);
|
||||
uint16 speed_max = readw(0x00d8);
|
||||
//physics
|
||||
uint16 speed = readw(0x00d4);
|
||||
uint16 accel = readw(0x00d6);
|
||||
uint16 speed_max = readw(0x00d8);
|
||||
|
||||
//special condition acknowledgement
|
||||
int16 system = readw(0x00da);
|
||||
int16 flags = readw(0x00dc);
|
||||
//special condition acknowledgement
|
||||
int16 system = readw(0x00da);
|
||||
int16 flags = readw(0x00dc);
|
||||
|
||||
//new target coordinates
|
||||
int16 ypos_new = readw(0x00de);
|
||||
int16 xpos_new = readw(0x00e0);
|
||||
//new target coordinates
|
||||
int16 ypos_new = readw(0x00de);
|
||||
int16 xpos_new = readw(0x00e0);
|
||||
|
||||
//mask upper bit
|
||||
//mask upper bit
|
||||
xpos_new &= 0x7fff;
|
||||
|
||||
//get the current distance
|
||||
//get the current distance
|
||||
dx = xpos_max - (xpos >> 16);
|
||||
dy = ypos_max - (ypos >> 16);
|
||||
|
||||
//quirk: clear and move in9
|
||||
//quirk: clear and move in9
|
||||
writew(0x00d2, 0xffff);
|
||||
writew(0x00da, 0x0000);
|
||||
|
||||
//grab the target angle
|
||||
//grab the target angle
|
||||
op_01(dy, dx, a1, b1, c1, (int16&)o1);
|
||||
|
||||
//check for wrapping
|
||||
//check for wrapping
|
||||
if(abs(o1 - rot) > 0x8000) {
|
||||
o1 += 0x8000;
|
||||
rot += 0x8000;
|
||||
wrap = true;
|
||||
}
|
||||
|
||||
uint16 old_speed = speed;
|
||||
uint16 old_speed = speed;
|
||||
|
||||
//special case
|
||||
//special case
|
||||
if(abs(o1 - rot) == 0x8000) {
|
||||
speed = 0x100;
|
||||
}
|
||||
|
||||
//slow down for sharp curves
|
||||
//slow down for sharp curves
|
||||
else if(abs(o1 - rot) >= 0x1000) {
|
||||
uint32 slow = abs(o1 - rot);
|
||||
slow >>= 4; //scaling
|
||||
slow >>= 4; //scaling
|
||||
speed -= slow;
|
||||
}
|
||||
|
||||
//otherwise accelerate
|
||||
//otherwise accelerate
|
||||
else {
|
||||
speed += accel;
|
||||
if(speed > speed_max) {
|
||||
speed = speed_max; //clip speed
|
||||
speed = speed_max; //clip speed
|
||||
}
|
||||
}
|
||||
|
||||
//prevent negative/positive overflow
|
||||
//prevent negative/positive overflow
|
||||
if(abs(old_speed - speed) > 0x8000) {
|
||||
if(old_speed < speed) { speed = 0; }
|
||||
else speed = 0xff00;
|
||||
}
|
||||
|
||||
//adjust direction by so many degrees
|
||||
//be careful of negative adjustments
|
||||
//adjust direction by so many degrees
|
||||
//be careful of negative adjustments
|
||||
if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
|
||||
if(o1 < rot) { rot -= 0x280; }
|
||||
else if(o1 > rot) { rot += 0x280; }
|
||||
}
|
||||
|
||||
//turn of wrapping
|
||||
//turn off wrapping
|
||||
if(wrap) { rot -= 0x8000; }
|
||||
|
||||
//now check the distances (store for later)
|
||||
//now check the distances (store for later)
|
||||
dx = (xpos_max << 16) - xpos;
|
||||
dy = (ypos_max << 16) - ypos;
|
||||
dx >>= 16;
|
||||
dy >>= 16;
|
||||
|
||||
//if we're in so many units of the target, signal it
|
||||
//if we're in so many units of the target, signal it
|
||||
if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
|
||||
//announce our new destination and flag it
|
||||
//announce our new destination and flag it
|
||||
xpos_max = xpos_new & 0x7fff;
|
||||
ypos_max = ypos_new;
|
||||
flags |= 0x08;
|
||||
}
|
||||
|
||||
//update position
|
||||
//update position
|
||||
xpos -= (cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
ypos -= (sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
|
||||
//quirk: mask upper byte
|
||||
//quirk: mask upper byte
|
||||
xpos &= 0x1fffffff;
|
||||
ypos &= 0x1fffffff;
|
||||
|
||||
|
@ -218,9 +218,9 @@ uint16 old_speed = speed;
|
|||
}
|
||||
|
||||
void ST010::op_06() {
|
||||
int16 multiplicand = readw(0x0000);
|
||||
int16 multiplier = readw(0x0002);
|
||||
int32 product;
|
||||
int16 multiplicand = readw(0x0000);
|
||||
int16 multiplier = readw(0x0002);
|
||||
int32 product;
|
||||
|
||||
product = multiplicand * multiplier << 1;
|
||||
|
||||
|
@ -228,9 +228,9 @@ int32 product;
|
|||
}
|
||||
|
||||
void ST010::op_07() {
|
||||
int16 theta = readw(0x0000);
|
||||
int16 theta = readw(0x0000);
|
||||
|
||||
int16 data;
|
||||
int16 data;
|
||||
for(int i = 0, offset = 0; i < 176; i++) {
|
||||
data = mode7_scale[i] * cos(theta) >> 15;
|
||||
writew(0x00f0 + offset, data);
|
||||
|
@ -246,10 +246,10 @@ int16 data;
|
|||
}
|
||||
|
||||
void ST010::op_08() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 theta = readw(0x0004);
|
||||
int16 x1, y1;
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 theta = readw(0x0004);
|
||||
int16 x1, y1;
|
||||
|
||||
x1 = (y0 * sin(theta) >> 15) + (x0 * cos(theta) >> 15);
|
||||
y1 = (y0 * cos(theta) >> 15) - (x0 * sin(theta) >> 15);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#include <../base.hpp>
|
||||
|
||||
#define ST011_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST011 st011;
|
||||
|
||||
void ST011::init() {
|
||||
}
|
||||
|
||||
void ST011::enable() {
|
||||
}
|
||||
|
||||
void ST011::power() {
|
||||
}
|
||||
|
||||
void ST011::reset() {
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
class ST011 {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
};
|
||||
|
||||
extern ST011 st011;
|
|
@ -0,0 +1,124 @@
|
|||
#include <../base.hpp>
|
||||
|
||||
#define ST018_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST018 st018;
|
||||
|
||||
uint8 ST018::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
if(addr == 0x3800) return regs.r3800;
|
||||
if(addr == 0x3804) return regs.r3804;
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void ST018::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x3802) {
|
||||
switch(regs.mode) {
|
||||
case Waiting: {
|
||||
switch(data) {
|
||||
case 0x01: regs.r3800 = regs.r3800_01; break;
|
||||
case 0xaa: op_board_upload(); break;
|
||||
case 0xb2: op_b2(); break;
|
||||
case 0xb3: op_b3(); break;
|
||||
case 0xb4: op_b4(); break;
|
||||
case 0xb5: op_b5(); break;
|
||||
case 0xf1: op_query_chip(); break;
|
||||
case 0xf2: op_query_chip(); break;
|
||||
default: fprintf(stdout, "* ST018 w3802::%.2x\n", data); break;
|
||||
}
|
||||
} return;
|
||||
|
||||
case BoardUpload: {
|
||||
op_board_upload(data);
|
||||
} return;
|
||||
}
|
||||
}
|
||||
|
||||
if(addr == 0x3804) {
|
||||
regs.w3804 <<= 8;
|
||||
regs.w3804 |= data;
|
||||
regs.w3804 &= 0xffffff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ST018::init() {
|
||||
}
|
||||
|
||||
void ST018::enable() {
|
||||
for(unsigned i = 0x3800; i <= 0x38ff; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void ST018::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void ST018::reset() {
|
||||
regs.mode = Waiting;
|
||||
regs.r3800 = 0x00;
|
||||
regs.r3804 = 0x85;
|
||||
regs.w3804 = 0;
|
||||
for(unsigned i = 0; i < 97; i++) board[i] = 0;
|
||||
}
|
||||
|
||||
//=============
|
||||
//ST018 opcodes
|
||||
//=============
|
||||
|
||||
void ST018::op_board_upload() {
|
||||
regs.mode = BoardUpload;
|
||||
regs.counter = 0;
|
||||
regs.r3800 = 0xe0;
|
||||
}
|
||||
|
||||
void ST018::op_board_upload(uint8 data) {
|
||||
board[regs.counter] = data;
|
||||
regs.r3800 = 96 - regs.counter;
|
||||
regs.counter++;
|
||||
if(regs.counter >= 97) {
|
||||
regs.mode = Waiting;
|
||||
#if 0
|
||||
for(unsigned y = 0; y < 9; y++) {
|
||||
for(unsigned x = 0; x < 9; x++) {
|
||||
fprintf(stdout, "%.2x ", board[y * 9 + x]);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
for(unsigned n = 0; n < 16; n++) fprintf(stdout, "%.2x ", board[81 + n]);
|
||||
fprintf(stdout, "\n\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ST018::op_b2() {
|
||||
fprintf(stdout, "* ST018 w3802::b2\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 0; //unknown
|
||||
}
|
||||
|
||||
void ST018::op_b3() {
|
||||
fprintf(stdout, "* ST018 w3802::b3\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 1; //0 = player lost?
|
||||
}
|
||||
|
||||
void ST018::op_b4() {
|
||||
fprintf(stdout, "* ST018 w3802::b4\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 1; //0 = player won?
|
||||
}
|
||||
|
||||
void ST018::op_b5() {
|
||||
fprintf(stdout, "* ST018 w3802::b5\n");
|
||||
regs.r3800 = 0xe0;
|
||||
regs.r3800_01 = 0; //1 = move will result in checkmate?
|
||||
}
|
||||
|
||||
void ST018::op_query_chip() {
|
||||
regs.r3800 = 0x00;
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
class ST018 : public MMIO {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
||||
enum mode_t { Waiting, BoardUpload };
|
||||
struct regs_t {
|
||||
mode_t mode;
|
||||
|
||||
uint8 r3800;
|
||||
uint8 r3800_01;
|
||||
uint8 r3804;
|
||||
|
||||
unsigned w3804;
|
||||
unsigned counter;
|
||||
} regs;
|
||||
|
||||
enum PieceID {
|
||||
Pawn = 0x00, //foot soldier
|
||||
Lance = 0x04, //incense chariot
|
||||
Knight = 0x08, //cassia horse
|
||||
Silver = 0x0c, //silver general
|
||||
Gold = 0x10, //gold general
|
||||
Rook = 0x14, //flying chariot
|
||||
Bishop = 0x18, //angle mover
|
||||
King = 0x1c, //king
|
||||
};
|
||||
|
||||
enum PieceFlag {
|
||||
PlayerA = 0x20,
|
||||
PlayerB = 0x40,
|
||||
};
|
||||
|
||||
uint8 board[9 * 9 + 16];
|
||||
|
||||
private:
|
||||
void op_board_upload();
|
||||
void op_board_upload(uint8 data);
|
||||
void op_b2();
|
||||
void op_b3();
|
||||
void op_b4();
|
||||
void op_b5();
|
||||
void op_query_chip();
|
||||
};
|
||||
|
||||
extern ST018 st018;
|
|
@ -33,25 +33,39 @@ unsigned SuperFXGSUROM::size() const {
|
|||
return memory::cartrom.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXGSUROM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ron) superfx.add_clocks(2);
|
||||
uint8 SuperFXGSUROM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ron) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
return memory::cartrom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXGSUROM::write(unsigned addr, uint8_t data) {
|
||||
void SuperFXGSUROM::write(unsigned addr, uint8 data) {
|
||||
while(!superfx.regs.scmr.ron) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
memory::cartrom.write(addr, data);
|
||||
}
|
||||
|
||||
unsigned SuperFXGSURAM::size() const {
|
||||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXGSURAM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ran) superfx.add_clocks(2);
|
||||
uint8 SuperFXGSURAM::read(unsigned addr) {
|
||||
while(!superfx.regs.scmr.ran) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXGSURAM::write(unsigned addr, uint8_t data) {
|
||||
while(!superfx.regs.scmr.ran) superfx.add_clocks(2);
|
||||
void SuperFXGSURAM::write(unsigned addr, uint8 data) {
|
||||
while(!superfx.regs.scmr.ran) {
|
||||
superfx.add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
|
@ -61,7 +75,7 @@ unsigned SuperFXCPUROM::size() const {
|
|||
return memory::cartrom.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXCPUROM::read(unsigned addr) {
|
||||
uint8 SuperFXCPUROM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
|
||||
static const uint8_t data[16] = {
|
||||
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
|
||||
|
@ -72,7 +86,7 @@ uint8_t SuperFXCPUROM::read(unsigned addr) {
|
|||
return memory::cartrom.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPUROM::write(unsigned addr, uint8_t data) {
|
||||
void SuperFXCPUROM::write(unsigned addr, uint8 data) {
|
||||
memory::cartrom.write(addr, data);
|
||||
}
|
||||
|
||||
|
@ -80,12 +94,12 @@ unsigned SuperFXCPURAM::size() const {
|
|||
return memory::cartram.size();
|
||||
}
|
||||
|
||||
uint8_t SuperFXCPURAM::read(unsigned addr) {
|
||||
uint8 SuperFXCPURAM::read(unsigned addr) {
|
||||
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr;
|
||||
return memory::cartram.read(addr);
|
||||
}
|
||||
|
||||
void SuperFXCPURAM::write(unsigned addr, uint8_t data) {
|
||||
void SuperFXCPURAM::write(unsigned addr, uint8 data) {
|
||||
memory::cartram.write(addr, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,24 +4,24 @@ struct SuperFXBus : Bus {
|
|||
|
||||
struct SuperFXGSUROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SuperFXGSURAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SuperFXCPUROM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
||||
struct SuperFXCPURAM : Memory {
|
||||
unsigned size() const;
|
||||
uint8_t read(unsigned);
|
||||
void write(unsigned, uint8_t);
|
||||
uint8 read(unsigned);
|
||||
void write(unsigned, uint8);
|
||||
};
|
||||
|
|
|
@ -3,28 +3,14 @@
|
|||
#include "opcodes.cpp"
|
||||
#include "opcode_table.cpp"
|
||||
|
||||
void SuperFX::exec_opcode() {
|
||||
#if 0
|
||||
if(!fp) fp = fopen("sfxtrace.log", "wb");
|
||||
char t[4096];
|
||||
disassemble_opcode(t);
|
||||
fprintf(fp, "%s ", t);
|
||||
for(unsigned i = 0; i < 16; i++) fprintf(fp, "r%u:%.4x ", i, (uint16_t)regs.r[i]);
|
||||
fprintf(fp, "\n");
|
||||
#endif
|
||||
|
||||
(this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
|
||||
if(r15_modified == false) regs.r[15]++;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::color(uint8_t source) {
|
||||
uint8 SuperFX::color(uint8 source) {
|
||||
if(regs.por.highnibble) return (regs.colr & 0xf0) | (source >> 4);
|
||||
if(regs.por.freezehigh) return (regs.colr & 0xf0) | (source & 0x0f);
|
||||
return source;
|
||||
}
|
||||
|
||||
void SuperFX::plot(uint8_t x, uint8_t y) {
|
||||
uint8_t color = regs.colr;
|
||||
void SuperFX::plot(uint8 x, uint8 y) {
|
||||
uint8 color = regs.colr;
|
||||
|
||||
if(regs.por.dither && regs.scmr.md != 3) {
|
||||
if((x ^ y) & 1) color >>= 4;
|
||||
|
@ -43,7 +29,7 @@ void SuperFX::plot(uint8_t x, uint8_t y) {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t offset = (y << 5) + (x >> 3);
|
||||
uint16 offset = (y << 5) + (x >> 3);
|
||||
if(offset != pixelcache[0].offset) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache[1] = pixelcache[0];
|
||||
|
@ -61,7 +47,7 @@ void SuperFX::plot(uint8_t x, uint8_t y) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
||||
uint8 SuperFX::rpix(uint8 x, uint8 y) {
|
||||
pixelcache_flush(pixelcache[1]);
|
||||
pixelcache_flush(pixelcache[0]);
|
||||
|
||||
|
@ -74,7 +60,7 @@ uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
|||
}
|
||||
unsigned bpp = 2 << (regs.scmr.md - (regs.scmr.md >> 1)); // = [regs.scmr.md]{ 2, 4, 4, 8 };
|
||||
unsigned addr = 0x700000 + (cn * (bpp << 3)) + (regs.scbr << 10) + ((y & 0x07) * 2);
|
||||
uint8_t data = 0x00;
|
||||
uint8 data = 0x00;
|
||||
x = (x & 7) ^ 7;
|
||||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
|
@ -89,8 +75,8 @@ uint8_t SuperFX::rpix(uint8_t x, uint8_t y) {
|
|||
void SuperFX::pixelcache_flush(pixelcache_t &cache) {
|
||||
if(cache.bitpend == 0x00) return;
|
||||
|
||||
uint8_t x = cache.offset << 3;
|
||||
uint8_t y = cache.offset >> 5;
|
||||
uint8 x = cache.offset << 3;
|
||||
uint8 y = cache.offset >> 5;
|
||||
|
||||
unsigned cn; //character number
|
||||
switch(regs.por.obj ? 3 : regs.scmr.ht) {
|
||||
|
@ -104,7 +90,7 @@ void SuperFX::pixelcache_flush(pixelcache_t &cache) {
|
|||
|
||||
for(unsigned n = 0; n < bpp; n++) {
|
||||
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
|
||||
uint8_t data = 0x00;
|
||||
uint8 data = 0x00;
|
||||
for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x;
|
||||
if(cache.bitpend != 0xff) {
|
||||
add_clocks(memory_access_speed);
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#include "registers.hpp"
|
||||
|
||||
void exec_opcode();
|
||||
uint8_t color(uint8_t source);
|
||||
void plot(uint8_t x, uint8_t y);
|
||||
uint8_t rpix(uint8_t x, uint8_t y);
|
||||
uint8 color(uint8 source);
|
||||
void plot(uint8 x, uint8 y);
|
||||
uint8 rpix(uint8 x, uint8 y);
|
||||
void pixelcache_flush(pixelcache_t &cache);
|
||||
|
||||
void (SuperFX::*opcode_table[1024])();
|
||||
|
|
|
@ -47,66 +47,66 @@ void SuperFX::op_rol() {
|
|||
|
||||
//$05 bra e
|
||||
void SuperFX::op_bra() {
|
||||
regs.r[15] += (int8_t)pipe();
|
||||
regs.r[15] += (int8)pipe();
|
||||
}
|
||||
|
||||
//$06 blt e
|
||||
void SuperFX::op_blt() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if((regs.sfr.s ^ regs.sfr.ov) == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$07 bge e
|
||||
void SuperFX::op_bge() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if((regs.sfr.s ^ regs.sfr.ov) == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$08 bne e
|
||||
void SuperFX::op_bne() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.z == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$09 beq e
|
||||
void SuperFX::op_beq() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.z == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0a bpl e
|
||||
void SuperFX::op_bpl() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.s == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0b bmi e
|
||||
void SuperFX::op_bmi() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.s == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0c bcc e
|
||||
void SuperFX::op_bcc() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.cy == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0d bcs e
|
||||
void SuperFX::op_bcs() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.cy == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0e bvc e
|
||||
void SuperFX::op_bvc() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.ov == 0) regs.r[15] += e;
|
||||
}
|
||||
|
||||
//$0f bvs e
|
||||
void SuperFX::op_bvs() {
|
||||
int e = (int8_t)pipe();
|
||||
int e = (int8)pipe();
|
||||
if(regs.sfr.ov == 1) regs.r[15] += e;
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,7 @@ template<int n> void SuperFX::op_bic_i() {
|
|||
|
||||
//$80-8f(alt0): mult rN
|
||||
template<int n> void SuperFX::op_mult_r() {
|
||||
regs.dr() = (int8_t)regs.sr() * (int8_t)regs.r[n];
|
||||
regs.dr() = (int8)regs.sr() * (int8)regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
|
@ -371,7 +371,7 @@ template<int n> void SuperFX::op_mult_r() {
|
|||
|
||||
//$80-8f(alt1): umult rN
|
||||
template<int n> void SuperFX::op_umult_r() {
|
||||
regs.dr() = (uint8_t)regs.sr() * (uint8_t)regs.r[n];
|
||||
regs.dr() = (uint8)regs.sr() * (uint8)regs.r[n];
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
|
@ -380,7 +380,7 @@ template<int n> void SuperFX::op_umult_r() {
|
|||
|
||||
//$80-8f(alt2): mult #N
|
||||
template<int n> void SuperFX::op_mult_i() {
|
||||
regs.dr() = (int8_t)regs.sr() * (int8_t)n;
|
||||
regs.dr() = (int8)regs.sr() * (int8)n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
|
@ -389,7 +389,7 @@ template<int n> void SuperFX::op_mult_i() {
|
|||
|
||||
//$80-8f(alt3): umult #N
|
||||
template<int n> void SuperFX::op_umult_i() {
|
||||
regs.dr() = (uint8_t)regs.sr() * (uint8_t)n;
|
||||
regs.dr() = (uint8)regs.sr() * (uint8)n;
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
|
@ -411,7 +411,7 @@ template<int n> void SuperFX::op_link() {
|
|||
|
||||
//$95: sex
|
||||
void SuperFX::op_sex() {
|
||||
regs.dr() = (int8_t)regs.sr();
|
||||
regs.dr() = (int8)regs.sr();
|
||||
regs.sfr.s = (regs.dr() & 0x8000);
|
||||
regs.sfr.z = (regs.dr() == 0);
|
||||
regs.reset();
|
||||
|
@ -493,7 +493,7 @@ void SuperFX::op_lmult() {
|
|||
|
||||
//$a0-af(alt0): ibt rN,#pp
|
||||
template<int n> void SuperFX::op_ibt_r() {
|
||||
regs.r[n] = (int8_t)pipe();
|
||||
regs.r[n] = (int8)pipe();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
@ -625,7 +625,7 @@ void SuperFX::op_getbl() {
|
|||
|
||||
//$ef(alt3): getbs
|
||||
void SuperFX::op_getbs() {
|
||||
regs.dr() = (int8_t)rombuffer_read();
|
||||
regs.dr() = (int8)rombuffer_read();
|
||||
regs.reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
|
||||
|
||||
//accepts a callback binding so r14 writes can trigger ROM buffering transparently
|
||||
struct reg16_t : noncopyable {
|
||||
uint16_t data;
|
||||
function<void (uint16_t)> on_modify;
|
||||
uint16 data;
|
||||
function<void (uint16)> on_modify;
|
||||
|
||||
inline operator unsigned() const { return data; }
|
||||
inline uint16_t assign(uint16_t i) {
|
||||
inline uint16 assign(uint16 i) {
|
||||
if(on_modify) on_modify(i);
|
||||
else data = i;
|
||||
return data;
|
||||
|
@ -47,7 +45,7 @@ struct sfr_t {
|
|||
bool cy; //carry flag
|
||||
bool z; //zero flag
|
||||
|
||||
operator uint16_t() const {
|
||||
operator unsigned() const {
|
||||
return (irq << 15) | (b << 12) | (ih << 11) | (il << 10) | (alt2 << 9) | (alt1 << 8)
|
||||
| (r << 6) | (g << 5) | (ov << 4) | (s << 3) | (cy << 2) | (z << 1);
|
||||
}
|
||||
|
@ -75,11 +73,11 @@ struct scmr_t {
|
|||
bool ran;
|
||||
unsigned md;
|
||||
|
||||
operator uint8_t() const {
|
||||
operator unsigned() const {
|
||||
return ((ht >> 1) << 5) | (ron << 4) | (ran << 3) | ((ht & 1) << 2) | (md);
|
||||
}
|
||||
|
||||
scmr_t& operator=(uint8_t data) {
|
||||
scmr_t& operator=(uint8 data) {
|
||||
ht = (bool)(data & 0x20) << 1;
|
||||
ht |= (bool)(data & 0x04) << 0;
|
||||
ron = data & 0x10;
|
||||
|
@ -96,11 +94,11 @@ struct por_t {
|
|||
bool dither;
|
||||
bool transparent;
|
||||
|
||||
operator uint8_t() const {
|
||||
operator unsigned() const {
|
||||
return (obj << 4) | (freezehigh << 3) | (highnibble << 2) | (dither << 1) | (transparent);
|
||||
}
|
||||
|
||||
por_t& operator=(uint8_t data) {
|
||||
por_t& operator=(uint8 data) {
|
||||
obj = data & 0x10;
|
||||
freezehigh = data & 0x08;
|
||||
highnibble = data & 0x04;
|
||||
|
@ -114,11 +112,11 @@ struct cfgr_t {
|
|||
bool irq;
|
||||
bool ms0;
|
||||
|
||||
operator uint8_t() const {
|
||||
operator unsigned() const {
|
||||
return (irq << 7) | (ms0 << 5);
|
||||
}
|
||||
|
||||
cfgr_t& operator=(uint8_t data) {
|
||||
cfgr_t& operator=(uint8 data) {
|
||||
irq = data & 0x80;
|
||||
ms0 = data & 0x20;
|
||||
return *this;
|
||||
|
@ -126,30 +124,30 @@ struct cfgr_t {
|
|||
};
|
||||
|
||||
struct regs_t {
|
||||
uint8_t pipeline;
|
||||
uint16_t ramaddr;
|
||||
uint8 pipeline;
|
||||
uint16 ramaddr;
|
||||
|
||||
reg16_t r[16]; //general purpose registers
|
||||
sfr_t sfr; //status flag register
|
||||
uint8_t pbr; //program bank register
|
||||
uint8_t rombr; //game pack ROM bank register
|
||||
uint8 pbr; //program bank register
|
||||
uint8 rombr; //game pack ROM bank register
|
||||
bool rambr; //game pack RAM bank register
|
||||
uint16_t cbr; //cache base register
|
||||
uint8_t scbr; //screen base register
|
||||
uint16 cbr; //cache base register
|
||||
uint8 scbr; //screen base register
|
||||
scmr_t scmr; //screen mode register
|
||||
uint8_t colr; //color register
|
||||
uint8 colr; //color register
|
||||
por_t por; //plot option register
|
||||
bool bramr; //back-up RAM register
|
||||
uint8_t vcr; //version code register
|
||||
uint8 vcr; //version code register
|
||||
cfgr_t cfgr; //config register
|
||||
bool clsr; //clock select register
|
||||
|
||||
unsigned romcl; //clock ticks until romdr is valid
|
||||
uint8_t romdr; //ROM buffer data register
|
||||
uint8 romdr; //ROM buffer data register
|
||||
|
||||
unsigned ramcl; //clock ticks until ramdr is valid
|
||||
uint16_t ramar; //RAM buffer address register
|
||||
uint8_t ramdr; //RAM buffer data register
|
||||
uint16 ramar; //RAM buffer address register
|
||||
uint8 ramdr; //RAM buffer data register
|
||||
|
||||
reg16_t *sreg, *dreg;
|
||||
reg16_t& sr() { return *sreg; } //source register (from)
|
||||
|
@ -166,12 +164,12 @@ struct regs_t {
|
|||
} regs;
|
||||
|
||||
struct cache_t {
|
||||
uint8_t buffer[512];
|
||||
uint8 buffer[512];
|
||||
bool valid[32];
|
||||
} cache;
|
||||
|
||||
struct pixelcache_t {
|
||||
uint16_t offset;
|
||||
uint8_t bitpend;
|
||||
uint8_t data[8];
|
||||
uint16 offset;
|
||||
uint8 bitpend;
|
||||
uint8 data[8];
|
||||
} pixelcache[2];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
uint8_t SuperFX::op_read(uint16_t addr) {
|
||||
uint16_t offset = addr - regs.cbr;
|
||||
uint8 SuperFX::op_read(uint16 addr) {
|
||||
uint16 offset = addr - regs.cbr;
|
||||
if(offset < 512) {
|
||||
if(cache.valid[offset >> 4] == false) {
|
||||
unsigned dp = offset & 0xfff0;
|
||||
|
@ -28,15 +28,15 @@ uint8_t SuperFX::op_read(uint16_t addr) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t SuperFX::peekpipe() {
|
||||
uint8_t result = regs.pipeline;
|
||||
uint8 SuperFX::peekpipe() {
|
||||
uint8 result = regs.pipeline;
|
||||
regs.pipeline = op_read(regs.r[15]);
|
||||
r15_modified = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::pipe() {
|
||||
uint8_t result = regs.pipeline;
|
||||
uint8 SuperFX::pipe() {
|
||||
uint8 result = regs.pipeline;
|
||||
regs.pipeline = op_read(++regs.r[15]);
|
||||
r15_modified = false;
|
||||
return result;
|
||||
|
@ -46,12 +46,12 @@ void SuperFX::cache_flush() {
|
|||
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::cache_mmio_read(uint16_t addr) {
|
||||
uint8 SuperFX::cache_mmio_read(uint16 addr) {
|
||||
addr = (addr + regs.cbr) & 511;
|
||||
return cache.buffer[addr];
|
||||
}
|
||||
|
||||
void SuperFX::cache_mmio_write(uint16_t addr, uint8_t data) {
|
||||
void SuperFX::cache_mmio_write(uint16 addr, uint8 data) {
|
||||
addr = (addr + regs.cbr) & 511;
|
||||
cache.buffer[addr] = data;
|
||||
if((addr & 15) == 15) cache.valid[addr >> 4] = true;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
uint8_t op_read(uint16_t addr);
|
||||
alwaysinline uint8_t peekpipe();
|
||||
alwaysinline uint8_t pipe();
|
||||
uint8 op_read(uint16 addr);
|
||||
alwaysinline uint8 peekpipe();
|
||||
alwaysinline uint8 pipe();
|
||||
|
||||
void cache_flush();
|
||||
uint8_t cache_mmio_read(uint16_t addr);
|
||||
void cache_mmio_write(uint16_t addr, uint8_t data);
|
||||
uint8 cache_mmio_read(uint16 addr);
|
||||
void cache_mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
void memory_reset();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifdef SUPERFX_CPP
|
||||
|
||||
uint8_t SuperFX::mmio_read(unsigned addr) {
|
||||
uint8 SuperFX::mmio_read(unsigned addr) {
|
||||
scheduler.sync_cpucop();
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
|
@ -17,7 +18,7 @@ uint8_t SuperFX::mmio_read(unsigned addr) {
|
|||
}
|
||||
|
||||
case 0x3031: {
|
||||
uint8_t r = regs.sfr >> 8;
|
||||
uint8 r = regs.sfr >> 8;
|
||||
regs.sfr.irq = 0;
|
||||
cpu.regs.irq = 0;
|
||||
return r;
|
||||
|
@ -51,7 +52,8 @@ uint8_t SuperFX::mmio_read(unsigned addr) {
|
|||
return 0x00;
|
||||
}
|
||||
|
||||
void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
||||
void SuperFX::mmio_write(unsigned addr, uint8 data) {
|
||||
scheduler.sync_cpucop();
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
|
@ -95,7 +97,7 @@ void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
|||
|
||||
case 0x3037: {
|
||||
regs.cfgr = data;
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
update_speed();
|
||||
} break;
|
||||
|
||||
case 0x3038: {
|
||||
|
@ -104,9 +106,7 @@ void SuperFX::mmio_write(unsigned addr, uint8_t data) {
|
|||
|
||||
case 0x3039: {
|
||||
regs.clsr = data;
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
cache_access_speed = (regs.clsr ? config.superfx.fast_cache_speed : config.superfx.slow_cache_speed );
|
||||
memory_access_speed = (regs.clsr ? config.superfx.fast_memory_speed : config.superfx.slow_memory_speed);
|
||||
update_speed();
|
||||
} break;
|
||||
|
||||
case 0x303a: {
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
uint8_t mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8_t data);
|
||||
uint8 mmio_read(unsigned addr);
|
||||
void mmio_write(unsigned addr, uint8 data);
|
||||
|
|
|
@ -14,8 +14,18 @@ SuperFX superfx;
|
|||
|
||||
void SuperFX::enter() {
|
||||
while(true) {
|
||||
while(regs.sfr.g == 0) add_clocks(2);
|
||||
exec_opcode();
|
||||
while(regs.sfr.g == 0) {
|
||||
add_clocks(6);
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
|
||||
(this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
|
||||
if(r15_modified == false) regs.r[15]++;
|
||||
|
||||
if(++instruction_counter >= 128) {
|
||||
instruction_counter = 0;
|
||||
scheduler.sync_copcpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,15 +36,17 @@ void SuperFX::init() {
|
|||
}
|
||||
|
||||
void SuperFX::enable() {
|
||||
for(uint16_t i = 0x3000; i <= 0x32ff; i++) memory::mmio.map(i, *this);
|
||||
for(unsigned i = 0x3000; i <= 0x32ff; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SuperFX::power() {
|
||||
clockmode = config.superfx.speed;
|
||||
reset();
|
||||
}
|
||||
|
||||
void SuperFX::reset() {
|
||||
superfxbus.init();
|
||||
instruction_counter = 0;
|
||||
|
||||
for(unsigned n = 0; n < 16; n++) regs.r[n] = 0x0000;
|
||||
regs.sfr = 0x0000;
|
||||
|
|
|
@ -14,6 +14,10 @@ public:
|
|||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
unsigned clockmode;
|
||||
unsigned instruction_counter;
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
||||
|
|
|
@ -27,7 +27,7 @@ void SuperFX::rombuffer_update() {
|
|||
regs.romcl = memory_access_speed;
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rombuffer_read() {
|
||||
uint8 SuperFX::rombuffer_read() {
|
||||
rombuffer_sync();
|
||||
return regs.romdr;
|
||||
}
|
||||
|
@ -36,31 +36,52 @@ void SuperFX::rambuffer_sync() {
|
|||
if(regs.ramcl) add_clocks(regs.ramcl);
|
||||
}
|
||||
|
||||
uint8_t SuperFX::rambuffer_read(uint16_t addr) {
|
||||
uint8 SuperFX::rambuffer_read(uint16 addr) {
|
||||
rambuffer_sync();
|
||||
return superfxbus.read(0x700000 + (regs.rambr << 16) + addr);
|
||||
}
|
||||
|
||||
void SuperFX::rambuffer_write(uint16_t addr, uint8_t data) {
|
||||
void SuperFX::rambuffer_write(uint16 addr, uint8 data) {
|
||||
rambuffer_sync();
|
||||
regs.ramcl = memory_access_speed;
|
||||
regs.ramar = addr;
|
||||
regs.ramdr = data;
|
||||
}
|
||||
|
||||
void SuperFX::r14_modify(uint16_t data) {
|
||||
void SuperFX::r14_modify(uint16 data) {
|
||||
regs.r[14].data = data;
|
||||
rombuffer_update();
|
||||
}
|
||||
|
||||
void SuperFX::r15_modify(uint16_t data) {
|
||||
void SuperFX::r15_modify(uint16 data) {
|
||||
regs.r[15].data = data;
|
||||
r15_modified = true;
|
||||
}
|
||||
|
||||
void SuperFX::update_speed() {
|
||||
//force SuperFX1 mode?
|
||||
if(clockmode == 1) {
|
||||
cache_access_speed = 2;
|
||||
memory_access_speed = 6;
|
||||
return;
|
||||
}
|
||||
|
||||
//force SuperFX2 mode?
|
||||
if(clockmode == 2) {
|
||||
cache_access_speed = 1;
|
||||
memory_access_speed = 5;
|
||||
regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
return;
|
||||
}
|
||||
|
||||
//default: allow S-CPU to select mode
|
||||
cache_access_speed = (regs.clsr ? 1 : 2);
|
||||
memory_access_speed = (regs.clsr ? 5 : 6);
|
||||
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
|
||||
}
|
||||
|
||||
void SuperFX::timing_reset() {
|
||||
cache_access_speed = config.superfx.slow_cache_speed;
|
||||
memory_access_speed = config.superfx.slow_memory_speed;
|
||||
update_speed();
|
||||
r15_modified = false;
|
||||
|
||||
regs.romcl = 0;
|
||||
|
|
|
@ -6,13 +6,14 @@ void add_clocks(unsigned clocks);
|
|||
|
||||
void rombuffer_sync();
|
||||
void rombuffer_update();
|
||||
uint8_t rombuffer_read();
|
||||
uint8 rombuffer_read();
|
||||
|
||||
void rambuffer_sync();
|
||||
uint8_t rambuffer_read(uint16_t addr);
|
||||
void rambuffer_write(uint16_t addr, uint8_t data);
|
||||
uint8 rambuffer_read(uint16 addr);
|
||||
void rambuffer_write(uint16 addr, uint8 data);
|
||||
|
||||
void r14_modify(uint16_t);
|
||||
void r15_modify(uint16_t);
|
||||
void r14_modify(uint16);
|
||||
void r15_modify(uint16);
|
||||
|
||||
void update_speed();
|
||||
void timing_reset();
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
clear
|
||||
bpp opcode_functions.cpp opcode_functions.bpp
|
||||
bpp opcode_headers.hpp opcode_headers.bpp
|
|
@ -3,11 +3,35 @@
|
|||
#define CPUCORE_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "opcode_algorithms.cpp"
|
||||
#include "opcode_functions.cpp"
|
||||
#include "opcode_tables.cpp"
|
||||
#include "serialization.cpp"
|
||||
#include "algorithms.cpp"
|
||||
#include "disasm/disasm.cpp"
|
||||
|
||||
#define L last_cycle();
|
||||
#define A 0
|
||||
#define X 1
|
||||
#define Y 2
|
||||
#define Z 3
|
||||
#define S 4
|
||||
#define D 5
|
||||
#define call(op) (this->*op)()
|
||||
|
||||
#include "opcode_read.cpp"
|
||||
#include "opcode_write.cpp"
|
||||
#include "opcode_rmw.cpp"
|
||||
#include "opcode_pc.cpp"
|
||||
#include "opcode_misc.cpp"
|
||||
#include "table.cpp"
|
||||
|
||||
#undef L
|
||||
#undef A
|
||||
#undef X
|
||||
#undef Y
|
||||
#undef Z
|
||||
#undef S
|
||||
#undef D
|
||||
#undef call
|
||||
|
||||
//immediate, 2-cycle opcodes with I/O cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion.
|
||||
//this affects the following opcodes:
|
||||
|
|
|
@ -2,7 +2,6 @@ class CPUcore {
|
|||
public:
|
||||
#include "registers.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "opcode_headers.hpp"
|
||||
#include "disasm/disasm.hpp"
|
||||
|
||||
regs_t regs;
|
||||
|
@ -62,6 +61,146 @@ public:
|
|||
void op_tsb_b();
|
||||
void op_tsb_w();
|
||||
|
||||
template<void (CPUcore::*)()> void op_read_const_b();
|
||||
template<void (CPUcore::*)()> void op_read_const_w();
|
||||
void op_read_bit_const_b();
|
||||
void op_read_bit_const_w();
|
||||
template<void (CPUcore::*)()> void op_read_addr_b();
|
||||
template<void (CPUcore::*)()> void op_read_addr_w();
|
||||
template<void (CPUcore::*)()> void op_read_addrx_b();
|
||||
template<void (CPUcore::*)()> void op_read_addrx_w();
|
||||
template<void (CPUcore::*)()> void op_read_addry_b();
|
||||
template<void (CPUcore::*)()> void op_read_addry_w();
|
||||
template<void (CPUcore::*)()> void op_read_long_b();
|
||||
template<void (CPUcore::*)()> void op_read_long_w();
|
||||
template<void (CPUcore::*)()> void op_read_longx_b();
|
||||
template<void (CPUcore::*)()> void op_read_longx_w();
|
||||
template<void (CPUcore::*)()> void op_read_dp_b();
|
||||
template<void (CPUcore::*)()> void op_read_dp_w();
|
||||
template<void (CPUcore::*)(), int> void op_read_dpr_b();
|
||||
template<void (CPUcore::*)(), int> void op_read_dpr_w();
|
||||
template<void (CPUcore::*)()> void op_read_idp_b();
|
||||
template<void (CPUcore::*)()> void op_read_idp_w();
|
||||
template<void (CPUcore::*)()> void op_read_idpx_b();
|
||||
template<void (CPUcore::*)()> void op_read_idpx_w();
|
||||
template<void (CPUcore::*)()> void op_read_idpy_b();
|
||||
template<void (CPUcore::*)()> void op_read_idpy_w();
|
||||
template<void (CPUcore::*)()> void op_read_ildp_b();
|
||||
template<void (CPUcore::*)()> void op_read_ildp_w();
|
||||
template<void (CPUcore::*)()> void op_read_ildpy_b();
|
||||
template<void (CPUcore::*)()> void op_read_ildpy_w();
|
||||
template<void (CPUcore::*)()> void op_read_sr_b();
|
||||
template<void (CPUcore::*)()> void op_read_sr_w();
|
||||
template<void (CPUcore::*)()> void op_read_isry_b();
|
||||
template<void (CPUcore::*)()> void op_read_isry_w();
|
||||
|
||||
template<int> void op_write_addr_b();
|
||||
template<int> void op_write_addr_w();
|
||||
template<int, int> void op_write_addrr_b();
|
||||
template<int, int> void op_write_addrr_w();
|
||||
template<int> void op_write_longr_b();
|
||||
template<int> void op_write_longr_w();
|
||||
template<int> void op_write_dp_b();
|
||||
template<int> void op_write_dp_w();
|
||||
template<int, int> void op_write_dpr_b();
|
||||
template<int, int> void op_write_dpr_w();
|
||||
void op_sta_idp_b();
|
||||
void op_sta_idp_w();
|
||||
void op_sta_ildp_b();
|
||||
void op_sta_ildp_w();
|
||||
void op_sta_idpx_b();
|
||||
void op_sta_idpx_w();
|
||||
void op_sta_idpy_b();
|
||||
void op_sta_idpy_w();
|
||||
void op_sta_ildpy_b();
|
||||
void op_sta_ildpy_w();
|
||||
void op_sta_sr_b();
|
||||
void op_sta_sr_w();
|
||||
void op_sta_isry_b();
|
||||
void op_sta_isry_w();
|
||||
|
||||
template<int, int> void op_adjust_imm_b();
|
||||
template<int, int> void op_adjust_imm_w();
|
||||
void op_asl_imm_b();
|
||||
void op_asl_imm_w();
|
||||
void op_lsr_imm_b();
|
||||
void op_lsr_imm_w();
|
||||
void op_rol_imm_b();
|
||||
void op_rol_imm_w();
|
||||
void op_ror_imm_b();
|
||||
void op_ror_imm_w();
|
||||
template<void (CPUcore::*)()> void op_adjust_addr_b();
|
||||
template<void (CPUcore::*)()> void op_adjust_addr_w();
|
||||
template<void (CPUcore::*)()> void op_adjust_addrx_b();
|
||||
template<void (CPUcore::*)()> void op_adjust_addrx_w();
|
||||
template<void (CPUcore::*)()> void op_adjust_dp_b();
|
||||
template<void (CPUcore::*)()> void op_adjust_dp_w();
|
||||
template<void (CPUcore::*)()> void op_adjust_dpx_b();
|
||||
template<void (CPUcore::*)()> void op_adjust_dpx_w();
|
||||
|
||||
template<int, int> void op_branch();
|
||||
void op_bra();
|
||||
void op_brl();
|
||||
void op_jmp_addr();
|
||||
void op_jmp_long();
|
||||
void op_jmp_iaddr();
|
||||
void op_jmp_iaddrx();
|
||||
void op_jmp_iladdr();
|
||||
void op_jsr_addr();
|
||||
void op_jsr_long_e();
|
||||
void op_jsr_long_n();
|
||||
void op_jsr_iaddrx_e();
|
||||
void op_jsr_iaddrx_n();
|
||||
void op_rti_e();
|
||||
void op_rti_n();
|
||||
void op_rts();
|
||||
void op_rtl_e();
|
||||
void op_rtl_n();
|
||||
|
||||
void op_nop();
|
||||
void op_wdm();
|
||||
void op_xba();
|
||||
template<int> void op_move_b();
|
||||
template<int> void op_move_w();
|
||||
template<int, int> void op_interrupt_e();
|
||||
template<int, int> void op_interrupt_n();
|
||||
void op_stp();
|
||||
void op_wai();
|
||||
void op_xce();
|
||||
template<int, int> void op_flag();
|
||||
template<int> void op_pflag_e();
|
||||
template<int> void op_pflag_n();
|
||||
template<int, int> void op_transfer_b();
|
||||
template<int, int> void op_transfer_w();
|
||||
void op_tcs_e();
|
||||
void op_tcs_n();
|
||||
void op_tsc_e();
|
||||
void op_tsc_n();
|
||||
void op_tsx_b();
|
||||
void op_tsx_w();
|
||||
void op_txs_e();
|
||||
void op_txs_n();
|
||||
template<int> void op_push_b();
|
||||
template<int> void op_push_w();
|
||||
void op_phd_e();
|
||||
void op_phd_n();
|
||||
void op_phb();
|
||||
void op_phk();
|
||||
void op_php();
|
||||
template<int> void op_pull_b();
|
||||
template<int> void op_pull_w();
|
||||
void op_pld_e();
|
||||
void op_pld_n();
|
||||
void op_plb();
|
||||
void op_plp_e();
|
||||
void op_plp_n();
|
||||
void op_pea_e();
|
||||
void op_pea_n();
|
||||
void op_pei_e();
|
||||
void op_pei_n();
|
||||
void op_per_e();
|
||||
void op_per_n();
|
||||
|
||||
void (CPUcore::**opcode_table)();
|
||||
void (CPUcore::*op_table[256 * 5])();
|
||||
void initialize_opcode_table();
|
||||
|
@ -75,5 +214,6 @@ public:
|
|||
table_mx = 1024, //16-bit accumulator, 16-bit index
|
||||
};
|
||||
|
||||
void core_serialize(serializer&);
|
||||
CPUcore();
|
||||
};
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
//opcode_functions.cpp was generated via bpp -> opcode_functions.bpp
|
||||
|
||||
@global class CPUcore
|
||||
@global lc last_cycle();
|
||||
@global wai regs.wai
|
||||
|
||||
@include "opcode_read.bpp"
|
||||
@include "opcode_write.bpp"
|
||||
@include "opcode_rmw.bpp"
|
||||
@include "opcode_pc.bpp"
|
||||
@include "opcode_misc.bpp"
|
||||
|
||||
@include "opcode_list.bpp"
|
File diff suppressed because it is too large
Load Diff
|
@ -1,386 +0,0 @@
|
|||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
@macro op_read_const(name)
|
||||
void op_{name}_const_b();
|
||||
void op_{name}_const_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_bit_const()
|
||||
void op_bit_const_b();
|
||||
void op_bit_const_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addr(name)
|
||||
void op_{name}_addr_b();
|
||||
void op_{name}_addr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addrx(name)
|
||||
void op_{name}_addrx_b();
|
||||
void op_{name}_addrx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addry(name)
|
||||
void op_{name}_addry_b();
|
||||
void op_{name}_addry_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_long(name)
|
||||
void op_{name}_long_b();
|
||||
void op_{name}_long_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_longx(name)
|
||||
void op_{name}_longx_b();
|
||||
void op_{name}_longx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dp(name)
|
||||
void op_{name}_dp_b();
|
||||
void op_{name}_dp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dpr(name, r)
|
||||
void op_{name}_dpr_b();
|
||||
void op_{name}_dpr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idp(name)
|
||||
void op_{name}_idp_b();
|
||||
void op_{name}_idp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpx(name)
|
||||
void op_{name}_idpx_b();
|
||||
void op_{name}_idpx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpy(name)
|
||||
void op_{name}_idpy_b();
|
||||
void op_{name}_idpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildp(name)
|
||||
void op_{name}_ildp_b();
|
||||
void op_{name}_ildp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildpy(name)
|
||||
void op_{name}_ildpy_b();
|
||||
void op_{name}_ildpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_sr(name)
|
||||
void op_{name}_sr_b();
|
||||
void op_{name}_sr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_read_isry(name)
|
||||
void op_{name}_isry_b();
|
||||
void op_{name}_isry_w();
|
||||
@endmacro
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
@macro op_store_addr(name, r)
|
||||
void op_{name}_addr_b();
|
||||
void op_{name}_addr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_addrr(name, suffix, r, index)
|
||||
void op_{name}_addr{suffix}_b();
|
||||
void op_{name}_addr{suffix}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_longr(name, suffix, index)
|
||||
void op_{name}_long{suffix}_b();
|
||||
void op_{name}_long{suffix}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dp(name, r)
|
||||
void op_{name}_dp_b();
|
||||
void op_{name}_dp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dpr(name, r, index)
|
||||
void op_{name}_dpr_b();
|
||||
void op_{name}_dpr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idp()
|
||||
void op_sta_idp_b();
|
||||
void op_sta_idp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildp()
|
||||
void op_sta_ildp_b();
|
||||
void op_sta_ildp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpx()
|
||||
void op_sta_idpx_b();
|
||||
void op_sta_idpx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpy()
|
||||
void op_sta_idpy_b();
|
||||
void op_sta_idpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildpy()
|
||||
void op_sta_ildpy_b();
|
||||
void op_sta_ildpy_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_sr()
|
||||
void op_sta_sr_b();
|
||||
void op_sta_sr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_isry()
|
||||
void op_sta_isry_b();
|
||||
void op_sta_isry_w();
|
||||
@endmacro
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
@macro op_adjust(name, r, op)
|
||||
void op_{name}_imm_b();
|
||||
void op_{name}_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_asl()
|
||||
void op_asl_imm_b();
|
||||
void op_asl_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_lsr()
|
||||
void op_lsr_imm_b();
|
||||
void op_lsr_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_rol()
|
||||
void op_rol_imm_b();
|
||||
void op_rol_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_ror()
|
||||
void op_ror_imm_b();
|
||||
void op_ror_imm_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addr(name)
|
||||
void op_{name}_addr_b();
|
||||
void op_{name}_addr_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addrx(name)
|
||||
void op_{name}_addrx_b();
|
||||
void op_{name}_addrx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dp(name)
|
||||
void op_{name}_dp_b();
|
||||
void op_{name}_dp_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dpx(name)
|
||||
void op_{name}_dpx_b();
|
||||
void op_{name}_dpx_w();
|
||||
@endmacro
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
@macro op_branch(name, condition)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_bra()
|
||||
void op_bra();
|
||||
@endmacro
|
||||
|
||||
@macro op_brl()
|
||||
void op_brl();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_addr()
|
||||
void op_jmp_addr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_long()
|
||||
void op_jmp_long();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddr()
|
||||
void op_jmp_iaddr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddrx()
|
||||
void op_jmp_iaddrx();
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iladdr()
|
||||
void op_jmp_iladdr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_addr()
|
||||
void op_jsr_addr();
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_long()
|
||||
void op_jsr_long_e();
|
||||
void op_jsr_long_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_iaddrx()
|
||||
void op_jsr_iaddrx_e();
|
||||
void op_jsr_iaddrx_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_rti()
|
||||
void op_rti_e();
|
||||
void op_rti_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_rts()
|
||||
void op_rts();
|
||||
@endmacro
|
||||
|
||||
@macro op_rtl()
|
||||
void op_rtl_e();
|
||||
void op_rtl_n();
|
||||
@endmacro
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
@macro op_nop()
|
||||
void op_nop();
|
||||
@endmacro
|
||||
|
||||
@macro op_wdm()
|
||||
void op_wdm();
|
||||
@endmacro
|
||||
|
||||
@macro op_xba()
|
||||
void op_xba();
|
||||
@endmacro
|
||||
|
||||
@macro op_move(name, op)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_interrupt(name, vectorE, vectorN)
|
||||
void op_{name}_e();
|
||||
void op_{name}_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_stp()
|
||||
void op_stp();
|
||||
@endmacro
|
||||
|
||||
@macro op_wai()
|
||||
void op_wai();
|
||||
@endmacro
|
||||
|
||||
@macro op_xce()
|
||||
void op_xce();
|
||||
@endmacro
|
||||
|
||||
@macro op_flag(name, rule)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_pflag(name, op)
|
||||
void op_{name}_e();
|
||||
void op_{name}_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer(name, from, to)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer_word(name, from, to)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_tcs()
|
||||
void op_tcs_e();
|
||||
void op_tcs_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_tsc()
|
||||
void op_tsc_e();
|
||||
void op_tsc_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_tsx()
|
||||
void op_tsx_b();
|
||||
void op_tsx_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_txs()
|
||||
void op_txs_e();
|
||||
void op_txs_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_push(name, r)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_phd()
|
||||
void op_phd_e();
|
||||
void op_phd_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_push_byte(name, r)
|
||||
void op_{name}();
|
||||
@endmacro
|
||||
|
||||
@macro op_pull(name, r)
|
||||
void op_{name}_b();
|
||||
void op_{name}_w();
|
||||
@endmacro
|
||||
|
||||
@macro op_pld()
|
||||
void op_pld_e();
|
||||
void op_pld_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_plb()
|
||||
void op_plb();
|
||||
@endmacro
|
||||
|
||||
@macro op_plp()
|
||||
void op_plp_e();
|
||||
void op_plp_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_pea()
|
||||
void op_pea_e();
|
||||
void op_pea_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_pei()
|
||||
void op_pei_e();
|
||||
void op_pei_n();
|
||||
@endmacro
|
||||
|
||||
@macro op_per()
|
||||
void op_per_e();
|
||||
void op_per_n();
|
||||
@endmacro
|
||||
|
||||
@include "opcode_list.bpp"
|
|
@ -1,892 +0,0 @@
|
|||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
void op_adc_const_b();
|
||||
void op_adc_const_w();
|
||||
|
||||
void op_and_const_b();
|
||||
void op_and_const_w();
|
||||
|
||||
void op_cmp_const_b();
|
||||
void op_cmp_const_w();
|
||||
|
||||
void op_cpx_const_b();
|
||||
void op_cpx_const_w();
|
||||
|
||||
void op_cpy_const_b();
|
||||
void op_cpy_const_w();
|
||||
|
||||
void op_eor_const_b();
|
||||
void op_eor_const_w();
|
||||
|
||||
void op_lda_const_b();
|
||||
void op_lda_const_w();
|
||||
|
||||
void op_ldx_const_b();
|
||||
void op_ldx_const_w();
|
||||
|
||||
void op_ldy_const_b();
|
||||
void op_ldy_const_w();
|
||||
|
||||
void op_ora_const_b();
|
||||
void op_ora_const_w();
|
||||
|
||||
void op_sbc_const_b();
|
||||
void op_sbc_const_w();
|
||||
|
||||
|
||||
void op_bit_const_b();
|
||||
void op_bit_const_w();
|
||||
|
||||
|
||||
void op_adc_addr_b();
|
||||
void op_adc_addr_w();
|
||||
|
||||
void op_and_addr_b();
|
||||
void op_and_addr_w();
|
||||
|
||||
void op_bit_addr_b();
|
||||
void op_bit_addr_w();
|
||||
|
||||
void op_cmp_addr_b();
|
||||
void op_cmp_addr_w();
|
||||
|
||||
void op_cpx_addr_b();
|
||||
void op_cpx_addr_w();
|
||||
|
||||
void op_cpy_addr_b();
|
||||
void op_cpy_addr_w();
|
||||
|
||||
void op_eor_addr_b();
|
||||
void op_eor_addr_w();
|
||||
|
||||
void op_lda_addr_b();
|
||||
void op_lda_addr_w();
|
||||
|
||||
void op_ldx_addr_b();
|
||||
void op_ldx_addr_w();
|
||||
|
||||
void op_ldy_addr_b();
|
||||
void op_ldy_addr_w();
|
||||
|
||||
void op_ora_addr_b();
|
||||
void op_ora_addr_w();
|
||||
|
||||
void op_sbc_addr_b();
|
||||
void op_sbc_addr_w();
|
||||
|
||||
|
||||
void op_adc_addrx_b();
|
||||
void op_adc_addrx_w();
|
||||
|
||||
void op_and_addrx_b();
|
||||
void op_and_addrx_w();
|
||||
|
||||
void op_bit_addrx_b();
|
||||
void op_bit_addrx_w();
|
||||
|
||||
void op_cmp_addrx_b();
|
||||
void op_cmp_addrx_w();
|
||||
|
||||
void op_eor_addrx_b();
|
||||
void op_eor_addrx_w();
|
||||
|
||||
void op_lda_addrx_b();
|
||||
void op_lda_addrx_w();
|
||||
|
||||
void op_ldy_addrx_b();
|
||||
void op_ldy_addrx_w();
|
||||
|
||||
void op_ora_addrx_b();
|
||||
void op_ora_addrx_w();
|
||||
|
||||
void op_sbc_addrx_b();
|
||||
void op_sbc_addrx_w();
|
||||
|
||||
|
||||
void op_adc_addry_b();
|
||||
void op_adc_addry_w();
|
||||
|
||||
void op_and_addry_b();
|
||||
void op_and_addry_w();
|
||||
|
||||
void op_cmp_addry_b();
|
||||
void op_cmp_addry_w();
|
||||
|
||||
void op_eor_addry_b();
|
||||
void op_eor_addry_w();
|
||||
|
||||
void op_lda_addry_b();
|
||||
void op_lda_addry_w();
|
||||
|
||||
void op_ldx_addry_b();
|
||||
void op_ldx_addry_w();
|
||||
|
||||
void op_ora_addry_b();
|
||||
void op_ora_addry_w();
|
||||
|
||||
void op_sbc_addry_b();
|
||||
void op_sbc_addry_w();
|
||||
|
||||
|
||||
void op_adc_long_b();
|
||||
void op_adc_long_w();
|
||||
|
||||
void op_and_long_b();
|
||||
void op_and_long_w();
|
||||
|
||||
void op_cmp_long_b();
|
||||
void op_cmp_long_w();
|
||||
|
||||
void op_eor_long_b();
|
||||
void op_eor_long_w();
|
||||
|
||||
void op_lda_long_b();
|
||||
void op_lda_long_w();
|
||||
|
||||
void op_ora_long_b();
|
||||
void op_ora_long_w();
|
||||
|
||||
void op_sbc_long_b();
|
||||
void op_sbc_long_w();
|
||||
|
||||
|
||||
void op_adc_longx_b();
|
||||
void op_adc_longx_w();
|
||||
|
||||
void op_and_longx_b();
|
||||
void op_and_longx_w();
|
||||
|
||||
void op_cmp_longx_b();
|
||||
void op_cmp_longx_w();
|
||||
|
||||
void op_eor_longx_b();
|
||||
void op_eor_longx_w();
|
||||
|
||||
void op_lda_longx_b();
|
||||
void op_lda_longx_w();
|
||||
|
||||
void op_ora_longx_b();
|
||||
void op_ora_longx_w();
|
||||
|
||||
void op_sbc_longx_b();
|
||||
void op_sbc_longx_w();
|
||||
|
||||
|
||||
void op_adc_dp_b();
|
||||
void op_adc_dp_w();
|
||||
|
||||
void op_and_dp_b();
|
||||
void op_and_dp_w();
|
||||
|
||||
void op_bit_dp_b();
|
||||
void op_bit_dp_w();
|
||||
|
||||
void op_cmp_dp_b();
|
||||
void op_cmp_dp_w();
|
||||
|
||||
void op_cpx_dp_b();
|
||||
void op_cpx_dp_w();
|
||||
|
||||
void op_cpy_dp_b();
|
||||
void op_cpy_dp_w();
|
||||
|
||||
void op_eor_dp_b();
|
||||
void op_eor_dp_w();
|
||||
|
||||
void op_lda_dp_b();
|
||||
void op_lda_dp_w();
|
||||
|
||||
void op_ldx_dp_b();
|
||||
void op_ldx_dp_w();
|
||||
|
||||
void op_ldy_dp_b();
|
||||
void op_ldy_dp_w();
|
||||
|
||||
void op_ora_dp_b();
|
||||
void op_ora_dp_w();
|
||||
|
||||
void op_sbc_dp_b();
|
||||
void op_sbc_dp_w();
|
||||
|
||||
|
||||
void op_adc_dpr_b();
|
||||
void op_adc_dpr_w();
|
||||
|
||||
void op_and_dpr_b();
|
||||
void op_and_dpr_w();
|
||||
|
||||
void op_bit_dpr_b();
|
||||
void op_bit_dpr_w();
|
||||
|
||||
void op_cmp_dpr_b();
|
||||
void op_cmp_dpr_w();
|
||||
|
||||
void op_eor_dpr_b();
|
||||
void op_eor_dpr_w();
|
||||
|
||||
void op_lda_dpr_b();
|
||||
void op_lda_dpr_w();
|
||||
|
||||
void op_ldx_dpr_b();
|
||||
void op_ldx_dpr_w();
|
||||
|
||||
void op_ldy_dpr_b();
|
||||
void op_ldy_dpr_w();
|
||||
|
||||
void op_ora_dpr_b();
|
||||
void op_ora_dpr_w();
|
||||
|
||||
void op_sbc_dpr_b();
|
||||
void op_sbc_dpr_w();
|
||||
|
||||
|
||||
void op_adc_idp_b();
|
||||
void op_adc_idp_w();
|
||||
|
||||
void op_and_idp_b();
|
||||
void op_and_idp_w();
|
||||
|
||||
void op_cmp_idp_b();
|
||||
void op_cmp_idp_w();
|
||||
|
||||
void op_eor_idp_b();
|
||||
void op_eor_idp_w();
|
||||
|
||||
void op_lda_idp_b();
|
||||
void op_lda_idp_w();
|
||||
|
||||
void op_ora_idp_b();
|
||||
void op_ora_idp_w();
|
||||
|
||||
void op_sbc_idp_b();
|
||||
void op_sbc_idp_w();
|
||||
|
||||
|
||||
void op_adc_idpx_b();
|
||||
void op_adc_idpx_w();
|
||||
|
||||
void op_and_idpx_b();
|
||||
void op_and_idpx_w();
|
||||
|
||||
void op_cmp_idpx_b();
|
||||
void op_cmp_idpx_w();
|
||||
|
||||
void op_eor_idpx_b();
|
||||
void op_eor_idpx_w();
|
||||
|
||||
void op_lda_idpx_b();
|
||||
void op_lda_idpx_w();
|
||||
|
||||
void op_ora_idpx_b();
|
||||
void op_ora_idpx_w();
|
||||
|
||||
void op_sbc_idpx_b();
|
||||
void op_sbc_idpx_w();
|
||||
|
||||
|
||||
void op_adc_idpy_b();
|
||||
void op_adc_idpy_w();
|
||||
|
||||
void op_and_idpy_b();
|
||||
void op_and_idpy_w();
|
||||
|
||||
void op_cmp_idpy_b();
|
||||
void op_cmp_idpy_w();
|
||||
|
||||
void op_eor_idpy_b();
|
||||
void op_eor_idpy_w();
|
||||
|
||||
void op_lda_idpy_b();
|
||||
void op_lda_idpy_w();
|
||||
|
||||
void op_ora_idpy_b();
|
||||
void op_ora_idpy_w();
|
||||
|
||||
void op_sbc_idpy_b();
|
||||
void op_sbc_idpy_w();
|
||||
|
||||
|
||||
void op_adc_ildp_b();
|
||||
void op_adc_ildp_w();
|
||||
|
||||
void op_and_ildp_b();
|
||||
void op_and_ildp_w();
|
||||
|
||||
void op_cmp_ildp_b();
|
||||
void op_cmp_ildp_w();
|
||||
|
||||
void op_eor_ildp_b();
|
||||
void op_eor_ildp_w();
|
||||
|
||||
void op_lda_ildp_b();
|
||||
void op_lda_ildp_w();
|
||||
|
||||
void op_ora_ildp_b();
|
||||
void op_ora_ildp_w();
|
||||
|
||||
void op_sbc_ildp_b();
|
||||
void op_sbc_ildp_w();
|
||||
|
||||
|
||||
void op_adc_ildpy_b();
|
||||
void op_adc_ildpy_w();
|
||||
|
||||
void op_and_ildpy_b();
|
||||
void op_and_ildpy_w();
|
||||
|
||||
void op_cmp_ildpy_b();
|
||||
void op_cmp_ildpy_w();
|
||||
|
||||
void op_eor_ildpy_b();
|
||||
void op_eor_ildpy_w();
|
||||
|
||||
void op_lda_ildpy_b();
|
||||
void op_lda_ildpy_w();
|
||||
|
||||
void op_ora_ildpy_b();
|
||||
void op_ora_ildpy_w();
|
||||
|
||||
void op_sbc_ildpy_b();
|
||||
void op_sbc_ildpy_w();
|
||||
|
||||
|
||||
void op_adc_sr_b();
|
||||
void op_adc_sr_w();
|
||||
|
||||
void op_and_sr_b();
|
||||
void op_and_sr_w();
|
||||
|
||||
void op_cmp_sr_b();
|
||||
void op_cmp_sr_w();
|
||||
|
||||
void op_eor_sr_b();
|
||||
void op_eor_sr_w();
|
||||
|
||||
void op_lda_sr_b();
|
||||
void op_lda_sr_w();
|
||||
|
||||
void op_ora_sr_b();
|
||||
void op_ora_sr_w();
|
||||
|
||||
void op_sbc_sr_b();
|
||||
void op_sbc_sr_w();
|
||||
|
||||
|
||||
void op_adc_isry_b();
|
||||
void op_adc_isry_w();
|
||||
|
||||
void op_and_isry_b();
|
||||
void op_and_isry_w();
|
||||
|
||||
void op_cmp_isry_b();
|
||||
void op_cmp_isry_w();
|
||||
|
||||
void op_eor_isry_b();
|
||||
void op_eor_isry_w();
|
||||
|
||||
void op_lda_isry_b();
|
||||
void op_lda_isry_w();
|
||||
|
||||
void op_ora_isry_b();
|
||||
void op_ora_isry_w();
|
||||
|
||||
void op_sbc_isry_b();
|
||||
void op_sbc_isry_w();
|
||||
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
void op_sta_addr_b();
|
||||
void op_sta_addr_w();
|
||||
|
||||
void op_stx_addr_b();
|
||||
void op_stx_addr_w();
|
||||
|
||||
void op_sty_addr_b();
|
||||
void op_sty_addr_w();
|
||||
|
||||
void op_stz_addr_b();
|
||||
void op_stz_addr_w();
|
||||
|
||||
|
||||
void op_sta_addrx_b();
|
||||
void op_sta_addrx_w();
|
||||
|
||||
void op_sta_addry_b();
|
||||
void op_sta_addry_w();
|
||||
|
||||
void op_stz_addrx_b();
|
||||
void op_stz_addrx_w();
|
||||
|
||||
|
||||
void op_sta_long_b();
|
||||
void op_sta_long_w();
|
||||
|
||||
void op_sta_longx_b();
|
||||
void op_sta_longx_w();
|
||||
|
||||
|
||||
void op_sta_dp_b();
|
||||
void op_sta_dp_w();
|
||||
|
||||
void op_stx_dp_b();
|
||||
void op_stx_dp_w();
|
||||
|
||||
void op_sty_dp_b();
|
||||
void op_sty_dp_w();
|
||||
|
||||
void op_stz_dp_b();
|
||||
void op_stz_dp_w();
|
||||
|
||||
|
||||
void op_sta_dpr_b();
|
||||
void op_sta_dpr_w();
|
||||
|
||||
void op_stx_dpr_b();
|
||||
void op_stx_dpr_w();
|
||||
|
||||
void op_sty_dpr_b();
|
||||
void op_sty_dpr_w();
|
||||
|
||||
void op_stz_dpr_b();
|
||||
void op_stz_dpr_w();
|
||||
|
||||
|
||||
void op_sta_idp_b();
|
||||
void op_sta_idp_w();
|
||||
|
||||
void op_sta_ildp_b();
|
||||
void op_sta_ildp_w();
|
||||
|
||||
void op_sta_idpx_b();
|
||||
void op_sta_idpx_w();
|
||||
|
||||
void op_sta_idpy_b();
|
||||
void op_sta_idpy_w();
|
||||
|
||||
void op_sta_ildpy_b();
|
||||
void op_sta_ildpy_w();
|
||||
|
||||
void op_sta_sr_b();
|
||||
void op_sta_sr_w();
|
||||
|
||||
void op_sta_isry_b();
|
||||
void op_sta_isry_w();
|
||||
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
void op_inc_imm_b();
|
||||
void op_inc_imm_w();
|
||||
|
||||
void op_inx_imm_b();
|
||||
void op_inx_imm_w();
|
||||
|
||||
void op_iny_imm_b();
|
||||
void op_iny_imm_w();
|
||||
|
||||
void op_dec_imm_b();
|
||||
void op_dec_imm_w();
|
||||
|
||||
void op_dex_imm_b();
|
||||
void op_dex_imm_w();
|
||||
|
||||
void op_dey_imm_b();
|
||||
void op_dey_imm_w();
|
||||
|
||||
|
||||
void op_asl_imm_b();
|
||||
void op_asl_imm_w();
|
||||
|
||||
void op_lsr_imm_b();
|
||||
void op_lsr_imm_w();
|
||||
|
||||
void op_rol_imm_b();
|
||||
void op_rol_imm_w();
|
||||
|
||||
void op_ror_imm_b();
|
||||
void op_ror_imm_w();
|
||||
|
||||
|
||||
void op_inc_addr_b();
|
||||
void op_inc_addr_w();
|
||||
|
||||
void op_dec_addr_b();
|
||||
void op_dec_addr_w();
|
||||
|
||||
void op_asl_addr_b();
|
||||
void op_asl_addr_w();
|
||||
|
||||
void op_lsr_addr_b();
|
||||
void op_lsr_addr_w();
|
||||
|
||||
void op_rol_addr_b();
|
||||
void op_rol_addr_w();
|
||||
|
||||
void op_ror_addr_b();
|
||||
void op_ror_addr_w();
|
||||
|
||||
void op_trb_addr_b();
|
||||
void op_trb_addr_w();
|
||||
|
||||
void op_tsb_addr_b();
|
||||
void op_tsb_addr_w();
|
||||
|
||||
|
||||
void op_inc_addrx_b();
|
||||
void op_inc_addrx_w();
|
||||
|
||||
void op_dec_addrx_b();
|
||||
void op_dec_addrx_w();
|
||||
|
||||
void op_asl_addrx_b();
|
||||
void op_asl_addrx_w();
|
||||
|
||||
void op_lsr_addrx_b();
|
||||
void op_lsr_addrx_w();
|
||||
|
||||
void op_rol_addrx_b();
|
||||
void op_rol_addrx_w();
|
||||
|
||||
void op_ror_addrx_b();
|
||||
void op_ror_addrx_w();
|
||||
|
||||
|
||||
void op_inc_dp_b();
|
||||
void op_inc_dp_w();
|
||||
|
||||
void op_dec_dp_b();
|
||||
void op_dec_dp_w();
|
||||
|
||||
void op_asl_dp_b();
|
||||
void op_asl_dp_w();
|
||||
|
||||
void op_lsr_dp_b();
|
||||
void op_lsr_dp_w();
|
||||
|
||||
void op_rol_dp_b();
|
||||
void op_rol_dp_w();
|
||||
|
||||
void op_ror_dp_b();
|
||||
void op_ror_dp_w();
|
||||
|
||||
void op_trb_dp_b();
|
||||
void op_trb_dp_w();
|
||||
|
||||
void op_tsb_dp_b();
|
||||
void op_tsb_dp_w();
|
||||
|
||||
|
||||
void op_inc_dpx_b();
|
||||
void op_inc_dpx_w();
|
||||
|
||||
void op_dec_dpx_b();
|
||||
void op_dec_dpx_w();
|
||||
|
||||
void op_asl_dpx_b();
|
||||
void op_asl_dpx_w();
|
||||
|
||||
void op_lsr_dpx_b();
|
||||
void op_lsr_dpx_w();
|
||||
|
||||
void op_rol_dpx_b();
|
||||
void op_rol_dpx_w();
|
||||
|
||||
void op_ror_dpx_b();
|
||||
void op_ror_dpx_w();
|
||||
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
void op_bcc();
|
||||
|
||||
void op_bcs();
|
||||
|
||||
void op_bne();
|
||||
|
||||
void op_beq();
|
||||
|
||||
void op_bpl();
|
||||
|
||||
void op_bmi();
|
||||
|
||||
void op_bvc();
|
||||
|
||||
void op_bvs();
|
||||
|
||||
|
||||
void op_bra();
|
||||
|
||||
void op_brl();
|
||||
|
||||
void op_jmp_addr();
|
||||
|
||||
void op_jmp_long();
|
||||
|
||||
void op_jmp_iaddr();
|
||||
|
||||
void op_jmp_iaddrx();
|
||||
|
||||
void op_jmp_iladdr();
|
||||
|
||||
void op_jsr_addr();
|
||||
|
||||
void op_jsr_long_e();
|
||||
void op_jsr_long_n();
|
||||
|
||||
void op_jsr_iaddrx_e();
|
||||
void op_jsr_iaddrx_n();
|
||||
|
||||
void op_rti_e();
|
||||
void op_rti_n();
|
||||
|
||||
void op_rts();
|
||||
|
||||
void op_rtl_e();
|
||||
void op_rtl_n();
|
||||
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
void op_nop();
|
||||
|
||||
void op_wdm();
|
||||
|
||||
void op_xba();
|
||||
|
||||
|
||||
void op_mvn_b();
|
||||
void op_mvn_w();
|
||||
|
||||
void op_mvp_b();
|
||||
void op_mvp_w();
|
||||
|
||||
|
||||
void op_brk_e();
|
||||
void op_brk_n();
|
||||
|
||||
void op_cop_e();
|
||||
void op_cop_n();
|
||||
|
||||
|
||||
void op_stp();
|
||||
|
||||
void op_wai();
|
||||
|
||||
void op_xce();
|
||||
|
||||
|
||||
void op_clc();
|
||||
|
||||
void op_cld();
|
||||
|
||||
void op_cli();
|
||||
|
||||
void op_clv();
|
||||
|
||||
void op_sec();
|
||||
|
||||
void op_sed();
|
||||
|
||||
void op_sei();
|
||||
|
||||
|
||||
void op_rep_e();
|
||||
void op_rep_n();
|
||||
|
||||
void op_sep_e();
|
||||
void op_sep_n();
|
||||
|
||||
|
||||
void op_tax_b();
|
||||
void op_tax_w();
|
||||
|
||||
void op_tay_b();
|
||||
void op_tay_w();
|
||||
|
||||
void op_txa_b();
|
||||
void op_txa_w();
|
||||
|
||||
void op_txy_b();
|
||||
void op_txy_w();
|
||||
|
||||
void op_tya_b();
|
||||
void op_tya_w();
|
||||
|
||||
void op_tyx_b();
|
||||
void op_tyx_w();
|
||||
|
||||
|
||||
void op_tcd();
|
||||
|
||||
void op_tdc();
|
||||
|
||||
|
||||
void op_tcs_e();
|
||||
void op_tcs_n();
|
||||
|
||||
void op_tsc_e();
|
||||
void op_tsc_n();
|
||||
|
||||
void op_tsx_b();
|
||||
void op_tsx_w();
|
||||
|
||||
void op_txs_e();
|
||||
void op_txs_n();
|
||||
|
||||
|
||||
void op_pha_b();
|
||||
void op_pha_w();
|
||||
|
||||
void op_phx_b();
|
||||
void op_phx_w();
|
||||
|
||||
void op_phy_b();
|
||||
void op_phy_w();
|
||||
|
||||
void op_phd_e();
|
||||
void op_phd_n();
|
||||
|
||||
void op_phb();
|
||||
|
||||
void op_phk();
|
||||
|
||||
void op_php();
|
||||
|
||||
|
||||
void op_pla_b();
|
||||
void op_pla_w();
|
||||
|
||||
void op_plx_b();
|
||||
void op_plx_w();
|
||||
|
||||
void op_ply_b();
|
||||
void op_ply_w();
|
||||
|
||||
void op_pld_e();
|
||||
void op_pld_n();
|
||||
|
||||
void op_plb();
|
||||
|
||||
void op_plp_e();
|
||||
void op_plp_n();
|
||||
|
||||
|
||||
void op_pea_e();
|
||||
void op_pea_n();
|
||||
|
||||
void op_pei_e();
|
||||
void op_pei_n();
|
||||
|
||||
void op_per_e();
|
||||
void op_per_n();
|
||||
|
||||
|
||||
|
|
@ -1,317 +0,0 @@
|
|||
//===============
|
||||
//opcode_read.bpp
|
||||
//===============
|
||||
|
||||
@op_read_const(adc)
|
||||
@op_read_const(and)
|
||||
@op_read_const(cmp)
|
||||
@op_read_const(cpx)
|
||||
@op_read_const(cpy)
|
||||
@op_read_const(eor)
|
||||
@op_read_const(lda)
|
||||
@op_read_const(ldx)
|
||||
@op_read_const(ldy)
|
||||
@op_read_const(ora)
|
||||
@op_read_const(sbc)
|
||||
|
||||
@op_read_bit_const()
|
||||
|
||||
@op_read_addr(adc)
|
||||
@op_read_addr(and)
|
||||
@op_read_addr(bit)
|
||||
@op_read_addr(cmp)
|
||||
@op_read_addr(cpx)
|
||||
@op_read_addr(cpy)
|
||||
@op_read_addr(eor)
|
||||
@op_read_addr(lda)
|
||||
@op_read_addr(ldx)
|
||||
@op_read_addr(ldy)
|
||||
@op_read_addr(ora)
|
||||
@op_read_addr(sbc)
|
||||
|
||||
@op_read_addrx(adc)
|
||||
@op_read_addrx(and)
|
||||
@op_read_addrx(bit)
|
||||
@op_read_addrx(cmp)
|
||||
@op_read_addrx(eor)
|
||||
@op_read_addrx(lda)
|
||||
@op_read_addrx(ldy)
|
||||
@op_read_addrx(ora)
|
||||
@op_read_addrx(sbc)
|
||||
|
||||
@op_read_addry(adc)
|
||||
@op_read_addry(and)
|
||||
@op_read_addry(cmp)
|
||||
@op_read_addry(eor)
|
||||
@op_read_addry(lda)
|
||||
@op_read_addry(ldx)
|
||||
@op_read_addry(ora)
|
||||
@op_read_addry(sbc)
|
||||
|
||||
@op_read_long(adc)
|
||||
@op_read_long(and)
|
||||
@op_read_long(cmp)
|
||||
@op_read_long(eor)
|
||||
@op_read_long(lda)
|
||||
@op_read_long(ora)
|
||||
@op_read_long(sbc)
|
||||
|
||||
@op_read_longx(adc)
|
||||
@op_read_longx(and)
|
||||
@op_read_longx(cmp)
|
||||
@op_read_longx(eor)
|
||||
@op_read_longx(lda)
|
||||
@op_read_longx(ora)
|
||||
@op_read_longx(sbc)
|
||||
|
||||
@op_read_dp(adc)
|
||||
@op_read_dp(and)
|
||||
@op_read_dp(bit)
|
||||
@op_read_dp(cmp)
|
||||
@op_read_dp(cpx)
|
||||
@op_read_dp(cpy)
|
||||
@op_read_dp(eor)
|
||||
@op_read_dp(lda)
|
||||
@op_read_dp(ldx)
|
||||
@op_read_dp(ldy)
|
||||
@op_read_dp(ora)
|
||||
@op_read_dp(sbc)
|
||||
|
||||
@op_read_dpr(adc, x)
|
||||
@op_read_dpr(and, x)
|
||||
@op_read_dpr(bit, x)
|
||||
@op_read_dpr(cmp, x)
|
||||
@op_read_dpr(eor, x)
|
||||
@op_read_dpr(lda, x)
|
||||
@op_read_dpr(ldx, y)
|
||||
@op_read_dpr(ldy, x)
|
||||
@op_read_dpr(ora, x)
|
||||
@op_read_dpr(sbc, x)
|
||||
|
||||
@op_read_idp(adc)
|
||||
@op_read_idp(and)
|
||||
@op_read_idp(cmp)
|
||||
@op_read_idp(eor)
|
||||
@op_read_idp(lda)
|
||||
@op_read_idp(ora)
|
||||
@op_read_idp(sbc)
|
||||
|
||||
@op_read_idpx(adc)
|
||||
@op_read_idpx(and)
|
||||
@op_read_idpx(cmp)
|
||||
@op_read_idpx(eor)
|
||||
@op_read_idpx(lda)
|
||||
@op_read_idpx(ora)
|
||||
@op_read_idpx(sbc)
|
||||
|
||||
@op_read_idpy(adc)
|
||||
@op_read_idpy(and)
|
||||
@op_read_idpy(cmp)
|
||||
@op_read_idpy(eor)
|
||||
@op_read_idpy(lda)
|
||||
@op_read_idpy(ora)
|
||||
@op_read_idpy(sbc)
|
||||
|
||||
@op_read_ildp(adc)
|
||||
@op_read_ildp(and)
|
||||
@op_read_ildp(cmp)
|
||||
@op_read_ildp(eor)
|
||||
@op_read_ildp(lda)
|
||||
@op_read_ildp(ora)
|
||||
@op_read_ildp(sbc)
|
||||
|
||||
@op_read_ildpy(adc)
|
||||
@op_read_ildpy(and)
|
||||
@op_read_ildpy(cmp)
|
||||
@op_read_ildpy(eor)
|
||||
@op_read_ildpy(lda)
|
||||
@op_read_ildpy(ora)
|
||||
@op_read_ildpy(sbc)
|
||||
|
||||
@op_read_sr(adc)
|
||||
@op_read_sr(and)
|
||||
@op_read_sr(cmp)
|
||||
@op_read_sr(eor)
|
||||
@op_read_sr(lda)
|
||||
@op_read_sr(ora)
|
||||
@op_read_sr(sbc)
|
||||
|
||||
@op_read_isry(adc)
|
||||
@op_read_isry(and)
|
||||
@op_read_isry(cmp)
|
||||
@op_read_isry(eor)
|
||||
@op_read_isry(lda)
|
||||
@op_read_isry(ora)
|
||||
@op_read_isry(sbc)
|
||||
|
||||
//================
|
||||
//opcode_write.bpp
|
||||
//================
|
||||
|
||||
@op_store_addr(sta, regs.a.w)
|
||||
@op_store_addr(stx, regs.x.w)
|
||||
@op_store_addr(sty, regs.y.w)
|
||||
@op_store_addr(stz, 0x0000)
|
||||
|
||||
@op_store_addrr(sta, x, regs.a.w, regs.x.w)
|
||||
@op_store_addrr(sta, y, regs.a.w, regs.y.w)
|
||||
@op_store_addrr(stz, x, 0x0000, regs.x.w)
|
||||
|
||||
@op_store_longr(sta, , 0x0000)
|
||||
@op_store_longr(sta, x, regs.x.w)
|
||||
|
||||
@op_store_dp(sta, regs.a.w)
|
||||
@op_store_dp(stx, regs.x.w)
|
||||
@op_store_dp(sty, regs.y.w)
|
||||
@op_store_dp(stz, 0x0000)
|
||||
|
||||
@op_store_dpr(sta, regs.a.w, x)
|
||||
@op_store_dpr(stx, regs.x.w, y)
|
||||
@op_store_dpr(sty, regs.y.w, x)
|
||||
@op_store_dpr(stz, 0x0000, x)
|
||||
|
||||
@op_sta_idp()
|
||||
@op_sta_ildp()
|
||||
@op_sta_idpx()
|
||||
@op_sta_idpy()
|
||||
@op_sta_ildpy()
|
||||
@op_sta_sr()
|
||||
@op_sta_isry()
|
||||
|
||||
//==============
|
||||
//opcode_rmw.bpp
|
||||
//==============
|
||||
|
||||
@op_adjust(inc, a, ++)
|
||||
@op_adjust(inx, x, ++)
|
||||
@op_adjust(iny, y, ++)
|
||||
@op_adjust(dec, a, --)
|
||||
@op_adjust(dex, x, --)
|
||||
@op_adjust(dey, y, --)
|
||||
|
||||
@op_asl()
|
||||
@op_lsr()
|
||||
@op_rol()
|
||||
@op_ror()
|
||||
|
||||
@op_adjust_addr(inc)
|
||||
@op_adjust_addr(dec)
|
||||
@op_adjust_addr(asl)
|
||||
@op_adjust_addr(lsr)
|
||||
@op_adjust_addr(rol)
|
||||
@op_adjust_addr(ror)
|
||||
@op_adjust_addr(trb)
|
||||
@op_adjust_addr(tsb)
|
||||
|
||||
@op_adjust_addrx(inc)
|
||||
@op_adjust_addrx(dec)
|
||||
@op_adjust_addrx(asl)
|
||||
@op_adjust_addrx(lsr)
|
||||
@op_adjust_addrx(rol)
|
||||
@op_adjust_addrx(ror)
|
||||
|
||||
@op_adjust_dp(inc)
|
||||
@op_adjust_dp(dec)
|
||||
@op_adjust_dp(asl)
|
||||
@op_adjust_dp(lsr)
|
||||
@op_adjust_dp(rol)
|
||||
@op_adjust_dp(ror)
|
||||
@op_adjust_dp(trb)
|
||||
@op_adjust_dp(tsb)
|
||||
|
||||
@op_adjust_dpx(inc)
|
||||
@op_adjust_dpx(dec)
|
||||
@op_adjust_dpx(asl)
|
||||
@op_adjust_dpx(lsr)
|
||||
@op_adjust_dpx(rol)
|
||||
@op_adjust_dpx(ror)
|
||||
|
||||
//=============
|
||||
//opcode_pc.bpp
|
||||
//=============
|
||||
|
||||
@op_branch(bcc, !regs.p.c)
|
||||
@op_branch(bcs, regs.p.c)
|
||||
@op_branch(bne, !regs.p.z)
|
||||
@op_branch(beq, regs.p.z)
|
||||
@op_branch(bpl, !regs.p.n)
|
||||
@op_branch(bmi, regs.p.n)
|
||||
@op_branch(bvc, !regs.p.v)
|
||||
@op_branch(bvs, regs.p.v)
|
||||
|
||||
@op_bra()
|
||||
@op_brl()
|
||||
@op_jmp_addr()
|
||||
@op_jmp_long()
|
||||
@op_jmp_iaddr()
|
||||
@op_jmp_iaddrx()
|
||||
@op_jmp_iladdr()
|
||||
@op_jsr_addr()
|
||||
@op_jsr_long()
|
||||
@op_jsr_iaddrx()
|
||||
@op_rti()
|
||||
@op_rts()
|
||||
@op_rtl()
|
||||
|
||||
//===============
|
||||
//opcode_misc.bpp
|
||||
//===============
|
||||
|
||||
@op_nop()
|
||||
@op_wdm()
|
||||
@op_xba()
|
||||
|
||||
@op_move(mvn, ++)
|
||||
@op_move(mvp, --)
|
||||
|
||||
@op_interrupt(brk, 0xfffe, 0xffe6)
|
||||
@op_interrupt(cop, 0xfff4, 0xffe4)
|
||||
|
||||
@op_stp()
|
||||
@op_wai()
|
||||
@op_xce()
|
||||
|
||||
@op_flag(clc, regs.p.c = 0)
|
||||
@op_flag(cld, regs.p.d = 0)
|
||||
@op_flag(cli, regs.p.i = 0)
|
||||
@op_flag(clv, regs.p.v = 0)
|
||||
@op_flag(sec, regs.p.c = 1)
|
||||
@op_flag(sed, regs.p.d = 1)
|
||||
@op_flag(sei, regs.p.i = 1)
|
||||
|
||||
@op_pflag(rep, &=~)
|
||||
@op_pflag(sep, |=)
|
||||
|
||||
@op_transfer(tax, a, x)
|
||||
@op_transfer(tay, a, y)
|
||||
@op_transfer(txa, x, a)
|
||||
@op_transfer(txy, x, y)
|
||||
@op_transfer(tya, y, a)
|
||||
@op_transfer(tyx, y, x)
|
||||
|
||||
@op_transfer_word(tcd, a, d)
|
||||
@op_transfer_word(tdc, d, a)
|
||||
|
||||
@op_tcs()
|
||||
@op_tsc()
|
||||
@op_tsx()
|
||||
@op_txs()
|
||||
|
||||
@op_push(pha, a)
|
||||
@op_push(phx, x)
|
||||
@op_push(phy, y)
|
||||
@op_phd()
|
||||
@op_push_byte(phb, regs.db)
|
||||
@op_push_byte(phk, regs.pc.b)
|
||||
@op_push_byte(php, regs.p)
|
||||
|
||||
@op_pull(pla, a)
|
||||
@op_pull(plx, x)
|
||||
@op_pull(ply, y)
|
||||
@op_pld()
|
||||
@op_plb()
|
||||
@op_plp()
|
||||
|
||||
@op_pea()
|
||||
@op_pei()
|
||||
@op_per()
|
|
@ -1,397 +0,0 @@
|
|||
@macro op_nop()
|
||||
void {class}::op_nop() {
|
||||
{lc}op_io_irq();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_wdm()
|
||||
void {class}::op_wdm() {
|
||||
{lc}op_readpc();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_xba()
|
||||
void {class}::op_xba() {
|
||||
op_io();
|
||||
{lc}op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_move(name, op)
|
||||
void {class}::op_{name}_b() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
regs.x.l {op};
|
||||
regs.y.l {op};
|
||||
{lc}op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
regs.x.w {op};
|
||||
regs.y.w {op};
|
||||
{lc}op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_interrupt(name, vectorE, vectorN)
|
||||
void {class}::op_{name}_e() {
|
||||
op_readpc();
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong({vectorE} + 0);
|
||||
regs.pc.b = 0;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
{lc}rd.h = op_readlong({vectorE} + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void {class}::op_{name}_n() {
|
||||
op_readpc();
|
||||
op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong({vectorN} + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
{lc}rd.h = op_readlong({vectorN} + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_stp()
|
||||
void {class}::op_stp() {
|
||||
while({wai} = true) {
|
||||
{lc} op_io();
|
||||
}
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_wai()
|
||||
void {class}::op_wai() {
|
||||
{wai} = true;
|
||||
while({wai}) {
|
||||
{lc} op_io();
|
||||
}
|
||||
op_io();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_xce()
|
||||
void {class}::op_xce() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_flag(name, rule)
|
||||
void {class}::op_{name}() {
|
||||
{lc}op_io_irq();
|
||||
{rule};
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pflag(name, op)
|
||||
void {class}::op_{name}_e() {
|
||||
rd.l = op_readpc();
|
||||
{lc}op_io();
|
||||
regs.p {op} rd.l;
|
||||
regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_n() {
|
||||
rd.l = op_readpc();
|
||||
{lc}op_io();
|
||||
regs.p {op} rd.l;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer(name, from, to)
|
||||
void {class}::op_{name}_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.{to}.l = regs.{from}.l;
|
||||
regs.p.n = (regs.{to}.l & 0x80);
|
||||
regs.p.z = (regs.{to}.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.{to}.w = regs.{from}.w;
|
||||
regs.p.n = (regs.{to}.w & 0x8000);
|
||||
regs.p.z = (regs.{to}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_transfer_word(name, from, to)
|
||||
void {class}::op_{name}() {
|
||||
{lc}op_io_irq();
|
||||
regs.{to}.w = regs.{from}.w;
|
||||
regs.p.n = (regs.{to}.w & 0x8000);
|
||||
regs.p.z = (regs.{to}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_tcs()
|
||||
void {class}::op_tcs_e() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.l = regs.a.l;
|
||||
}
|
||||
|
||||
void {class}::op_tcs_n() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_tsc()
|
||||
void {class}::op_tsc_e() {
|
||||
{lc}op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_tsc_n() {
|
||||
{lc}op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_tsx()
|
||||
void {class}::op_tsx_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = (regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_tsx_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = (regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_txs()
|
||||
void {class}::op_txs_e() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.l = regs.x.l;
|
||||
}
|
||||
|
||||
void {class}::op_txs_n() {
|
||||
{lc}op_io_irq();
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_push(name, r)
|
||||
void {class}::op_{name}_b() {
|
||||
op_io();
|
||||
{lc}op_writestack(regs.{r}.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
op_io();
|
||||
op_writestack(regs.{r}.h);
|
||||
{lc}op_writestack(regs.{r}.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_phd()
|
||||
void {class}::op_phd_e() {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
{lc}op_writestackn(regs.d.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_phd_n() {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
{lc}op_writestackn(regs.d.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_push_byte(name, r)
|
||||
void {class}::op_{name}() {
|
||||
op_io();
|
||||
{lc}op_writestack({r});
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pull(name, r)
|
||||
void {class}::op_{name}_b() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.{r}.l = op_readstack();
|
||||
regs.p.n = (regs.{r}.l & 0x80);
|
||||
regs.p.z = (regs.{r}.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_w() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.{r}.l = op_readstack();
|
||||
{lc}regs.{r}.h = op_readstack();
|
||||
regs.p.n = (regs.{r}.w & 0x8000);
|
||||
regs.p.z = (regs.{r}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pld()
|
||||
void {class}::op_pld_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
{lc}regs.d.h = op_readstackn();
|
||||
regs.p.n = (regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_pld_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
{lc}regs.d.h = op_readstackn();
|
||||
regs.p.n = (regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_plb()
|
||||
void {class}::op_plb() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.db = op_readstack();
|
||||
regs.p.n = (regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_plp()
|
||||
void {class}::op_plp_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.p = op_readstack() | 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
void {class}::op_plp_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
{lc}regs.p = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pea()
|
||||
void {class}::op_pea_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_pea_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_pei()
|
||||
void {class}::op_pei_e() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_pei_n() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
{lc}op_writestackn(aa.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_per()
|
||||
void {class}::op_per_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16_t)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
{lc}op_writestackn(rd.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_per_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16_t)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
{lc}op_writestackn(rd.l);
|
||||
}
|
||||
@endmacro
|
|
@ -0,0 +1,348 @@
|
|||
void CPUcore::op_nop() {
|
||||
L op_io_irq();
|
||||
}
|
||||
|
||||
void CPUcore::op_wdm() {
|
||||
L op_readpc();
|
||||
}
|
||||
|
||||
void CPUcore::op_xba() {
|
||||
op_io();
|
||||
L op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
template<int adjust> void CPUcore::op_move_b() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
regs.x.l += adjust;
|
||||
regs.y.l += adjust;
|
||||
L op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
template<int adjust> void CPUcore::op_move_w() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
regs.x.w += adjust;
|
||||
regs.y.w += adjust;
|
||||
L op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
template<int vectorE, int vectorN> void CPUcore::op_interrupt_e() {
|
||||
op_readpc();
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong(vectorE + 0);
|
||||
regs.pc.b = 0;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
L rd.h = op_readlong(vectorE + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
template<int vectorE, int vectorN> void CPUcore::op_interrupt_n() {
|
||||
op_readpc();
|
||||
op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong(vectorN + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
L rd.h = op_readlong(vectorN + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_stp() {
|
||||
while(regs.wai = true) {
|
||||
L op_io();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUcore::op_wai() {
|
||||
regs.wai = true;
|
||||
while(regs.wai) {
|
||||
L op_io();
|
||||
}
|
||||
op_io();
|
||||
}
|
||||
|
||||
void CPUcore::op_xce() {
|
||||
L op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
template<int mask, int value> void CPUcore::op_flag() {
|
||||
L op_io_irq();
|
||||
regs.p = (regs.p & ~mask) | value;
|
||||
}
|
||||
|
||||
template<int mode> void CPUcore::op_pflag_e() {
|
||||
rd.l = op_readpc();
|
||||
L op_io();
|
||||
regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l);
|
||||
regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
template<int mode> void CPUcore::op_pflag_n() {
|
||||
rd.l = op_readpc();
|
||||
L op_io();
|
||||
regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l);
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
template<int from, int to> void CPUcore::op_transfer_b() {
|
||||
L op_io_irq();
|
||||
regs.r[to].l = regs.r[from].l;
|
||||
regs.p.n = (regs.r[to].l & 0x80);
|
||||
regs.p.z = (regs.r[to].l == 0);
|
||||
}
|
||||
|
||||
template<int from, int to> void CPUcore::op_transfer_w() {
|
||||
L op_io_irq();
|
||||
regs.r[to].w = regs.r[from].w;
|
||||
regs.p.n = (regs.r[to].w & 0x8000);
|
||||
regs.p.z = (regs.r[to].w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_tcs_e() {
|
||||
L op_io_irq();
|
||||
regs.s.l = regs.a.l;
|
||||
}
|
||||
|
||||
void CPUcore::op_tcs_n() {
|
||||
L op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_tsc_e() {
|
||||
L op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_tsc_n() {
|
||||
L op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_tsx_b() {
|
||||
L op_io_irq();
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = (regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_tsx_w() {
|
||||
L op_io_irq();
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = (regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_txs_e() {
|
||||
L op_io_irq();
|
||||
regs.s.l = regs.x.l;
|
||||
}
|
||||
|
||||
void CPUcore::op_txs_n() {
|
||||
L op_io_irq();
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_push_b() {
|
||||
op_io();
|
||||
L op_writestack(regs.r[n].l);
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_push_w() {
|
||||
op_io();
|
||||
op_writestack(regs.r[n].h);
|
||||
L op_writestack(regs.r[n].l);
|
||||
}
|
||||
|
||||
void CPUcore::op_phd_e() {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
L op_writestackn(regs.d.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_phd_n() {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
L op_writestackn(regs.d.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_phb() {
|
||||
op_io();
|
||||
L op_writestack(regs.db);
|
||||
}
|
||||
|
||||
void CPUcore::op_phk() {
|
||||
op_io();
|
||||
L op_writestack(regs.pc.b);
|
||||
}
|
||||
|
||||
void CPUcore::op_php() {
|
||||
op_io();
|
||||
L op_writestack(regs.p);
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_pull_b() {
|
||||
op_io();
|
||||
op_io();
|
||||
L regs.r[n].l = op_readstack();
|
||||
regs.p.n = (regs.r[n].l & 0x80);
|
||||
regs.p.z = (regs.r[n].l == 0);
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_pull_w() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.r[n].l = op_readstack();
|
||||
L regs.r[n].h = op_readstack();
|
||||
regs.p.n = (regs.r[n].w & 0x8000);
|
||||
regs.p.z = (regs.r[n].w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_pld_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
L regs.d.h = op_readstackn();
|
||||
regs.p.n = (regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_pld_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
L regs.d.h = op_readstackn();
|
||||
regs.p.n = (regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_plb() {
|
||||
op_io();
|
||||
op_io();
|
||||
L regs.db = op_readstack();
|
||||
regs.p.n = (regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_plp_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
L regs.p = op_readstack() | 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
void CPUcore::op_plp_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
L regs.p = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
update_table();
|
||||
}
|
||||
|
||||
void CPUcore::op_pea_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
L op_writestackn(aa.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_pea_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
L op_writestackn(aa.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_pei_e() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
L op_writestackn(aa.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_pei_n() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
L op_writestackn(aa.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_per_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
L op_writestackn(rd.l);
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_per_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
L op_writestackn(rd.l);
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
@macro op_branch(name, condition)
|
||||
void {class}::op_{name}() {
|
||||
if({condition} == false) {
|
||||
{lc} rd.l = op_readpc();
|
||||
} else {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8_t)rd.l;
|
||||
op_io_cond6(aa.w);
|
||||
{lc} op_io();
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_bra()
|
||||
void {class}::op_bra() {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8_t)rd.l;
|
||||
op_io_cond6(aa.w);
|
||||
{lc}op_io();
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_brl()
|
||||
void {class}::op_brl() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
{lc}op_io();
|
||||
regs.pc.w = regs.pc.d + (int16_t)rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_addr()
|
||||
void {class}::op_jmp_addr() {
|
||||
rd.l = op_readpc();
|
||||
{lc}rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_long()
|
||||
void {class}::op_jmp_long() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
{lc}rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddr()
|
||||
void {class}::op_jmp_iaddr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
{lc}rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iaddrx()
|
||||
void {class}::op_jmp_iaddrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jmp_iladdr()
|
||||
void {class}::op_jmp_iladdr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
{lc}rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_addr()
|
||||
void {class}::op_jsr_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
{lc}op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_long()
|
||||
void {class}::op_jsr_long_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
{lc}op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_jsr_long_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
{lc}op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_jsr_iaddrx()
|
||||
void {class}::op_jsr_iaddrx_e() {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_jsr_iaddrx_n() {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rti()
|
||||
void {class}::op_rti_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack() | 0x30;
|
||||
rd.l = op_readstack();
|
||||
{lc}rd.h = op_readstack();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void {class}::op_rti_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
{lc}rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
update_table();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rts()
|
||||
void {class}::op_rts() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
{lc}op_io();
|
||||
regs.pc.w = ++rd.w;
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rtl()
|
||||
void {class}::op_rtl_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
{lc}rd.b = op_readstackn();
|
||||
regs.pc.b = rd.b;
|
||||
regs.pc.w = ++rd.w;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void {class}::op_rtl_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
{lc}rd.b = op_readstackn();
|
||||
regs.pc.b = rd.b;
|
||||
regs.pc.w = ++rd.w;
|
||||
}
|
||||
@endmacro
|
|
@ -0,0 +1,177 @@
|
|||
template<int bit, int val> void CPUcore::op_branch() {
|
||||
if((bool)(regs.p & bit) != val) {
|
||||
L rd.l = op_readpc();
|
||||
} else {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
op_io_cond6(aa.w);
|
||||
L op_io();
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
}
|
||||
|
||||
void CPUcore::op_bra() {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
op_io_cond6(aa.w);
|
||||
L op_io();
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_brl() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
L op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_jmp_addr() {
|
||||
rd.l = op_readpc();
|
||||
L rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_jmp_long() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
L rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
void CPUcore::op_jmp_iaddr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
L rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_jmp_iaddrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
L rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_jmp_iladdr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
L rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
void CPUcore::op_jsr_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
L op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_jsr_long_e() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
L op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_jsr_long_n() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
L op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
}
|
||||
|
||||
void CPUcore::op_jsr_iaddrx_e() {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
L rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_jsr_iaddrx_n() {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w + 0);
|
||||
L rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_rti_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack() | 0x30;
|
||||
rd.l = op_readstack();
|
||||
L rd.h = op_readstack();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_rti_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
L rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
update_table();
|
||||
}
|
||||
|
||||
void CPUcore::op_rts() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
L op_io();
|
||||
regs.pc.w = ++rd.w;
|
||||
}
|
||||
|
||||
void CPUcore::op_rtl_e() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
L rd.b = op_readstackn();
|
||||
regs.pc.b = rd.b;
|
||||
regs.pc.w = ++rd.w;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
void CPUcore::op_rtl_n() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
L rd.b = op_readstackn();
|
||||
regs.pc.b = rd.b;
|
||||
regs.pc.w = ++rd.w;
|
||||
}
|
|
@ -1,307 +0,0 @@
|
|||
@macro op_read_const(name)
|
||||
void {class}::op_{name}_const_b() {
|
||||
{lc}rd.l = op_readpc();
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_const_w() {
|
||||
rd.l = op_readpc();
|
||||
{lc}rd.h = op_readpc();
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_bit_const()
|
||||
void {class}::op_bit_const_b() {
|
||||
{lc}rd.l = op_readpc();
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
void {class}::op_bit_const_w() {
|
||||
rd.l = op_readpc();
|
||||
{lc}rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addr(name)
|
||||
void {class}::op_{name}_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
{lc}rd.l = op_readdbr(aa.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addrx(name)
|
||||
void {class}::op_{name}_addrx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addrx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
rd.l = op_readdbr(aa.w + regs.x.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_addry(name)
|
||||
void {class}::op_{name}_addry_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addry_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_long(name)
|
||||
void {class}::op_{name}_long_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
{lc}rd.l = op_readlong(aa.d);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_long_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
rd.l = op_readlong(aa.d + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_longx(name)
|
||||
void {class}::op_{name}_longx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
{lc}rd.l = op_readlong(aa.d + regs.x.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_longx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
rd.l = op_readlong(aa.d + regs.x.w + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dp(name)
|
||||
void {class}::op_{name}_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
{lc}rd.l = op_readdp(dp);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp + 0);
|
||||
{lc}rd.h = op_readdp(dp + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_dpr(name, r)
|
||||
void {class}::op_{name}_dpr_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
{lc}rd.l = op_readdp(dp + regs.{r}.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dpr_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
{lc}rd.l = op_readdp(dp + regs.{r}.w + 0);
|
||||
rd.h = op_readdp(dp + regs.{r}.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idp(name)
|
||||
void {class}::op_{name}_idp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
{lc}rd.l = op_readdbr(aa.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_idp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpx(name)
|
||||
void {class}::op_{name}_idpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
{lc}rd.l = op_readdbr(aa.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_idpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_idpy(name)
|
||||
void {class}::op_{name}_idpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_idpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildp(name)
|
||||
void {class}::op_{name}_ildp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}rd.l = op_readlong(aa.d);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_ildp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
rd.l = op_readlong(aa.d + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_ildpy(name)
|
||||
void {class}::op_{name}_ildpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}rd.l = op_readlong(aa.d + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_ildpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
rd.l = op_readlong(aa.d + regs.y.w + 0);
|
||||
{lc}rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_sr(name)
|
||||
void {class}::op_{name}_sr_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
{lc}rd.l = op_readsp(sp);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_sr_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readsp(sp + 0);
|
||||
{lc}rd.h = op_readsp(sp + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_read_isry(name)
|
||||
void {class}::op_{name}_isry_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
op_{name}_b();
|
||||
}
|
||||
|
||||
void {class}::op_{name}_isry_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_{name}_w();
|
||||
}
|
||||
@endmacro
|
|
@ -0,0 +1,275 @@
|
|||
template<void (CPUcore::*op)()> void CPUcore::op_read_const_b() {
|
||||
L rd.l = op_readpc();
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_const_w() {
|
||||
rd.l = op_readpc();
|
||||
L rd.h = op_readpc();
|
||||
call(op);
|
||||
}
|
||||
|
||||
void CPUcore::op_read_bit_const_b() {
|
||||
L rd.l = op_readpc();
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_read_bit_const_w() {
|
||||
rd.l = op_readpc();
|
||||
L rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
L rd.l = op_readdbr(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_addrx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
L rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_addrx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
rd.l = op_readdbr(aa.w + regs.x.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_addry_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
L rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_addry_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_long_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
L rd.l = op_readlong(aa.d);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_long_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
rd.l = op_readlong(aa.d + 0);
|
||||
L rd.h = op_readlong(aa.d + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_longx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
L rd.l = op_readlong(aa.d + regs.x.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_longx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
rd.l = op_readlong(aa.d + regs.x.w + 0);
|
||||
L rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
L rd.l = op_readdp(dp);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp + 0);
|
||||
L rd.h = op_readdp(dp + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)(), int n> void CPUcore::op_read_dpr_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
L rd.l = op_readdp(dp + regs.r[n].w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)(), int n> void CPUcore::op_read_dpr_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
L rd.l = op_readdp(dp + regs.r[n].w + 0);
|
||||
rd.h = op_readdp(dp + regs.r[n].w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_idp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
L rd.l = op_readdbr(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_idp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_idpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
L rd.l = op_readdbr(aa.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_idpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_idpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
L rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_idpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_ildp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
L rd.l = op_readlong(aa.d);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_ildp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
rd.l = op_readlong(aa.d + 0);
|
||||
L rd.h = op_readlong(aa.d + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_ildpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
L rd.l = op_readlong(aa.d + regs.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_ildpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
rd.l = op_readlong(aa.d + regs.y.w + 0);
|
||||
L rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_sr_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
L rd.l = op_readsp(sp);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_sr_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readsp(sp + 0);
|
||||
L rd.h = op_readsp(sp + 1);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_isry_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
L rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
call(op);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_read_isry_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w + 0);
|
||||
L rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
call(op);
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
@macro op_adjust(name, r, op)
|
||||
void {class}::op_{name}_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.{r}.l {op};
|
||||
regs.p.n = (regs.{r}.l & 0x80);
|
||||
regs.p.z = (regs.{r}.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.{r}.w {op};
|
||||
regs.p.n = (regs.{r}.w & 0x8000);
|
||||
regs.p.z = (regs.{r}.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_asl()
|
||||
void {class}::op_asl_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_asl_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_lsr()
|
||||
void {class}::op_lsr_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.l & 0x01);
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_lsr_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
regs.p.c = (regs.a.w & 0x0001);
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_rol()
|
||||
void {class}::op_rol_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.l & 0x80);
|
||||
regs.a.l = (regs.a.l << 1) | carry;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_rol_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.w & 0x8000);
|
||||
regs.a.w = (regs.a.w << 1) | carry;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_ror()
|
||||
void {class}::op_ror_imm_b() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.l & 0x01);
|
||||
regs.a.l = (carry << 7) | (regs.a.l >> 1);
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void {class}::op_ror_imm_w() {
|
||||
{lc}op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.w & 0x0001);
|
||||
regs.a.w = (carry << 15) | (regs.a.w >> 1);
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addr(name)
|
||||
void {class}::op_{name}_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedbr(aa.w + 1, rd.h);
|
||||
{lc}op_writedbr(aa.w + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_addrx(name)
|
||||
void {class}::op_{name}_addrx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addrx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w + 0);
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h);
|
||||
{lc}op_writedbr(aa.w + regs.x.w + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dp(name)
|
||||
void {class}::op_{name}_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp + 0);
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedp(dp + 1, rd.h);
|
||||
{lc}op_writedp(dp + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_adjust_dpx(name)
|
||||
void {class}::op_{name}_dpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
op_io();
|
||||
op_{name}_b();
|
||||
{lc}op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w + 0);
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
op_{name}_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h);
|
||||
{lc}op_writedp(dp + regs.x.w + 0, rd.l);
|
||||
}
|
||||
@endmacro
|
|
@ -0,0 +1,165 @@
|
|||
template<int n, int adjust> void CPUcore::op_adjust_imm_b() {
|
||||
L op_io_irq();
|
||||
regs.r[n].l += adjust;
|
||||
regs.p.n = (regs.r[n].l & 0x80);
|
||||
regs.p.z = (regs.r[n].l == 0);
|
||||
}
|
||||
|
||||
template<int n, int adjust> void CPUcore::op_adjust_imm_w() {
|
||||
L op_io_irq();
|
||||
regs.r[n].w += adjust;
|
||||
regs.p.n = (regs.r[n].w & 0x8000);
|
||||
regs.p.z = (regs.r[n].w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_asl_imm_b() {
|
||||
L op_io_irq();
|
||||
regs.p.c = (regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_asl_imm_w() {
|
||||
L op_io_irq();
|
||||
regs.p.c = (regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_lsr_imm_b() {
|
||||
L op_io_irq();
|
||||
regs.p.c = (regs.a.l & 0x01);
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_lsr_imm_w() {
|
||||
L op_io_irq();
|
||||
regs.p.c = (regs.a.w & 0x0001);
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_rol_imm_b() {
|
||||
L op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.l & 0x80);
|
||||
regs.a.l = (regs.a.l << 1) | carry;
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_rol_imm_w() {
|
||||
L op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.w & 0x8000);
|
||||
regs.a.w = (regs.a.w << 1) | carry;
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_ror_imm_b() {
|
||||
L op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.l & 0x01);
|
||||
regs.a.l = (carry << 7) | (regs.a.l >> 1);
|
||||
regs.p.n = (regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
void CPUcore::op_ror_imm_w() {
|
||||
L op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = (regs.a.w & 0x0001);
|
||||
regs.a.w = (carry << 15) | (regs.a.w >> 1);
|
||||
regs.p.n = (regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
op_io();
|
||||
call(op);
|
||||
L op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w + 0);
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
call(op);
|
||||
op_writedbr(aa.w + 1, rd.h);
|
||||
L op_writedbr(aa.w + 0, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addrx_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
op_io();
|
||||
call(op);
|
||||
L op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_addrx_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w + 0);
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
call(op);
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h);
|
||||
L op_writedbr(aa.w + regs.x.w + 0, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
op_io();
|
||||
call(op);
|
||||
L op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp + 0);
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
call(op);
|
||||
op_writedp(dp + 1, rd.h);
|
||||
L op_writedp(dp + 0, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
op_io();
|
||||
call(op);
|
||||
L op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
template<void (CPUcore::*op)()> void CPUcore::op_adjust_dpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w + 0);
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
call(op);
|
||||
op_writedp(dp + regs.x.w + 1, rd.h);
|
||||
L op_writedp(dp + regs.x.w + 0, rd.l);
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
#ifdef CPUCORE_CPP
|
||||
|
||||
void CPUcore::initialize_opcode_table() {
|
||||
//same implementation for all processor states
|
||||
#define opA(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name;
|
||||
|
||||
//implementation changes based on E processor state
|
||||
#define opE(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name ## _e; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name ## _n; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _n; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name ## _n; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name ## _n; \
|
||||
|
||||
//implementation changes based on M processor state
|
||||
#define opM(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name ## _w; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
|
||||
|
||||
//implementation changes based on X processor state
|
||||
#define opX(id, name) \
|
||||
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _w; \
|
||||
op_table[table_mX + id] = &CPUcore::op_ ## name ## _b; \
|
||||
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
|
||||
|
||||
opE(0x00, brk) opM(0x01, ora_idpx) opE(0x02, cop) opM(0x03, ora_sr)
|
||||
opM(0x04, tsb_dp) opM(0x05, ora_dp) opM(0x06, asl_dp) opM(0x07, ora_ildp)
|
||||
opA(0x08, php) opM(0x09, ora_const) opM(0x0a, asl_imm) opE(0x0b, phd)
|
||||
opM(0x0c, tsb_addr) opM(0x0d, ora_addr) opM(0x0e, asl_addr) opM(0x0f, ora_long)
|
||||
|
||||
opA(0x10, bpl) opM(0x11, ora_idpy) opM(0x12, ora_idp) opM(0x13, ora_isry)
|
||||
opM(0x14, trb_dp) opM(0x15, ora_dpr) opM(0x16, asl_dpx) opM(0x17, ora_ildpy)
|
||||
opA(0x18, clc) opM(0x19, ora_addry) opM(0x1a, inc_imm) opE(0x1b, tcs)
|
||||
opM(0x1c, trb_addr) opM(0x1d, ora_addrx) opM(0x1e, asl_addrx) opM(0x1f, ora_longx)
|
||||
|
||||
opA(0x20, jsr_addr) opM(0x21, and_idpx) opE(0x22, jsr_long) opM(0x23, and_sr)
|
||||
opM(0x24, bit_dp) opM(0x25, and_dp) opM(0x26, rol_dp) opM(0x27, and_ildp)
|
||||
opE(0x28, plp) opM(0x29, and_const) opM(0x2a, rol_imm) opE(0x2b, pld)
|
||||
opM(0x2c, bit_addr) opM(0x2d, and_addr) opM(0x2e, rol_addr) opM(0x2f, and_long)
|
||||
|
||||
opA(0x30, bmi) opM(0x31, and_idpy) opM(0x32, and_idp) opM(0x33, and_isry)
|
||||
opM(0x34, bit_dpr) opM(0x35, and_dpr) opM(0x36, rol_dpx) opM(0x37, and_ildpy)
|
||||
opA(0x38, sec) opM(0x39, and_addry) opM(0x3a, dec_imm) opE(0x3b, tsc)
|
||||
opM(0x3c, bit_addrx) opM(0x3d, and_addrx) opM(0x3e, rol_addrx) opM(0x3f, and_longx)
|
||||
|
||||
opE(0x40, rti) opM(0x41, eor_idpx) opA(0x42, wdm) opM(0x43, eor_sr)
|
||||
opX(0x44, mvp) opM(0x45, eor_dp) opM(0x46, lsr_dp) opM(0x47, eor_ildp)
|
||||
opM(0x48, pha) opM(0x49, eor_const) opM(0x4a, lsr_imm) opA(0x4b, phk)
|
||||
opA(0x4c, jmp_addr) opM(0x4d, eor_addr) opM(0x4e, lsr_addr) opM(0x4f, eor_long)
|
||||
|
||||
opA(0x50, bvc) opM(0x51, eor_idpy) opM(0x52, eor_idp) opM(0x53, eor_isry)
|
||||
opX(0x54, mvn) opM(0x55, eor_dpr) opM(0x56, lsr_dpx) opM(0x57, eor_ildpy)
|
||||
opA(0x58, cli) opM(0x59, eor_addry) opX(0x5a, phy) opA(0x5b, tcd)
|
||||
opA(0x5c, jmp_long) opM(0x5d, eor_addrx) opM(0x5e, lsr_addrx) opM(0x5f, eor_longx)
|
||||
|
||||
opA(0x60, rts) opM(0x61, adc_idpx) opE(0x62, per) opM(0x63, adc_sr)
|
||||
opM(0x64, stz_dp) opM(0x65, adc_dp) opM(0x66, ror_dp) opM(0x67, adc_ildp)
|
||||
opM(0x68, pla) opM(0x69, adc_const) opM(0x6a, ror_imm) opE(0x6b, rtl)
|
||||
opA(0x6c, jmp_iaddr) opM(0x6d, adc_addr) opM(0x6e, ror_addr) opM(0x6f, adc_long)
|
||||
|
||||
opA(0x70, bvs) opM(0x71, adc_idpy) opM(0x72, adc_idp) opM(0x73, adc_isry)
|
||||
opM(0x74, stz_dpr) opM(0x75, adc_dpr) opM(0x76, ror_dpx) opM(0x77, adc_ildpy)
|
||||
opA(0x78, sei) opM(0x79, adc_addry) opX(0x7a, ply) opA(0x7b, tdc)
|
||||
opA(0x7c, jmp_iaddrx) opM(0x7d, adc_addrx) opM(0x7e, ror_addrx) opM(0x7f, adc_longx)
|
||||
|
||||
opA(0x80, bra) opM(0x81, sta_idpx) opA(0x82, brl) opM(0x83, sta_sr)
|
||||
opX(0x84, sty_dp) opM(0x85, sta_dp) opX(0x86, stx_dp) opM(0x87, sta_ildp)
|
||||
opX(0x88, dey_imm) opM(0x89, bit_const) opM(0x8a, txa) opA(0x8b, phb)
|
||||
opX(0x8c, sty_addr) opM(0x8d, sta_addr) opX(0x8e, stx_addr) opM(0x8f, sta_long)
|
||||
|
||||
opA(0x90, bcc) opM(0x91, sta_idpy) opM(0x92, sta_idp) opM(0x93, sta_isry)
|
||||
opX(0x94, sty_dpr) opM(0x95, sta_dpr) opX(0x96, stx_dpr) opM(0x97, sta_ildpy)
|
||||
opM(0x98, tya) opM(0x99, sta_addry) opE(0x9a, txs) opX(0x9b, txy)
|
||||
opM(0x9c, stz_addr) opM(0x9d, sta_addrx) opM(0x9e, stz_addrx) opM(0x9f, sta_longx)
|
||||
|
||||
opX(0xa0, ldy_const) opM(0xa1, lda_idpx) opX(0xa2, ldx_const) opM(0xa3, lda_sr)
|
||||
opX(0xa4, ldy_dp) opM(0xa5, lda_dp) opX(0xa6, ldx_dp) opM(0xa7, lda_ildp)
|
||||
opX(0xa8, tay) opM(0xa9, lda_const) opX(0xaa, tax) opA(0xab, plb)
|
||||
opX(0xac, ldy_addr) opM(0xad, lda_addr) opX(0xae, ldx_addr) opM(0xaf, lda_long)
|
||||
|
||||
opA(0xb0, bcs) opM(0xb1, lda_idpy) opM(0xb2, lda_idp) opM(0xb3, lda_isry)
|
||||
opX(0xb4, ldy_dpr) opM(0xb5, lda_dpr) opX(0xb6, ldx_dpr) opM(0xb7, lda_ildpy)
|
||||
opA(0xb8, clv) opM(0xb9, lda_addry) opX(0xba, tsx) opX(0xbb, tyx)
|
||||
opX(0xbc, ldy_addrx) opM(0xbd, lda_addrx) opX(0xbe, ldx_addry) opM(0xbf, lda_longx)
|
||||
|
||||
opX(0xc0, cpy_const) opM(0xc1, cmp_idpx) opE(0xc2, rep) opM(0xc3, cmp_sr)
|
||||
opX(0xc4, cpy_dp) opM(0xc5, cmp_dp) opM(0xc6, dec_dp) opM(0xc7, cmp_ildp)
|
||||
opX(0xc8, iny_imm) opM(0xc9, cmp_const) opX(0xca, dex_imm) opA(0xcb, wai)
|
||||
opX(0xcc, cpy_addr) opM(0xcd, cmp_addr) opM(0xce, dec_addr) opM(0xcf, cmp_long)
|
||||
|
||||
opA(0xd0, bne) opM(0xd1, cmp_idpy) opM(0xd2, cmp_idp) opM(0xd3, cmp_isry)
|
||||
opE(0xd4, pei) opM(0xd5, cmp_dpr) opM(0xd6, dec_dpx) opM(0xd7, cmp_ildpy)
|
||||
opA(0xd8, cld) opM(0xd9, cmp_addry) opX(0xda, phx) opA(0xdb, stp)
|
||||
opA(0xdc, jmp_iladdr) opM(0xdd, cmp_addrx) opM(0xde, dec_addrx) opM(0xdf, cmp_longx)
|
||||
|
||||
opX(0xe0, cpx_const) opM(0xe1, sbc_idpx) opE(0xe2, sep) opM(0xe3, sbc_sr)
|
||||
opX(0xe4, cpx_dp) opM(0xe5, sbc_dp) opM(0xe6, inc_dp) opM(0xe7, sbc_ildp)
|
||||
opX(0xe8, inx_imm) opM(0xe9, sbc_const) opA(0xea, nop) opA(0xeb, xba)
|
||||
opX(0xec, cpx_addr) opM(0xed, sbc_addr) opM(0xee, inc_addr) opM(0xef, sbc_long)
|
||||
|
||||
opA(0xf0, beq) opM(0xf1, sbc_idpy) opM(0xf2, sbc_idp) opM(0xf3, sbc_isry)
|
||||
opE(0xf4, pea) opM(0xf5, sbc_dpr) opM(0xf6, inc_dpx) opM(0xf7, sbc_ildpy)
|
||||
opA(0xf8, sed) opM(0xf9, sbc_addry) opX(0xfa, plx) opA(0xfb, xce)
|
||||
opE(0xfc, jsr_iaddrx) opM(0xfd, sbc_addrx) opM(0xfe, inc_addrx) opM(0xff, sbc_longx)
|
||||
|
||||
#undef opA
|
||||
#undef opE
|
||||
#undef opM
|
||||
#undef opX
|
||||
}
|
||||
|
||||
void CPUcore::update_table() {
|
||||
if(regs.e) {
|
||||
opcode_table = &op_table[table_EM];
|
||||
} else if(regs.p.m) {
|
||||
if(regs.p.x) {
|
||||
opcode_table = &op_table[table_MX];
|
||||
} else {
|
||||
opcode_table = &op_table[table_Mx];
|
||||
}
|
||||
} else {
|
||||
if(regs.p.x) {
|
||||
opcode_table = &op_table[table_mX];
|
||||
} else {
|
||||
opcode_table = &op_table[table_mx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,219 +0,0 @@
|
|||
@macro op_store_addr(name, r)
|
||||
void {class}::op_{name}_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
{lc}op_writedbr(aa.w, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writedbr(aa.w + 0, {r} >> 0);
|
||||
{lc}op_writedbr(aa.w + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_addrr(name, suffix, r, index)
|
||||
void {class}::op_{name}_addr{suffix}_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
{lc}op_writedbr(aa.w + {index}, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_addr{suffix}_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
op_writedbr(aa.w + {index} + 0, {r} >> 0);
|
||||
{lc}op_writedbr(aa.w + {index} + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_longr(name, suffix, index)
|
||||
void {class}::op_{name}_long{suffix}_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
{lc}op_writelong(aa.d + {index}, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_{name}_long{suffix}_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
op_writelong(aa.d + {index} + 0, regs.a.l);
|
||||
{lc}op_writelong(aa.d + {index} + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dp(name, r)
|
||||
void {class}::op_{name}_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
{lc}op_writedp(dp, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_writedp(dp + 0, {r} >> 0);
|
||||
{lc}op_writedp(dp + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_store_dpr(name, r, index)
|
||||
void {class}::op_{name}_dpr_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
{lc}op_writedp(dp + regs.{index}.w, {r});
|
||||
}
|
||||
|
||||
void {class}::op_{name}_dpr_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
op_writedp(dp + regs.{index}.w + 0, {r} >> 0);
|
||||
{lc}op_writedp(dp + regs.{index}.w + 1, {r} >> 8);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idp()
|
||||
void {class}::op_sta_idp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
{lc}op_writedbr(aa.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_idp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writedbr(aa.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildp()
|
||||
void {class}::op_sta_ildp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}op_writelong(aa.d, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_ildp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
op_writelong(aa.d + 0, regs.a.l);
|
||||
{lc}op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpx()
|
||||
void {class}::op_sta_idpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
{lc}op_writedbr(aa.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_idpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_writedbr(aa.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_idpy()
|
||||
void {class}::op_sta_idpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
{lc}op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_idpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_ildpy()
|
||||
void {class}::op_sta_ildpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
{lc}op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_ildpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
op_writelong(aa.d + regs.y.w + 0, regs.a.l);
|
||||
{lc}op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_sr()
|
||||
void {class}::op_sta_sr_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
{lc}op_writesp(sp, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_sr_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
op_writesp(sp + 0, regs.a.l);
|
||||
{lc}op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
||||
|
||||
@macro op_sta_isry()
|
||||
void {class}::op_sta_isry_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
{lc}op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void {class}::op_sta_isry_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
|
||||
{lc}op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@endmacro
|
|
@ -0,0 +1,195 @@
|
|||
template<int n> void CPUcore::op_write_addr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
L op_writedbr(aa.w, regs.r[n]);
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_write_addr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writedbr(aa.w + 0, regs.r[n] >> 0);
|
||||
L op_writedbr(aa.w + 1, regs.r[n] >> 8);
|
||||
}
|
||||
|
||||
template<int n, int i> void CPUcore::op_write_addrr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
L op_writedbr(aa.w + regs.r[i], regs.r[n]);
|
||||
}
|
||||
|
||||
template<int n, int i> void CPUcore::op_write_addrr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.r[i] + 0, regs.r[n] >> 0);
|
||||
L op_writedbr(aa.w + regs.r[i] + 1, regs.r[n] >> 8);
|
||||
}
|
||||
|
||||
template<int i> void CPUcore::op_write_longr_b() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
L op_writelong(aa.d + regs.r[i], regs.a.l);
|
||||
}
|
||||
|
||||
template<int i> void CPUcore::op_write_longr_w() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
op_writelong(aa.d + regs.r[i] + 0, regs.a.l);
|
||||
L op_writelong(aa.d + regs.r[i] + 1, regs.a.h);
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_write_dp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
L op_writedp(dp, regs.r[n]);
|
||||
}
|
||||
|
||||
template<int n> void CPUcore::op_write_dp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_writedp(dp + 0, regs.r[n] >> 0);
|
||||
L op_writedp(dp + 1, regs.r[n] >> 8);
|
||||
}
|
||||
|
||||
template<int n, int i> void CPUcore::op_write_dpr_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
L op_writedp(dp + regs.r[i], regs.r[n]);
|
||||
}
|
||||
|
||||
template<int n, int i> void CPUcore::op_write_dpr_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
op_writedp(dp + regs.r[i] + 0, regs.r[n] >> 0);
|
||||
L op_writedp(dp + regs.r[i] + 1, regs.r[n] >> 8);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_idp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
L op_writedbr(aa.w, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_idp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writedbr(aa.w + 0, regs.a.l);
|
||||
L op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_ildp_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
L op_writelong(aa.d, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_ildp_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
op_writelong(aa.d + 0, regs.a.l);
|
||||
L op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_idpx_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
L op_writedbr(aa.w, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_idpx_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w + 0);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_writedbr(aa.w + 0, regs.a.l);
|
||||
L op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_idpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
L op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_idpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
|
||||
L op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_ildpy_b() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
L op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_ildpy_w() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp + 0);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
op_writelong(aa.d + regs.y.w + 0, regs.a.l);
|
||||
L op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_sr_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
L op_writesp(sp, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_sr_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
op_writesp(sp + 0, regs.a.l);
|
||||
L op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_isry_b() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
L op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
}
|
||||
|
||||
void CPUcore::op_sta_isry_w() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp + 0);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
|
||||
L op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
|
@ -6,7 +6,7 @@ struct flag_t {
|
|||
+ (d << 3) + (i << 2) + (z << 1) + (c << 0);
|
||||
}
|
||||
|
||||
inline unsigned operator=(uint8_t data) {
|
||||
inline unsigned operator=(uint8 data) {
|
||||
n = data & 0x80; v = data & 0x40; m = data & 0x20; x = data & 0x10;
|
||||
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
|
||||
return data;
|
||||
|
@ -65,15 +65,17 @@ struct reg24_t {
|
|||
};
|
||||
|
||||
struct regs_t {
|
||||
reg24_t pc;
|
||||
reg16_t a, x, y, s, d;
|
||||
flag_t p;
|
||||
uint8_t db;
|
||||
bool e;
|
||||
reg24_t pc;
|
||||
reg16_t r[6], &a, &x, &y, &z, &s, &d;
|
||||
flag_t p;
|
||||
uint8 db;
|
||||
bool e;
|
||||
|
||||
bool irq; //IRQ pin (0 = low, 1 = trigger)
|
||||
bool wai; //raised during wai, cleared after interrupt triggered
|
||||
uint8_t mdr; //memory data register
|
||||
bool irq; //IRQ pin (0 = low, 1 = trigger)
|
||||
bool wai; //raised during wai, cleared after interrupt triggered
|
||||
uint8 mdr; //memory data register
|
||||
|
||||
regs_t() : db(0), e(false), irq(false), wai(false), mdr(0) {}
|
||||
regs_t() : a(r[0]), x(r[1]), y(r[2]), z(r[3]), s(r[4]), d(r[5]), db(0), e(false), irq(false), wai(false), mdr(0) {
|
||||
z = 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#ifdef CPUCORE_CPP
|
||||
|
||||
void CPUcore::core_serialize(serializer &s) {
|
||||
s.integer(regs.pc.d);
|
||||
|
||||
s.integer(regs.a.w);
|
||||
s.integer(regs.x.w);
|
||||
s.integer(regs.y.w);
|
||||
s.integer(regs.z.w);
|
||||
s.integer(regs.s.w);
|
||||
s.integer(regs.d.w);
|
||||
|
||||
s.integer(regs.p.n);
|
||||
s.integer(regs.p.v);
|
||||
s.integer(regs.p.m);
|
||||
s.integer(regs.p.x);
|
||||
s.integer(regs.p.d);
|
||||
s.integer(regs.p.i);
|
||||
s.integer(regs.p.z);
|
||||
s.integer(regs.p.c);
|
||||
|
||||
s.integer(regs.db);
|
||||
s.integer(regs.e);
|
||||
s.integer(regs.irq);
|
||||
s.integer(regs.wai);
|
||||
s.integer(regs.mdr);
|
||||
|
||||
s.integer(aa.d);
|
||||
s.integer(rd.d);
|
||||
s.integer(sp);
|
||||
s.integer(dp);
|
||||
|
||||
update_table();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,312 @@
|
|||
#ifdef CPUCORE_CPP
|
||||
|
||||
void CPUcore::initialize_opcode_table() {
|
||||
#define opA( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name;
|
||||
#define opAII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name<x, y>;
|
||||
#define opE( id, name ) op_table[table_EM + id] = &CPUcore::op_##name##_e; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n;
|
||||
#define opEI( id, name, x ) op_table[table_EM + id] = &CPUcore::op_##name##_e<x>; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n<x>;
|
||||
#define opEII(id, name, x, y ) op_table[table_EM + id] = &CPUcore::op_##name##_e<x, y>; op_table[table_MX + id] = op_table[table_Mx + id] = op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_n<x, y>;
|
||||
#define opM( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w;
|
||||
#define opMI( id, name, x ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<x>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x>;
|
||||
#define opMII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<x, y>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x, y>;
|
||||
#define opMF( id, name, fn ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w>;
|
||||
#define opMFI(id, name, fn, x) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_Mx + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b, x>; op_table[table_mX + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w, x>;
|
||||
#define opX( id, name ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w;
|
||||
#define opXI( id, name, x ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<x>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x>;
|
||||
#define opXII(id, name, x, y ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<x, y>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<x, y>;
|
||||
#define opXF( id, name, fn ) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w>;
|
||||
#define opXFI(id, name, fn, x) op_table[table_EM + id] = op_table[table_MX + id] = op_table[table_mX + id] = &CPUcore::op_##name##_b<&CPUcore::op_##fn##_b, x>; op_table[table_Mx + id] = op_table[table_mx + id] = &CPUcore::op_##name##_w<&CPUcore::op_##fn##_w, x>;
|
||||
|
||||
opEII(0x00, interrupt, 0xfffe, 0xffe6)
|
||||
opMF (0x01, read_idpx, ora)
|
||||
opEII(0x02, interrupt, 0xfff4, 0xffe4)
|
||||
opMF (0x03, read_sr, ora)
|
||||
opMF (0x04, adjust_dp, tsb)
|
||||
opMF (0x05, read_dp, ora)
|
||||
opMF (0x06, adjust_dp, asl)
|
||||
opMF (0x07, read_ildp, ora)
|
||||
opA (0x08, php)
|
||||
opMF (0x09, read_const, ora)
|
||||
opM (0x0a, asl_imm)
|
||||
opE (0x0b, phd)
|
||||
opMF (0x0c, adjust_addr, tsb)
|
||||
opMF (0x0d, read_addr, ora)
|
||||
opMF (0x0e, adjust_addr, asl)
|
||||
opMF (0x0f, read_long, ora)
|
||||
opAII(0x10, branch, 0x80, false)
|
||||
opMF (0x11, read_idpy, ora)
|
||||
opMF (0x12, read_idp, ora)
|
||||
opMF (0x13, read_isry, ora)
|
||||
opMF (0x14, adjust_dp, trb)
|
||||
opMFI(0x15, read_dpr, ora, X)
|
||||
opMF (0x16, adjust_dpx, asl)
|
||||
opMF (0x17, read_ildpy, ora)
|
||||
opAII(0x18, flag, 0x01, 0x00)
|
||||
opMF (0x19, read_addry, ora)
|
||||
opMII(0x1a, adjust_imm, A, +1)
|
||||
opE (0x1b, tcs)
|
||||
opMF (0x1c, adjust_addr, trb)
|
||||
opMF (0x1d, read_addrx, ora)
|
||||
opMF (0x1e, adjust_addrx, asl)
|
||||
opMF (0x1f, read_longx, ora)
|
||||
opA (0x20, jsr_addr)
|
||||
opMF (0x21, read_idpx, and)
|
||||
opE (0x22, jsr_long)
|
||||
opMF (0x23, read_sr, and)
|
||||
opMF (0x24, read_dp, bit)
|
||||
opMF (0x25, read_dp, and)
|
||||
opMF (0x26, adjust_dp, rol)
|
||||
opMF (0x27, read_ildp, and)
|
||||
opE (0x28, plp)
|
||||
opMF (0x29, read_const, and)
|
||||
opM (0x2a, rol_imm)
|
||||
opE (0x2b, pld)
|
||||
opMF (0x2c, read_addr, bit)
|
||||
opMF (0x2d, read_addr, and)
|
||||
opMF (0x2e, adjust_addr, rol)
|
||||
opMF (0x2f, read_long, and)
|
||||
opAII(0x30, branch, 0x80, true)
|
||||
opMF (0x31, read_idpy, and)
|
||||
opMF (0x32, read_idp, and)
|
||||
opMF (0x33, read_isry, and)
|
||||
opMFI(0x34, read_dpr, bit, X)
|
||||
opMFI(0x35, read_dpr, and, X)
|
||||
opMF (0x36, adjust_dpx, rol)
|
||||
opMF (0x37, read_ildpy, and)
|
||||
opAII(0x38, flag, 0x01, 0x01)
|
||||
opMF (0x39, read_addry, and)
|
||||
opMII(0x3a, adjust_imm, A, -1)
|
||||
opE (0x3b, tsc)
|
||||
opMF (0x3c, read_addrx, bit)
|
||||
opMF (0x3d, read_addrx, and)
|
||||
opMF (0x3e, adjust_addrx, rol)
|
||||
opMF (0x3f, read_longx, and)
|
||||
opE (0x40, rti)
|
||||
opMF (0x41, read_idpx, eor)
|
||||
opA (0x42, wdm)
|
||||
opMF (0x43, read_sr, eor)
|
||||
opXI (0x44, move, -1)
|
||||
opMF (0x45, read_dp, eor)
|
||||
opMF (0x46, adjust_dp, lsr)
|
||||
opMF (0x47, read_ildp, eor)
|
||||
opMI (0x48, push, A)
|
||||
opMF (0x49, read_const, eor)
|
||||
opM (0x4a, lsr_imm)
|
||||
opA (0x4b, phk)
|
||||
opA (0x4c, jmp_addr)
|
||||
opMF (0x4d, read_addr, eor)
|
||||
opMF (0x4e, adjust_addr, lsr)
|
||||
opMF (0x4f, read_long, eor)
|
||||
opAII(0x50, branch, 0x40, false)
|
||||
opMF (0x51, read_idpy, eor)
|
||||
opMF (0x52, read_idp, eor)
|
||||
opMF (0x53, read_isry, eor)
|
||||
opXI (0x54, move, +1)
|
||||
opMFI(0x55, read_dpr, eor, X)
|
||||
opMF (0x56, adjust_dpx, lsr)
|
||||
opMF (0x57, read_ildpy, eor)
|
||||
opAII(0x58, flag, 0x04, 0x00)
|
||||
opMF (0x59, read_addry, eor)
|
||||
opXI (0x5a, push, Y)
|
||||
opAII(0x5b, transfer_w, A, D)
|
||||
opA (0x5c, jmp_long)
|
||||
opMF (0x5d, read_addrx, eor)
|
||||
opMF (0x5e, adjust_addrx, lsr)
|
||||
opMF (0x5f, read_longx, eor)
|
||||
opA (0x60, rts)
|
||||
opMF (0x61, read_idpx, adc)
|
||||
opE (0x62, per)
|
||||
opMF (0x63, read_sr, adc)
|
||||
opMI (0x64, write_dp, Z)
|
||||
opMF (0x65, read_dp, adc)
|
||||
opMF (0x66, adjust_dp, ror)
|
||||
opMF (0x67, read_ildp, adc)
|
||||
opMI (0x68, pull, A)
|
||||
opMF (0x69, read_const, adc)
|
||||
opM (0x6a, ror_imm)
|
||||
opE (0x6b, rtl)
|
||||
opA (0x6c, jmp_iaddr)
|
||||
opMF (0x6d, read_addr, adc)
|
||||
opMF (0x6e, adjust_addr, ror)
|
||||
opMF (0x6f, read_long, adc)
|
||||
opAII(0x70, branch, 0x40, true)
|
||||
opMF (0x71, read_idpy, adc)
|
||||
opMF (0x72, read_idp, adc)
|
||||
opMF (0x73, read_isry, adc)
|
||||
opMII(0x74, write_dpr, Z, X)
|
||||
opMFI(0x75, read_dpr, adc, X)
|
||||
opMF (0x76, adjust_dpx, ror)
|
||||
opMF (0x77, read_ildpy, adc)
|
||||
opAII(0x78, flag, 0x04, 0x04)
|
||||
opMF (0x79, read_addry, adc)
|
||||
opXI (0x7a, pull, Y)
|
||||
opAII(0x7b, transfer_w, D, A)
|
||||
opA (0x7c, jmp_iaddrx)
|
||||
opMF (0x7d, read_addrx, adc)
|
||||
opMF (0x7e, adjust_addrx, ror)
|
||||
opMF (0x7f, read_longx, adc)
|
||||
opA (0x80, bra)
|
||||
opM (0x81, sta_idpx)
|
||||
opA (0x82, brl)
|
||||
opM (0x83, sta_sr)
|
||||
opXI (0x84, write_dp, Y)
|
||||
opMI (0x85, write_dp, A)
|
||||
opXI (0x86, write_dp, X)
|
||||
opM (0x87, sta_ildp)
|
||||
opXII(0x88, adjust_imm, Y, -1)
|
||||
opM (0x89, read_bit_const)
|
||||
opMII(0x8a, transfer, X, A)
|
||||
opA (0x8b, phb)
|
||||
opXI (0x8c, write_addr, Y)
|
||||
opMI (0x8d, write_addr, A)
|
||||
opXI (0x8e, write_addr, X)
|
||||
opMI (0x8f, write_longr, Z)
|
||||
opAII(0x90, branch, 0x01, false)
|
||||
opM (0x91, sta_idpy)
|
||||
opM (0x92, sta_idp)
|
||||
opM (0x93, sta_isry)
|
||||
opXII(0x94, write_dpr, Y, X)
|
||||
opMII(0x95, write_dpr, A, X)
|
||||
opXII(0x96, write_dpr, X, Y)
|
||||
opM (0x97, sta_ildpy)
|
||||
opMII(0x98, transfer, Y, A)
|
||||
opMII(0x99, write_addrr, A, Y)
|
||||
opE (0x9a, txs)
|
||||
opXII(0x9b, transfer, X, Y)
|
||||
opMI (0x9c, write_addr, Z)
|
||||
opMII(0x9d, write_addrr, A, X)
|
||||
opMII(0x9e, write_addrr, Z, X)
|
||||
opMI (0x9f, write_longr, X)
|
||||
opXF (0xa0, read_const, ldy)
|
||||
opMF (0xa1, read_idpx, lda)
|
||||
opXF (0xa2, read_const, ldx)
|
||||
opMF (0xa3, read_sr, lda)
|
||||
opXF (0xa4, read_dp, ldy)
|
||||
opMF (0xa5, read_dp, lda)
|
||||
opXF (0xa6, read_dp, ldx)
|
||||
opMF (0xa7, read_ildp, lda)
|
||||
opXII(0xa8, transfer, A, Y)
|
||||
opMF (0xa9, read_const, lda)
|
||||
opXII(0xaa, transfer, A, X)
|
||||
opA (0xab, plb)
|
||||
opXF (0xac, read_addr, ldy)
|
||||
opMF (0xad, read_addr, lda)
|
||||
opXF (0xae, read_addr, ldx)
|
||||
opMF (0xaf, read_long, lda)
|
||||
opAII(0xb0, branch, 0x01, true)
|
||||
opMF (0xb1, read_idpy, lda)
|
||||
opMF (0xb2, read_idp, lda)
|
||||
opMF (0xb3, read_isry, lda)
|
||||
opXFI(0xb4, read_dpr, ldy, X)
|
||||
opMFI(0xb5, read_dpr, lda, X)
|
||||
opXFI(0xb6, read_dpr, ldx, Y)
|
||||
opMF (0xb7, read_ildpy, lda)
|
||||
opAII(0xb8, flag, 0x40, 0x00)
|
||||
opMF (0xb9, read_addry, lda)
|
||||
opX (0xba, tsx)
|
||||
opXII(0xbb, transfer, Y, X)
|
||||
opXF (0xbc, read_addrx, ldy)
|
||||
opMF (0xbd, read_addrx, lda)
|
||||
opXF (0xbe, read_addry, ldx)
|
||||
opMF (0xbf, read_longx, lda)
|
||||
opXF (0xc0, read_const, cpy)
|
||||
opMF (0xc1, read_idpx, cmp)
|
||||
opEI (0xc2, pflag, 0)
|
||||
opMF (0xc3, read_sr, cmp)
|
||||
opXF (0xc4, read_dp, cpy)
|
||||
opMF (0xc5, read_dp, cmp)
|
||||
opMF (0xc6, adjust_dp, dec)
|
||||
opMF (0xc7, read_ildp, cmp)
|
||||
opXII(0xc8, adjust_imm, Y, +1)
|
||||
opMF (0xc9, read_const, cmp)
|
||||
opXII(0xca, adjust_imm, X, -1)
|
||||
opA (0xcb, wai)
|
||||
opXF (0xcc, read_addr, cpy)
|
||||
opMF (0xcd, read_addr, cmp)
|
||||
opMF (0xce, adjust_addr, dec)
|
||||
opMF (0xcf, read_long, cmp)
|
||||
opAII(0xd0, branch, 0x02, false)
|
||||
opMF (0xd1, read_idpy, cmp)
|
||||
opMF (0xd2, read_idp, cmp)
|
||||
opMF (0xd3, read_isry, cmp)
|
||||
opE (0xd4, pei)
|
||||
opMFI(0xd5, read_dpr, cmp, X)
|
||||
opMF (0xd6, adjust_dpx, dec)
|
||||
opMF (0xd7, read_ildpy, cmp)
|
||||
opAII(0xd8, flag, 0x08, 0x00)
|
||||
opMF (0xd9, read_addry, cmp)
|
||||
opXI (0xda, push, X)
|
||||
opA (0xdb, stp)
|
||||
opA (0xdc, jmp_iladdr)
|
||||
opMF (0xdd, read_addrx, cmp)
|
||||
opMF (0xde, adjust_addrx, dec)
|
||||
opMF (0xdf, read_longx, cmp)
|
||||
opXF (0xe0, read_const, cpx)
|
||||
opMF (0xe1, read_idpx, sbc)
|
||||
opEI (0xe2, pflag, 1)
|
||||
opMF (0xe3, read_sr, sbc)
|
||||
opXF (0xe4, read_dp, cpx)
|
||||
opMF (0xe5, read_dp, sbc)
|
||||
opMF (0xe6, adjust_dp, inc)
|
||||
opMF (0xe7, read_ildp, sbc)
|
||||
opXII(0xe8, adjust_imm, X, +1)
|
||||
opMF (0xe9, read_const, sbc)
|
||||
opA (0xea, nop)
|
||||
opA (0xeb, xba)
|
||||
opXF (0xec, read_addr, cpx)
|
||||
opMF (0xed, read_addr, sbc)
|
||||
opMF (0xee, adjust_addr, inc)
|
||||
opMF (0xef, read_long, sbc)
|
||||
opAII(0xf0, branch, 0x02, true)
|
||||
opMF (0xf1, read_idpy, sbc)
|
||||
opMF (0xf2, read_idp, sbc)
|
||||
opMF (0xf3, read_isry, sbc)
|
||||
opE (0xf4, pea)
|
||||
opMFI(0xf5, read_dpr, sbc, X)
|
||||
opMF (0xf6, adjust_dpx, inc)
|
||||
opMF (0xf7, read_ildpy, sbc)
|
||||
opAII(0xf8, flag, 0x08, 0x08)
|
||||
opMF (0xf9, read_addry, sbc)
|
||||
opXI (0xfa, pull, X)
|
||||
opA (0xfb, xce)
|
||||
opE (0xfc, jsr_iaddrx)
|
||||
opMF (0xfd, read_addrx, sbc)
|
||||
opMF (0xfe, adjust_addrx, inc)
|
||||
opMF (0xff, read_longx, sbc)
|
||||
|
||||
#undef opA
|
||||
#undef opAII
|
||||
#undef opE
|
||||
#undef opEI
|
||||
#undef opEII
|
||||
#undef opM
|
||||
#undef opMI
|
||||
#undef opMII
|
||||
#undef opMF
|
||||
#undef opMFI
|
||||
#undef opX
|
||||
#undef opXI
|
||||
#undef opXII
|
||||
#undef opXF
|
||||
#undef opXFI
|
||||
}
|
||||
|
||||
void CPUcore::update_table() {
|
||||
if(regs.e) {
|
||||
opcode_table = &op_table[table_EM];
|
||||
} else if(regs.p.m) {
|
||||
if(regs.p.x) {
|
||||
opcode_table = &op_table[table_MX];
|
||||
} else {
|
||||
opcode_table = &op_table[table_Mx];
|
||||
}
|
||||
} else {
|
||||
if(regs.p.x) {
|
||||
opcode_table = &op_table[table_mX];
|
||||
} else {
|
||||
opcode_table = &op_table[table_mx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,6 +8,12 @@ void CPU::power() {
|
|||
}
|
||||
|
||||
void CPU::reset() {
|
||||
PPUcounter::reset();
|
||||
}
|
||||
|
||||
void CPU::serialize(serializer &s) {
|
||||
PPUcounter::serialize(s);
|
||||
s.integer(cpu_version);
|
||||
}
|
||||
|
||||
CPU::CPU() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class CPU : public MMIO {
|
||||
class CPU : public PPUcounter, public MMIO {
|
||||
public:
|
||||
virtual void enter() = 0;
|
||||
|
||||
|
@ -17,6 +17,7 @@ public:
|
|||
virtual void power();
|
||||
virtual void reset();
|
||||
|
||||
virtual void serialize(serializer&);
|
||||
CPU();
|
||||
virtual ~CPU();
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@ uint8 sCPU::op_read(uint32 addr) {
|
|||
status.clock_count = speed(addr);
|
||||
cycle_edge();
|
||||
add_clocks(status.clock_count - 4);
|
||||
scheduler.sync_cpucop();
|
||||
regs.mdr = bus.read(addr);
|
||||
add_clocks(4);
|
||||
return regs.mdr;
|
||||
|
@ -20,7 +19,6 @@ void sCPU::op_write(uint32 addr, uint8 data) {
|
|||
status.clock_count = speed(addr);
|
||||
cycle_edge();
|
||||
add_clocks(status.clock_count);
|
||||
scheduler.sync_cpucop();
|
||||
bus.write(addr, regs.mdr = data);
|
||||
}
|
||||
|
||||
|
|
|
@ -190,13 +190,13 @@ uint8 sCPU::mmio_r4212() {
|
|||
uint16 vs = ppu.overscan() == false ? 225 : 240;
|
||||
|
||||
//auto joypad polling
|
||||
if(ppu.vcounter() >= vs && ppu.vcounter() <= (vs + 2))r |= 0x01;
|
||||
if(vcounter() >= vs && vcounter() <= (vs + 2))r |= 0x01;
|
||||
|
||||
//hblank
|
||||
if(ppu.hcounter() <= 2 || ppu.hcounter() >= 1096)r |= 0x40;
|
||||
if(hcounter() <= 2 || hcounter() >= 1096)r |= 0x40;
|
||||
|
||||
//vblank
|
||||
if(ppu.vcounter() >= vs)r |= 0x80;
|
||||
if(vcounter() >= vs)r |= 0x80;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#include <../base.hpp>
|
||||
#include <nall/priorityqueue.hpp>
|
||||
|
||||
#define SCPU_CPP
|
||||
namespace SNES {
|
||||
|
||||
priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu));
|
||||
#include "serialization.cpp"
|
||||
|
||||
#include "dma/dma.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
|
@ -12,11 +11,12 @@ priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu));
|
|||
#include "timing/timing.cpp"
|
||||
|
||||
void sCPU::enter() {
|
||||
regs.pc.l = bus.read(0xfffc);
|
||||
regs.pc.h = bus.read(0xfffd);
|
||||
add_clocks(186);
|
||||
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SyncCpu) {
|
||||
scheduler.sync = Scheduler::SyncAll;
|
||||
scheduler.exit();
|
||||
}
|
||||
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
if(status.nmi_pending) {
|
||||
|
@ -89,9 +89,13 @@ void sCPU::reset() {
|
|||
apu_port[1] = 0x00;
|
||||
apu_port[2] = 0x00;
|
||||
apu_port[3] = 0x00;
|
||||
|
||||
regs.pc.l = bus.read(0xfffc);
|
||||
regs.pc.h = bus.read(0xfffd);
|
||||
}
|
||||
|
||||
sCPU::sCPU() {
|
||||
sCPU::sCPU() : event(512, bind(&sCPU::queue_event, this)) {
|
||||
PPUcounter::scanline = bind(&sCPU::scanline, this);
|
||||
}
|
||||
|
||||
sCPU::~sCPU() {
|
||||
|
|
|
@ -9,6 +9,8 @@ public:
|
|||
#include "mmio/mmio.hpp"
|
||||
#include "timing/timing.hpp"
|
||||
|
||||
priority_queue<unsigned> event;
|
||||
|
||||
struct {
|
||||
bool interrupt_pending;
|
||||
uint16 interrupt_vector;
|
||||
|
@ -86,6 +88,7 @@ public:
|
|||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
sCPU();
|
||||
~sCPU();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
#ifdef SCPU_CPP
|
||||
|
||||
void sCPU::serialize(serializer &s) {
|
||||
CPU::serialize(s);
|
||||
CPUcore::core_serialize(s);
|
||||
|
||||
event.serialize(s);
|
||||
|
||||
s.integer(status.interrupt_pending);
|
||||
s.integer(status.interrupt_vector);
|
||||
|
||||
s.integer(status.clock_count);
|
||||
s.integer(status.line_clocks);
|
||||
|
||||
s.integer(status.irq_lock);
|
||||
s.integer(status.alu_lock);
|
||||
s.integer(status.dram_refresh_position);
|
||||
|
||||
s.integer(status.nmi_valid);
|
||||
s.integer(status.nmi_line);
|
||||
s.integer(status.nmi_transition);
|
||||
s.integer(status.nmi_pending);
|
||||
s.integer(status.nmi_hold);
|
||||
|
||||
s.integer(status.irq_valid);
|
||||
s.integer(status.irq_line);
|
||||
s.integer(status.irq_transition);
|
||||
s.integer(status.irq_pending);
|
||||
s.integer(status.irq_hold);
|
||||
|
||||
s.integer(status.dma_active);
|
||||
s.integer(status.dma_counter);
|
||||
s.integer(status.dma_clocks);
|
||||
s.integer(status.dma_pending);
|
||||
s.integer(status.hdma_pending);
|
||||
s.integer(status.hdma_mode);
|
||||
|
||||
s.integer(status.wram_addr);
|
||||
|
||||
s.integer(status.joypad_strobe_latch);
|
||||
s.integer(status.joypad1_bits);
|
||||
s.integer(status.joypad2_bits);
|
||||
|
||||
s.integer(status.nmi_enabled);
|
||||
s.integer(status.hirq_enabled);
|
||||
s.integer(status.virq_enabled);
|
||||
s.integer(status.auto_joypad_poll);
|
||||
|
||||
s.integer(status.pio);
|
||||
|
||||
s.integer(status.mul_a);
|
||||
s.integer(status.mul_b);
|
||||
|
||||
s.integer(status.div_a);
|
||||
s.integer(status.div_b);
|
||||
|
||||
s.integer(status.hirq_pos);
|
||||
s.integer(status.virq_pos);
|
||||
|
||||
s.integer(status.rom_speed);
|
||||
|
||||
s.integer(status.r4214);
|
||||
s.integer(status.r4216);
|
||||
|
||||
s.integer(status.joy1l);
|
||||
s.integer(status.joy1h);
|
||||
s.integer(status.joy2l);
|
||||
s.integer(status.joy2h);
|
||||
s.integer(status.joy3l);
|
||||
s.integer(status.joy3h);
|
||||
s.integer(status.joy4l);
|
||||
s.integer(status.joy4h);
|
||||
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
s.integer(channel[i].dma_enabled);
|
||||
s.integer(channel[i].hdma_enabled);
|
||||
s.integer(channel[i].dmap);
|
||||
s.integer(channel[i].direction);
|
||||
s.integer(channel[i].hdma_indirect);
|
||||
s.integer(channel[i].reversexfer);
|
||||
s.integer(channel[i].fixedxfer);
|
||||
s.integer(channel[i].xfermode);
|
||||
s.integer(channel[i].destaddr);
|
||||
s.integer(channel[i].srcaddr);
|
||||
s.integer(channel[i].srcbank);
|
||||
s.integer(channel[i].xfersize);
|
||||
s.integer(channel[i].hdma_ibank);
|
||||
s.integer(channel[i].hdma_addr);
|
||||
s.integer(channel[i].hdma_line_counter);
|
||||
s.integer(channel[i].unknown);
|
||||
s.integer(channel[i].hdma_completed);
|
||||
s.integer(channel[i].hdma_do_transfer);
|
||||
}
|
||||
|
||||
s.integer(apu_port[0]);
|
||||
s.integer(apu_port[1]);
|
||||
s.integer(apu_port[2]);
|
||||
s.integer(apu_port[3]);
|
||||
|
||||
s.integer(cycle_edge_state);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,7 +13,7 @@ void sCPU::poll_interrupts() {
|
|||
}
|
||||
|
||||
//NMI test
|
||||
bool nmi_valid = (ppu.vcounter(2) >= (!ppu.overscan() ? 225 : 240));
|
||||
bool nmi_valid = (vcounter(2) >= (!ppu.overscan() ? 225 : 240));
|
||||
if(!status.nmi_valid && nmi_valid) {
|
||||
//0->1 edge sensitive transition
|
||||
status.nmi_line = true;
|
||||
|
@ -33,9 +33,9 @@ void sCPU::poll_interrupts() {
|
|||
//IRQ test
|
||||
bool irq_valid = (status.virq_enabled || status.hirq_enabled);
|
||||
if(irq_valid) {
|
||||
if((status.virq_enabled && ppu.vcounter(10) != (status.virq_pos))
|
||||
|| (status.hirq_enabled && ppu.hcounter(10) != (status.hirq_pos + 1) * 4)
|
||||
|| (status.virq_pos && ppu.vcounter(6) == 0) //IRQs cannot trigger on last dot of field
|
||||
if((status.virq_enabled && vcounter(10) != (status.virq_pos))
|
||||
|| (status.hirq_enabled && hcounter(10) != (status.hirq_pos + 1) * 4)
|
||||
|| (status.virq_pos && vcounter(6) == 0) //IRQs cannot trigger on last dot of field
|
||||
) irq_valid = false;
|
||||
}
|
||||
if(!status.irq_valid && irq_valid) {
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
#include "joypad.cpp"
|
||||
|
||||
unsigned sCPU::dma_counter() {
|
||||
return (status.dma_counter + ppu.hcounter()) & 7;
|
||||
return (status.dma_counter + hcounter()) & 7;
|
||||
}
|
||||
|
||||
void sCPU::add_clocks(unsigned clocks) {
|
||||
event.tick(clocks);
|
||||
unsigned ticks = clocks >> 1;
|
||||
while(ticks--) {
|
||||
ppu.tick();
|
||||
if(ppu.hcounter() & 2) {
|
||||
tick();
|
||||
if(hcounter() & 2) {
|
||||
input.tick();
|
||||
poll_interrupts();
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ void sCPU::add_clocks(unsigned clocks) {
|
|||
//called by ppu.tick() when Hcounter=0
|
||||
void sCPU::scanline() {
|
||||
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
|
||||
status.line_clocks = ppu.lineclocks();
|
||||
status.line_clocks = lineclocks();
|
||||
|
||||
//forcefully sync S-CPU to other processors, in case chips are not communicating
|
||||
scheduler.sync_cpuppu();
|
||||
|
@ -32,7 +32,7 @@ void sCPU::scanline() {
|
|||
scheduler.sync_cpusmp();
|
||||
system.scanline();
|
||||
|
||||
if(ppu.vcounter() == 0) {
|
||||
if(vcounter() == 0) {
|
||||
//hdma init triggers once every frame
|
||||
event.enqueue(cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter(), EventHdmaInit);
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ void sCPU::scanline() {
|
|||
event.enqueue(status.dram_refresh_position, EventDramRefresh);
|
||||
|
||||
//hdma triggers once every visible scanline
|
||||
if(ppu.vcounter() <= (ppu.overscan() == false ? 224 : 239)) {
|
||||
if(vcounter() <= (ppu.overscan() == false ? 224 : 239)) {
|
||||
event.enqueue(1104, EventHdmaRun);
|
||||
}
|
||||
|
||||
if(status.auto_joypad_poll == true && ppu.vcounter() == (ppu.overscan() == false ? 227 : 242)) {
|
||||
if(status.auto_joypad_poll == true && vcounter() == (ppu.overscan() == false ? 227 : 242)) {
|
||||
input.poll();
|
||||
run_auto_joypad_poll();
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ void sCPU::timing_reset() {
|
|||
event.reset();
|
||||
|
||||
status.clock_count = 0;
|
||||
status.line_clocks = ppu.lineclocks();
|
||||
status.line_clocks = lineclocks();
|
||||
|
||||
status.irq_lock = false;
|
||||
status.alu_lock = false;
|
||||
|
|
|
@ -51,10 +51,6 @@ are contrary to the design goals of this emulator. As a result, most BS-X
|
|||
software will not function correctly.<br>
|
||||
<br>
|
||||
|
||||
<b>Savestates:</b> due to the internal design of bsnes, it is not plausible to
|
||||
implement support for savestate and/or rewind functionality.<br>
|
||||
<br>
|
||||
|
||||
<b>Netplay:</b> internet multiplay is not currently supported nor planned.
|
||||
<hr>
|
||||
|
||||
|
|
|
@ -8,6 +8,5 @@ public:
|
|||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
DSP() {}
|
||||
virtual ~DSP() {}
|
||||
virtual void serialize(serializer&) {}
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/*
|
||||
S-DSP emulator
|
||||
Note: this is basically a C++ cothreaded implementation of Shay Green's (blargg's) S-DSP emulator.
|
||||
The actual algorithms, timing information, tables, variable names, etc were all from him.
|
||||
*/
|
||||
//S-DSP emulator
|
||||
//note: this is basically a C++ cothreaded implementation of Shay Green's (blargg's) S-DSP emulator.
|
||||
//the actual algorithms, timing information, tables, variable names, etc were all from him.
|
||||
|
||||
#include <../base.hpp>
|
||||
|
||||
#define SDSP_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "serialization.cpp"
|
||||
|
||||
#define REG(n) state.regs[r_##n]
|
||||
#define VREG(n) state.regs[v.vidx + v_##n]
|
||||
|
||||
#if !defined(DSP_STATE_MACHINE)
|
||||
#define phase_start() while(true) {
|
||||
#define phase_start() while(true) { if(scheduler.sync == Scheduler::SyncAll) scheduler.exit();
|
||||
#define phase(n)
|
||||
#define tick() scheduler.addclocks_dsp(3 * 8); scheduler.sync_dspsmp()
|
||||
#define phase_end() }
|
||||
|
@ -311,11 +311,11 @@ void sDSP::reset() {
|
|||
}
|
||||
|
||||
sDSP::sDSP() {
|
||||
static_assert<sizeof(int) >= 32 / 8>(); //int >= 32-bits
|
||||
static_assert<(int8_t)0x80 == -0x80>(); //8-bit sign extension
|
||||
static_assert<(int16_t)0x8000 == -0x8000>(); //16-bit sign extension
|
||||
static_assert<(uint16_t)0xffff0000 == 0>(); //16-bit unsigned clip
|
||||
static_assert<(-1 >> 1) == -1>(); //arithmetic shift right
|
||||
static_assert<sizeof(int) >= 32 / 8>(); //int >= 32-bits
|
||||
static_assert<(int8)0x80 == -0x80>(); //8-bit sign extension
|
||||
static_assert<(int16)0x8000 == -0x8000>(); //16-bit sign extension
|
||||
static_assert<(uint16)0xffff0000 == 0>(); //16-bit unsigned clip
|
||||
static_assert<(-1 >> 1) == -1>(); //arithmetic shift right
|
||||
|
||||
//-0x8000 <= n <= +0x7fff
|
||||
assert(sclamp<16>(+0x8000) == +0x7fff);
|
||||
|
|
|
@ -8,11 +8,12 @@ public:
|
|||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
sDSP();
|
||||
~sDSP();
|
||||
|
||||
private:
|
||||
//USE_STATE_MACHINE variable
|
||||
//DSP_STATE_MACHINE variable
|
||||
unsigned phase_index;
|
||||
|
||||
//global registers
|
||||
|
@ -105,7 +106,7 @@ private:
|
|||
int vbit; //bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc
|
||||
int vidx; //voice channel register index: 0x00 for voice 0, 0x10 for voice 1, etc
|
||||
int kon_delay; //KON delay/current setup phase
|
||||
env_mode_t env_mode;
|
||||
int env_mode;
|
||||
int env; //current envelope level
|
||||
int t_envx_out;
|
||||
int hidden_env; //used by GAIN mode 7, very obscure quirk
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
#ifdef SDSP_CPP
|
||||
|
||||
void sDSP::serialize(serializer &s) {
|
||||
DSP::serialize(s);
|
||||
|
||||
s.integer(phase_index);
|
||||
|
||||
s.array(state.regs, 128);
|
||||
state.echo_hist[0].serialize(s);
|
||||
state.echo_hist[1].serialize(s);
|
||||
s.integer(state.echo_hist_pos);
|
||||
|
||||
s.integer(state.every_other_sample);
|
||||
s.integer(state.kon);
|
||||
s.integer(state.noise);
|
||||
s.integer(state.counter);
|
||||
s.integer(state.echo_offset);
|
||||
s.integer(state.echo_length);
|
||||
|
||||
s.integer(state.new_kon);
|
||||
s.integer(state.endx_buf);
|
||||
s.integer(state.envx_buf);
|
||||
s.integer(state.outx_buf);
|
||||
|
||||
s.integer(state.t_pmon);
|
||||
s.integer(state.t_non);
|
||||
s.integer(state.t_eon);
|
||||
s.integer(state.t_dir);
|
||||
s.integer(state.t_koff);
|
||||
|
||||
s.integer(state.t_brr_next_addr);
|
||||
s.integer(state.t_adsr0);
|
||||
s.integer(state.t_brr_header);
|
||||
s.integer(state.t_brr_byte);
|
||||
s.integer(state.t_srcn);
|
||||
s.integer(state.t_esa);
|
||||
s.integer(state.t_echo_disabled);
|
||||
|
||||
s.integer(state.t_dir_addr);
|
||||
s.integer(state.t_pitch);
|
||||
s.integer(state.t_output);
|
||||
s.integer(state.t_looped);
|
||||
s.integer(state.t_echo_ptr);
|
||||
|
||||
s.integer(state.t_main_out[0]);
|
||||
s.integer(state.t_main_out[1]);
|
||||
s.integer(state.t_echo_out[0]);
|
||||
s.integer(state.t_echo_out[1]);
|
||||
s.integer(state.t_echo_in [0]);
|
||||
s.integer(state.t_echo_in [1]);
|
||||
|
||||
for(unsigned n = 0; n < 8; n++) {
|
||||
voice[n].buffer.serialize(s);
|
||||
s.integer(voice[n].buf_pos);
|
||||
s.integer(voice[n].interp_pos);
|
||||
s.integer(voice[n].brr_addr);
|
||||
s.integer(voice[n].brr_offset);
|
||||
s.integer(voice[n].vbit);
|
||||
s.integer(voice[n].vidx);
|
||||
s.integer(voice[n].kon_delay);
|
||||
s.integer(voice[n].env_mode);
|
||||
s.integer(voice[n].env);
|
||||
s.integer(voice[n].t_envx_out);
|
||||
s.integer(voice[n].hidden_env);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,9 +1,10 @@
|
|||
namespace SNES {
|
||||
#include "cheat/cheat.hpp"
|
||||
|
||||
#include "memory/memory.hpp"
|
||||
#include "memory/smemory/smemory.hpp"
|
||||
|
||||
#include "ppu/ppu.hpp"
|
||||
#include "ppu/bppu/bppu.hpp"
|
||||
|
||||
#include "cpu/cpu.hpp"
|
||||
#include "cpu/core/core.hpp"
|
||||
#include "cpu/scpu/scpu.hpp"
|
||||
|
@ -12,19 +13,21 @@ namespace SNES {
|
|||
#include "smp/core/core.hpp"
|
||||
#include "smp/ssmp/ssmp.hpp"
|
||||
|
||||
#include "ppu/ppu.hpp"
|
||||
#include "ppu/bppu/bppu.hpp"
|
||||
|
||||
#include "dsp/dsp.hpp"
|
||||
#include "dsp/sdsp/sdsp.hpp"
|
||||
|
||||
extern BUSCORE bus;
|
||||
extern CPUCORE cpu;
|
||||
extern SMPCORE smp;
|
||||
extern DSPCORE dsp;
|
||||
extern PPUCORE ppu;
|
||||
extern DSPCORE dsp;
|
||||
|
||||
#include "system/system.hpp"
|
||||
#include "chip/chip.hpp"
|
||||
#include "cartridge/cartridge.hpp"
|
||||
#include "cheat/cheat.hpp"
|
||||
|
||||
#include "memory/memory-inline.hpp"
|
||||
#include "ppu/ppu-inline.hpp"
|
||||
#include "cheat/cheat-inline.hpp"
|
||||
};
|
||||
|
|
|
@ -1,175 +0,0 @@
|
|||
#include "bpp.hpp"
|
||||
|
||||
bool BPP::process_macro(Macro ¯o, const lstring &arg) {
|
||||
lstring linedata;
|
||||
linedata.split("\n", macro.data);
|
||||
|
||||
for(unsigned i = 0; i < linedata.size(); i++) {
|
||||
string line = linedata[i];
|
||||
|
||||
for(unsigned j = 0; j < macro.args; j++) {
|
||||
line.replace(macro.arg[j], arg[j]);
|
||||
}
|
||||
|
||||
for(unsigned j = 0; j < global.size(); j++) {
|
||||
line.replace(global[j].name, global[j].data);
|
||||
}
|
||||
|
||||
output.print(string() << line << "\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BPP::process(const char *inputfn) {
|
||||
string filedata;
|
||||
if(filedata.readfile(inputfn) == false) {
|
||||
fprintf(stdout, "error: failed to open input file '%s'\n", inputfn);
|
||||
return false;
|
||||
}
|
||||
|
||||
filedata.replace("\r", "");
|
||||
lstring linedata;
|
||||
linedata.split("\n", filedata);
|
||||
|
||||
for(unsigned i = 0; i < linedata.size();) {
|
||||
string line = linedata[i];
|
||||
trim(line);
|
||||
line.replace("\t", " ");
|
||||
|
||||
if(strbegin(line, "@") == false) {
|
||||
output.print(string() << linedata[i] << "\n");
|
||||
i++;
|
||||
} else if(strbegin(line, "@include ")) {
|
||||
ltrim(line, "@include ");
|
||||
trim(line, "\"");
|
||||
if(process(line) == false) return false;
|
||||
i++;
|
||||
} else if(strbegin(line, "@global ")) {
|
||||
ltrim(line, "@global ");
|
||||
while(qstrpos(line, " ") >= 0) line.replace(" ", " ");
|
||||
|
||||
lstring part;
|
||||
part.qsplit(" ", line);
|
||||
if(part.size() != 2) {
|
||||
fprintf(stdout, "error: malformed global\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned n = global.size();
|
||||
global[n].name = string() << "{" << part[0] << "}";
|
||||
global[n].data = trim(part[1], "\"");
|
||||
i++;
|
||||
} else if(strbegin(line, "@macro ")) {
|
||||
ltrim(line, "@macro ");
|
||||
|
||||
int pos = strpos(line, "(");
|
||||
if(pos < 0 || !strend(line, ")")) {
|
||||
fprintf(stdout, "error: malformed macro\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
string name = substr(line, 0, pos);
|
||||
line = substr(line, pos);
|
||||
ltrim(line, "(");
|
||||
rtrim(line, ")");
|
||||
line.qreplace(" ", "");
|
||||
|
||||
unsigned n = macro.size();
|
||||
macro[n].name = name;
|
||||
|
||||
if(line == "") {
|
||||
macro[n].args = 0;
|
||||
} else {
|
||||
lstring arg;
|
||||
arg.split(",", line);
|
||||
if(arg.size() >= 8) {
|
||||
fprintf(stdout, "error: too many macro arguments\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
macro[n].args = arg.size();
|
||||
for(unsigned j = 0; j < arg.size(); j++) {
|
||||
macro[n].arg[j] = string() << "{" << arg[j] << "}";
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
while(i < linedata.size()) {
|
||||
string line = linedata[i];
|
||||
trim(line);
|
||||
if(line == "@endmacro") break;
|
||||
macro[n].data << linedata[i++] << "\n";
|
||||
}
|
||||
|
||||
i++;
|
||||
} else {
|
||||
ltrim(line, "@");
|
||||
int pos = strpos(line, "(");
|
||||
if(pos < 0 || !strend(line, ")")) {
|
||||
fprintf(stdout, "error: malformed macro invocation\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
string name = substr(line, 0, pos);
|
||||
line = substr(line, pos);
|
||||
ltrim(line, "(");
|
||||
rtrim(line, ")");
|
||||
line.qreplace(" ", "");
|
||||
|
||||
lstring arg;
|
||||
if(line != "") arg.qsplit(",", line);
|
||||
for(unsigned j = 0; j < arg.size(); j++) {
|
||||
trim(arg[j], "\"");
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
for(unsigned j = 0; j < macro.size(); j++) {
|
||||
if(name == macro[j].name && arg.size() == macro[j].args) {
|
||||
success = process_macro(macro[j], arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(success == false) {
|
||||
fprintf(stdout, "error: unable to process macro '%s'\n", (const char*)name);
|
||||
return false;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BPP::process(const char *outputfn, const char *inputfn) {
|
||||
if(file::exists(inputfn) == false) {
|
||||
fprintf(stdout, "error: failed to open input file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(output.open(outputfn, file::mode_write) == false) {
|
||||
fprintf(stdout, "error: failed to open output file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = process(inputfn);
|
||||
output.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
if(argc != 3) {
|
||||
fprintf(stdout, "bpp v0.01\n");
|
||||
fprintf(stdout, "author: byuu\n");
|
||||
fprintf(stdout, "usage: bpp output input\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BPP bpp;
|
||||
bool success = bpp.process(argv[1], argv[2]);
|
||||
if(success == false) fprintf(stdout, "error: pre-processing failed\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
#include <nall/array.hpp>
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
using namespace nall;
|
||||
|
||||
class BPP {
|
||||
public:
|
||||
bool process(const char *outputfn, const char *inputfn);
|
||||
|
||||
private:
|
||||
nall::file output;
|
||||
|
||||
struct Global {
|
||||
string name;
|
||||
string data;
|
||||
};
|
||||
vector<Global> global;
|
||||
|
||||
struct Macro {
|
||||
string name;
|
||||
unsigned args;
|
||||
string arg[8];
|
||||
string data;
|
||||
};
|
||||
vector<Macro> macro;
|
||||
|
||||
bool process_macro(Macro ¯o, const lstring &arg);
|
||||
bool process(const char *inputfn);
|
||||
};
|
|
@ -9,6 +9,7 @@ void FilterInterface::size(unsigned &outwidth, unsigned &outheight, unsigned wid
|
|||
case Direct: return filter_direct.size(outwidth, outheight, width, height);
|
||||
case Scanline: return filter_scanline.size(outwidth, outheight, width, height);
|
||||
case Scale2x: return filter_scale2x.size(outwidth, outheight, width, height);
|
||||
case LQ2x: return filter_lq2x.size(outwidth, outheight, width, height);
|
||||
case HQ2x: return filter_hq2x.size(outwidth, outheight, width, height);
|
||||
case NTSC: return filter_ntsc.size(outwidth, outheight, width, height);
|
||||
}
|
||||
|
@ -22,6 +23,7 @@ void FilterInterface::render(
|
|||
case Direct: return filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
case Scanline: return filter_scanline.render(output, outpitch, input, pitch, line, width, height);
|
||||
case Scale2x: return filter_scale2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case LQ2x: return filter_lq2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case HQ2x: return filter_hq2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case NTSC: return filter_ntsc.render(output, outpitch, input, pitch, line, width, height);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public:
|
|||
Direct,
|
||||
Scanline,
|
||||
Scale2x,
|
||||
LQ2x,
|
||||
HQ2x,
|
||||
NTSC,
|
||||
};
|
||||
|
|
|
@ -1,59 +1,89 @@
|
|||
HQ2xFilter filter_hq2x;
|
||||
|
||||
#define diff(x, y) ((yuvtable[x] - yuvtable[y] + diff_offset) & diff_mask)
|
||||
#define hdiff(x, y) ((x - yuvtable[y]) & diff_mask)
|
||||
#define expand_rgb(n) { n |= n << 16; n &= 0x03e07c1f; }
|
||||
#define pack_rgb(n) { n &= 0x03e07c1f; n |= n >> 16; }
|
||||
const uint8_t HQ2xFilter::hqTable[256] = {
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 15, 12, 5, 3, 17, 13,
|
||||
4, 4, 6, 18, 4, 4, 6, 18, 5, 3, 12, 12, 5, 3, 1, 12,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 17, 13, 5, 3, 16, 14,
|
||||
4, 4, 6, 18, 4, 4, 6, 18, 5, 3, 16, 12, 5, 3, 1, 14,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 19, 12, 12, 5, 19, 16, 12,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 16, 12,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 19, 1, 12, 5, 19, 1, 14,
|
||||
4, 4, 6, 2, 4, 4, 6, 18, 5, 3, 16, 12, 5, 19, 1, 14,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 15, 12, 5, 3, 17, 13,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 16, 12,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 17, 13, 5, 3, 16, 14,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 13, 5, 3, 1, 14,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 16, 13,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 1, 12,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 1, 14,
|
||||
4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 1, 12, 5, 3, 1, 14,
|
||||
};
|
||||
|
||||
static uint16_t blend1(uint32_t c1, uint32_t c2) {
|
||||
expand_rgb(c1);
|
||||
expand_rgb(c2);
|
||||
c1 = (c1 * 3 + c2) >> 2;
|
||||
pack_rgb(c1);
|
||||
return c1;
|
||||
bool HQ2xFilter::same(uint16_t x, uint16_t y) {
|
||||
return !((yuvTable[x] - yuvTable[y] + diff_offset) & diff_mask);
|
||||
}
|
||||
|
||||
static uint16_t blend2(uint32_t c1, uint32_t c2, uint32_t c3) {
|
||||
//c1 = (c1 * 2 + c2 + c3) >> 2;
|
||||
c2 = (c2 + c3 - ((c2 ^ c3) & 0x0421)) >> 1;
|
||||
c1 = (c1 + c2 - ((c1 ^ c2) & 0x0421)) >> 1;
|
||||
return c1;
|
||||
bool HQ2xFilter::diff(uint32_t x, uint16_t y) {
|
||||
return ((x - yuvTable[y]) & diff_mask);
|
||||
}
|
||||
|
||||
static uint16_t blend6(uint32_t c1, uint32_t c2, uint32_t c3) {
|
||||
expand_rgb(c1);
|
||||
expand_rgb(c2);
|
||||
expand_rgb(c3);
|
||||
c1 = (c1 * 5 + c2 * 2 + c3) >> 3;
|
||||
pack_rgb(c1);
|
||||
return c1;
|
||||
void HQ2xFilter::grow(uint32_t &n) { n |= n << 16; n &= 0x03e07c1f; }
|
||||
uint16_t HQ2xFilter::pack(uint32_t n) { n &= 0x03e07c1f; return n | (n >> 16); }
|
||||
|
||||
uint16_t HQ2xFilter::blend1(uint32_t A, uint32_t B) {
|
||||
grow(A); grow(B);
|
||||
A = (A * 3 + B) >> 2;
|
||||
return pack(A);
|
||||
}
|
||||
|
||||
static uint16_t blend7(uint32_t c1, uint32_t c2, uint32_t c3) {
|
||||
expand_rgb(c1);
|
||||
expand_rgb(c2);
|
||||
expand_rgb(c3);
|
||||
c1 = (c1 * 6 + c2 + c3) >> 3;
|
||||
pack_rgb(c1);
|
||||
return c1;
|
||||
uint16_t HQ2xFilter::blend2(uint32_t A, uint32_t B, uint32_t C) {
|
||||
grow(A); grow(B); grow(C);
|
||||
return pack((A * 2 + B + C) >> 2);
|
||||
}
|
||||
|
||||
static uint16_t blend9(uint32_t c1, uint32_t c2, uint32_t c3) {
|
||||
expand_rgb(c1);
|
||||
expand_rgb(c2);
|
||||
expand_rgb(c3);
|
||||
c1 = (c1 * 2 + (c2 + c3) * 3) >> 3;
|
||||
pack_rgb(c1);
|
||||
return c1;
|
||||
uint16_t HQ2xFilter::blend3(uint32_t A, uint32_t B, uint32_t C) {
|
||||
grow(A); grow(B); grow(C);
|
||||
return pack((A * 5 + B * 2 + C) >> 3);
|
||||
}
|
||||
|
||||
static uint16_t blend10(uint32_t c1, uint32_t c2, uint32_t c3) {
|
||||
expand_rgb(c1);
|
||||
expand_rgb(c2);
|
||||
expand_rgb(c3);
|
||||
c1 = (c1 * 14 + c2 + c3) >> 4;
|
||||
pack_rgb(c1);
|
||||
return c1;
|
||||
uint16_t HQ2xFilter::blend4(uint32_t A, uint32_t B, uint32_t C) {
|
||||
grow(A); grow(B); grow(C);
|
||||
return pack((A * 6 + B + C) >> 3);
|
||||
}
|
||||
|
||||
uint16_t HQ2xFilter::blend5(uint32_t A, uint32_t B, uint32_t C) {
|
||||
grow(A); grow(B); grow(C);
|
||||
return pack((A * 2 + (B + C) * 3) >> 3);
|
||||
}
|
||||
|
||||
uint16_t HQ2xFilter::blend6(uint32_t A, uint32_t B, uint32_t C) {
|
||||
grow(A); grow(B); grow(C);
|
||||
return pack((A * 14 + B + C) >> 4);
|
||||
}
|
||||
|
||||
alwaysinline uint16_t HQ2xFilter::blend(unsigned rule, uint16_t E, uint16_t A, uint16_t B, uint16_t D, uint16_t F, uint16_t H) {
|
||||
switch(rule) { default:
|
||||
case 0: return E;
|
||||
case 1: return blend1(E, A);
|
||||
case 2: return blend1(E, D);
|
||||
case 3: return blend1(E, B);
|
||||
case 4: return blend2(E, D, B);
|
||||
case 5: return blend2(E, A, B);
|
||||
case 6: return blend2(E, A, D);
|
||||
case 7: return blend3(E, B, D);
|
||||
case 8: return blend3(E, D, B);
|
||||
case 9: return blend4(E, D, B);
|
||||
case 10: return blend5(E, D, B);
|
||||
case 11: return blend6(E, D, B);
|
||||
case 12: return same(B, D) ? blend2(E, D, B) : E;
|
||||
case 13: return same(B, D) ? blend5(E, D, B) : E;
|
||||
case 14: return same(B, D) ? blend6(E, D, B) : E;
|
||||
case 15: return same(B, D) ? blend2(E, D, B) : blend1(E, A);
|
||||
case 16: return same(B, D) ? blend4(E, D, B) : blend1(E, A);
|
||||
case 17: return same(B, D) ? blend5(E, D, B) : blend1(E, A);
|
||||
case 18: return same(B, F) ? blend3(E, B, D) : blend1(E, D);
|
||||
case 19: return same(D, H) ? blend3(E, D, B) : blend1(E, B);
|
||||
}
|
||||
}
|
||||
|
||||
void HQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
|
@ -76,43 +106,40 @@ void HQ2xFilter::render(
|
|||
uint32_t *out0 = output;
|
||||
uint32_t *out1 = output + outpitch;
|
||||
|
||||
#define W1 input[-1 - (int)pitch]
|
||||
#define W2 input[ 0 - (int)pitch]
|
||||
#define W3 input[+1 - (int)pitch]
|
||||
#define W4 input[-1]
|
||||
#define W5 input[ 0]
|
||||
#define W6 input[+1]
|
||||
#define W7 input[-1 + (int)pitch]
|
||||
#define W8 input[ 0 + (int)pitch]
|
||||
#define W9 input[+1 + (int)pitch]
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
int prevline = (y == 0) ? 0 : pitch;
|
||||
int nextline = (y == height - 1) ? 0 : pitch;
|
||||
|
||||
input += pitch;
|
||||
memset(out0, 0, 2048); out0 += outpitch << 1;
|
||||
memset(out1, 0, 2048); out1 += outpitch << 1;
|
||||
|
||||
for(int y = height - 2; y; --y) {
|
||||
input++;
|
||||
*out0++ = 0; *out0++ = 0;
|
||||
*out1++ = 0; *out1++ = 0;
|
||||
|
||||
int32_t pattern = diff(W5, W4) ? 0x10 : 0x00;
|
||||
for(int x = 256 - 2; x; --x) {
|
||||
uint32_t center = yuvtable[W5] + diff_offset;
|
||||
for(unsigned x = 1; x < 256 - 1; x++) {
|
||||
uint16_t A = *(input - prevline - 1);
|
||||
uint16_t B = *(input - prevline + 0);
|
||||
uint16_t C = *(input - prevline + 1);
|
||||
uint16_t D = *(input - 1);
|
||||
uint16_t E = *(input + 0);
|
||||
uint16_t F = *(input + 1);
|
||||
uint16_t G = *(input + nextline - 1);
|
||||
uint16_t H = *(input + nextline + 0);
|
||||
uint16_t I = *(input + nextline + 1);
|
||||
uint32_t e = yuvTable[E] + diff_offset;
|
||||
|
||||
//W4 for pixel x+1 is the same as W6 for pixel x
|
||||
pattern = (pattern & 0x10) >> 1;
|
||||
pattern |= hdiff(center, W1) ? 0x01 : 0x00;
|
||||
pattern |= hdiff(center, W2) ? 0x02 : 0x00;
|
||||
pattern |= hdiff(center, W3) ? 0x04 : 0x00;
|
||||
//pattern |= hdiff(center, W4) ? 0x08 : 0x00;
|
||||
pattern |= hdiff(center, W6) ? 0x10 : 0x00;
|
||||
pattern |= hdiff(center, W7) ? 0x20 : 0x00;
|
||||
pattern |= hdiff(center, W8) ? 0x40 : 0x00;
|
||||
pattern |= hdiff(center, W9) ? 0x80 : 0x00;
|
||||
uint8_t pattern;
|
||||
pattern = diff(e, A) << 0;
|
||||
pattern |= diff(e, B) << 1;
|
||||
pattern |= diff(e, C) << 2;
|
||||
pattern |= diff(e, D) << 3;
|
||||
pattern |= diff(e, F) << 4;
|
||||
pattern |= diff(e, G) << 5;
|
||||
pattern |= diff(e, H) << 6;
|
||||
pattern |= diff(e, I) << 7;
|
||||
|
||||
switch(pattern) {
|
||||
#include "hq2x_table.hpp"
|
||||
}
|
||||
*(out0 + 0) = colortable[blend(hqTable[pattern], E, A, B, D, F, H)]; pattern = rotate[pattern];
|
||||
*(out0 + 1) = colortable[blend(hqTable[pattern], E, C, F, B, H, D)]; pattern = rotate[pattern];
|
||||
*(out1 + 1) = colortable[blend(hqTable[pattern], E, I, H, F, D, B)]; pattern = rotate[pattern];
|
||||
*(out1 + 0) = colortable[blend(hqTable[pattern], E, G, D, H, B, F)];
|
||||
|
||||
input++;
|
||||
out0 += 2;
|
||||
|
@ -127,36 +154,39 @@ void HQ2xFilter::render(
|
|||
out0 += outpitch + outpitch - 512;
|
||||
out1 += outpitch + outpitch - 512;
|
||||
}
|
||||
|
||||
memset(out0, 0, 2048);
|
||||
memset(out1, 0, 2048);
|
||||
}
|
||||
|
||||
HQ2xFilter::HQ2xFilter() {
|
||||
yuvtable = new uint32_t[32768];
|
||||
yuvTable = new uint32_t[32768];
|
||||
|
||||
for(int i = 0; i < 32768; i++) {
|
||||
int ir = (i) & 0x1f;
|
||||
int ig = (i >> 5) & 0x1f;
|
||||
int ib = (i >> 10) & 0x1f;
|
||||
for(unsigned i = 0; i < 32768; i++) {
|
||||
uint8_t R = (i >> 0) & 31;
|
||||
uint8_t G = (i >> 5) & 31;
|
||||
uint8_t B = (i >> 10) & 31;
|
||||
|
||||
//bgr555->bgr888
|
||||
double r = (ir << 3) | (ir >> 2);
|
||||
double g = (ig << 3) | (ig >> 2);
|
||||
double b = (ib << 3) | (ib >> 2);
|
||||
double r = (R << 3) | (R >> 2);
|
||||
double g = (G << 3) | (G >> 2);
|
||||
double b = (B << 3) | (B >> 2);
|
||||
|
||||
//bgr888->yuv888
|
||||
double y = (r + g + b) * (0.25f * (63.5f / 48.0f));
|
||||
double u = ((r - b) * 0.25f + 128.0f) * (7.5f / 7.0f);
|
||||
double v = ((g * 2.0f - r - b) * 0.125f + 128.0f) * (7.5f / 6.0f);
|
||||
|
||||
yuvtable[i] = (int(y) << 21) + (int(u) << 11) + (int(v));
|
||||
yuvTable[i] = ((unsigned)y << 21) + ((unsigned)u << 11) + ((unsigned)v);
|
||||
}
|
||||
|
||||
diff_offset = (0x440 << 21) + (0x207 << 11) + 0x407;
|
||||
diff_mask = (0x380 << 21) + (0x1f0 << 11) + 0x3f0;
|
||||
|
||||
for(unsigned n = 0; n < 256; n++) {
|
||||
rotate[n] = ((n >> 2) & 0x11) | ((n << 2) & 0x88)
|
||||
| ((n & 0x01) << 5) | ((n & 0x08) << 3)
|
||||
| ((n & 0x10) >> 3) | ((n & 0x80) >> 5);
|
||||
}
|
||||
}
|
||||
|
||||
HQ2xFilter::~HQ2xFilter() {
|
||||
delete[] yuvtable;
|
||||
delete[] yuvTable;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue