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:
byuu 2009-07-12 09:45:57 +00:00
parent 7b0e484c18
commit c26f9d912a
214 changed files with 7000 additions and 16732 deletions

View File

@ -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 ###

View File

@ -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"

Binary file not shown.

View File

@ -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();

View File

@ -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();

View File

@ -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); }

View File

@ -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) {

View File

@ -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;

View File

@ -12,3 +12,5 @@
#include "dsp4/dsp4.hpp"
#include "obc1/obc1.hpp"
#include "st010/st010.hpp"
#include "st011/st011.hpp"
#include "st018/st018.hpp"

View File

@ -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);
}
};
};

View File

@ -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; }

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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() {

View File

@ -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();
}

View File

@ -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();

View File

@ -8,6 +8,7 @@ public:
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
OBC1();
~OBC1();

View File

@ -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

View File

@ -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;

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -30,6 +30,7 @@ understood.
************************************************************************/
typedef uint8 bool8;
#define SDD1_read(__addr) (sdd1.read(__addr))
////////////////////////////////////////////////////

View File

@ -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

View File

@ -4,6 +4,7 @@ public:
void init(unsigned mode, unsigned offset, unsigned index);
void reset();
void serialize(serializer&);
SPC7110Decomp();
~SPC7110Decomp();

View File

@ -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

View File

@ -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 };

View File

@ -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];

View File

@ -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();
}

View File

@ -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();

View File

@ -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);

20
src/chip/st011/st011.cpp Normal file
View File

@ -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() {
}
};

9
src/chip/st011/st011.hpp Normal file
View File

@ -0,0 +1,9 @@
class ST011 {
public:
void init();
void enable();
void power();
void reset();
};
extern ST011 st011;

124
src/chip/st018/st018.cpp Normal file
View File

@ -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;
}
};

51
src/chip/st018/st018.hpp Normal file
View File

@ -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;

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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);

View File

@ -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])();

View File

@ -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();
}

View File

@ -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];

View File

@ -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;

View File

@ -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();

View File

@ -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: {

View File

@ -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);

View File

@ -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;

View File

@ -14,6 +14,10 @@ public:
void enable();
void power();
void reset();
private:
unsigned clockmode;
unsigned instruction_counter;
};
extern SuperFX superfx;

View File

@ -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;

View File

@ -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();

View File

@ -1,3 +0,0 @@
clear
bpp opcode_functions.cpp opcode_functions.bpp
bpp opcode_headers.hpp opcode_headers.bpp

View File

@ -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:

View File

@ -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();
};

View File

@ -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

View File

@ -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"

View File

@ -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();

View File

@ -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()

View File

@ -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

View File

@ -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);
}

View File

@ -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

177
src/cpu/core/opcode_pc.cpp Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

165
src/cpu/core/opcode_rmw.cpp Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}
};

View File

@ -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

312
src/cpu/core/table.cpp Normal file
View File

@ -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

View File

@ -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() {

View File

@ -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();
};

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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() {

View File

@ -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();
};

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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>

View File

@ -8,6 +8,5 @@ public:
virtual void power() = 0;
virtual void reset() = 0;
DSP() {}
virtual ~DSP() {}
virtual void serialize(serializer&) {}
};

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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"
};

View File

@ -1,175 +0,0 @@
#include "bpp.hpp"
bool BPP::process_macro(Macro &macro, 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;
}

View File

@ -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 &macro, const lstring &arg);
bool process(const char *inputfn);
};

View File

@ -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);
}

View File

@ -14,6 +14,7 @@ public:
Direct,
Scanline,
Scale2x,
LQ2x,
HQ2x,
NTSC,
};

View File

@ -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