mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-09 09:19:42 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3945e5772 | ||
|
|
6b6233b3af | ||
|
|
9f63cb1b99 | ||
|
|
49c39e0e4d |
No files matched your search
@@ -1,139 +0,0 @@
|
||||
# Applies contrast adjust filter to video output when enabled
|
||||
# Works by lowering the brightness of darker colors,
|
||||
# while leaving brighter colors alone; thus reducing saturation
|
||||
# (default = true)
|
||||
snes.video_color_curve = true
|
||||
|
||||
# Selects color adjustment filter for video output
|
||||
# 0 = Normal (no filter, rgb555)
|
||||
# 1 = Grayscale mode (l5)
|
||||
# 2 = VGA mode (rgb332)
|
||||
# 3 = Genesis mode (rgb333)
|
||||
# (default = 0)
|
||||
snes.video_color_adjust_mode = 0
|
||||
|
||||
# Mutes SNES audio output when enabled
|
||||
# (default = true)
|
||||
snes.mute = false
|
||||
|
||||
# Regulate speed to 60hz (NTSC) / 50hz (PAL)
|
||||
# (default = true)
|
||||
system.regulate_speed = true
|
||||
|
||||
# Video mode
|
||||
# 0 = 256x224w
|
||||
# 1 = 512x448w
|
||||
# 2 = 960x720w
|
||||
# 3 = 640x480f
|
||||
# 4 = 1024x768f
|
||||
# (default = 1)
|
||||
video.mode = 1
|
||||
|
||||
# Use Video RAM instead of System RAM
|
||||
# (default = true)
|
||||
video.use_vram = true
|
||||
|
||||
# Wait for vertical retrace when updating screen
|
||||
# (default = false)
|
||||
video.vblank = false
|
||||
|
||||
# Show framerate in window title
|
||||
# (default = true)
|
||||
gui.show_fps = true
|
||||
|
||||
# Joypad1 up
|
||||
# (default = 0x26)
|
||||
input.joypad1.up = 0x26
|
||||
|
||||
# Joypad1 down
|
||||
# (default = 0x28)
|
||||
input.joypad1.down = 0x28
|
||||
|
||||
# Joypad1 left
|
||||
# (default = 0x25)
|
||||
input.joypad1.left = 0x25
|
||||
|
||||
# Joypad1 right
|
||||
# (default = 0x27)
|
||||
input.joypad1.right = 0x27
|
||||
|
||||
# Joypad1 A
|
||||
# (default = 0x58)
|
||||
input.joypad1.a = 0x58
|
||||
|
||||
# Joypad1 B
|
||||
# (default = 0x5a)
|
||||
input.joypad1.b = 0x5a
|
||||
|
||||
# Joypad1 X
|
||||
# (default = 0x53)
|
||||
input.joypad1.x = 0x53
|
||||
|
||||
# Joypad1 Y
|
||||
# (default = 0x41)
|
||||
input.joypad1.y = 0x41
|
||||
|
||||
# Joypad1 L
|
||||
# (default = 0x44)
|
||||
input.joypad1.l = 0x44
|
||||
|
||||
# Joypad1 R
|
||||
# (default = 0x43)
|
||||
input.joypad1.r = 0x43
|
||||
|
||||
# Joypad1 select
|
||||
# (default = 0x10)
|
||||
input.joypad1.select = 0x10
|
||||
|
||||
# Joypad1 start
|
||||
# (default = 0xd)
|
||||
input.joypad1.start = 0xd
|
||||
|
||||
# Joypad2 up
|
||||
# (default = 0x54)
|
||||
input.joypad2.up = 0x54
|
||||
|
||||
# Joypad2 down
|
||||
# (default = 0x47)
|
||||
input.joypad2.down = 0x47
|
||||
|
||||
# Joypad2 left
|
||||
# (default = 0x46)
|
||||
input.joypad2.left = 0x46
|
||||
|
||||
# Joypad2 right
|
||||
# (default = 0x48)
|
||||
input.joypad2.right = 0x48
|
||||
|
||||
# Joypad2 A
|
||||
# (default = 0x4b)
|
||||
input.joypad2.a = 0x4b
|
||||
|
||||
# Joypad2 B
|
||||
# (default = 0x4a)
|
||||
input.joypad2.b = 0x4a
|
||||
|
||||
# Joypad2 X
|
||||
# (default = 0x49)
|
||||
input.joypad2.x = 0x49
|
||||
|
||||
# Joypad2 Y
|
||||
# (default = 0x55)
|
||||
input.joypad2.y = 0x55
|
||||
|
||||
# Joypad2 L
|
||||
# (default = 0x4f)
|
||||
input.joypad2.l = 0x4f
|
||||
|
||||
# Joypad2 R
|
||||
# (default = 0x4c)
|
||||
input.joypad2.r = 0x4c
|
||||
|
||||
# Joypad2 select
|
||||
# (default = 0x5b)
|
||||
input.joypad2.select = 0x5b
|
||||
|
||||
# Joypad2 start
|
||||
# (default = 0x5d)
|
||||
input.joypad2.start = 0x5d
|
||||
|
||||
@@ -27,4 +27,7 @@ static const uint8 iplrom[64];
|
||||
virtual bool in_opcode();
|
||||
void disassemble_opcode(char *output);
|
||||
inline uint16 __relb(int8 offset, int op_len);
|
||||
|
||||
APU() {}
|
||||
virtual ~APU() {}
|
||||
};
|
||||
+4
-245
@@ -1,230 +1,11 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "bapu_op_fn.cpp"
|
||||
#include "bapu_op_mov.cpp"
|
||||
#include "bapu_op_pc.cpp"
|
||||
#include "bapu_op_read.cpp"
|
||||
#include "bapu_op_rmw.cpp"
|
||||
#include "bapu_op_misc.cpp"
|
||||
|
||||
#include "bapu_exec.cpp"
|
||||
|
||||
uint8 bAPU::spcram_read(uint16 addr) {
|
||||
uint8 r;
|
||||
if(addr >= 0x00f0 && addr <= 0x00ff) {
|
||||
switch(addr) {
|
||||
case 0xf0: //TEST -- operation unknown, supposedly returns 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xf1: //CONTROL -- write-only register, always returns 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xf2: //DSPADDR
|
||||
r = status.dsp_addr;
|
||||
break;
|
||||
case 0xf3: //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
r = r_dsp->read(status.dsp_addr & 0x7f);
|
||||
break;
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
r = r_cpu->port_read(addr & 3);
|
||||
break;
|
||||
case 0xf8: //???
|
||||
case 0xf9: //??? -- Mapped to SPCRAM
|
||||
r = spcram[addr];
|
||||
break;
|
||||
case 0xfa: //T0TARGET
|
||||
case 0xfb: //T1TARGET
|
||||
case 0xfc: //T2TARGET -- write-only registers, always return 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xfd: //T0OUT -- 4-bit counter value
|
||||
r = t0.stage3_ticks & 15;
|
||||
t0.stage3_ticks = 0;
|
||||
break;
|
||||
case 0xfe: //T1OUT -- 4-bit counter value
|
||||
r = t1.stage3_ticks & 15;
|
||||
t1.stage3_ticks = 0;
|
||||
break;
|
||||
case 0xff: //T2OUT -- 4-bit counter value
|
||||
r = t2.stage3_ticks & 15;
|
||||
t2.stage3_ticks = 0;
|
||||
break;
|
||||
}
|
||||
} else if(addr < 0xffc0) {
|
||||
r = spcram[addr];
|
||||
} else {
|
||||
if(status.iplrom_enabled == true) {
|
||||
r = iplrom[addr & 0x3f];
|
||||
} else {
|
||||
r = spcram[addr];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
snes->notify(SNES::SPCRAM_READ, addr, r);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
void bAPU::spcram_write(uint16 addr, uint8 value) {
|
||||
if(addr >= 0x00f0 && addr <= 0x00ff) {
|
||||
switch(addr) {
|
||||
case 0xf0: //TEST -- operation unknown
|
||||
break;
|
||||
case 0xf1: //CONTROL
|
||||
status.iplrom_enabled = !!(value & 0x80);
|
||||
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
if(value & 0x20) {
|
||||
r_cpu->port_write(2, 0x00);
|
||||
r_cpu->port_write(3, 0x00);
|
||||
}
|
||||
if(value & 0x10) {
|
||||
r_cpu->port_write(0, 0x00);
|
||||
r_cpu->port_write(1, 0x00);
|
||||
}
|
||||
|
||||
//0->1 transistion resets timers
|
||||
if(t2.enabled == false && (value & 0x04)) {
|
||||
t2.stage2_ticks = 0;
|
||||
t2.stage3_ticks = 0;
|
||||
}
|
||||
t2.enabled = !!(value & 0x04);
|
||||
|
||||
if(t1.enabled == false && (value & 0x02)) {
|
||||
t1.stage2_ticks = 0;
|
||||
t1.stage3_ticks = 0;
|
||||
}
|
||||
t1.enabled = !!(value & 0x02);
|
||||
|
||||
if(t0.enabled == false && (value & 0x01)) {
|
||||
t0.stage2_ticks = 0;
|
||||
t0.stage3_ticks = 0;
|
||||
}
|
||||
t0.enabled = !!(value & 0x01);
|
||||
break;
|
||||
case 0xf2: //DSPADDR
|
||||
status.dsp_addr = value;
|
||||
break;
|
||||
case 0xf3: //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
if(status.dsp_addr < 0x80) {
|
||||
r_dsp->write(status.dsp_addr & 0x7f, value);
|
||||
}
|
||||
break;
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
port_write(addr & 3, value);
|
||||
break;
|
||||
case 0xf8: //???
|
||||
case 0xf9: //??? - Mapped to SPCRAM
|
||||
spcram[addr] = value;
|
||||
break;
|
||||
case 0xfa: //T0TARGET
|
||||
t0.target = value;
|
||||
break;
|
||||
case 0xfb: //T1TARGET
|
||||
t1.target = value;
|
||||
break;
|
||||
case 0xfc: //T2TARGET
|
||||
t2.target = value;
|
||||
break;
|
||||
case 0xfd: //T0OUT
|
||||
case 0xfe: //T1OUT
|
||||
case 0xff: //T2OUT -- read-only registers
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//writes to $ffc0-$ffff always go to spcram,
|
||||
//even if the iplrom is enabled.
|
||||
spcram[addr] = value;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
snes->notify(SNES::SPCRAM_WRITE, addr, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8 bAPU::port_read(uint8 port) {
|
||||
return spcram[0xf4 + (port & 3)];
|
||||
}
|
||||
|
||||
void bAPU::port_write(uint8 port, uint8 value) {
|
||||
spcram[0xf4 + (port & 0x03)] = value;
|
||||
}
|
||||
|
||||
void bAPU::add_cycles(int cycles) {
|
||||
status.cycles_executed += cycles;
|
||||
|
||||
t0.add_cycles(cycles);
|
||||
t1.add_cycles(cycles);
|
||||
t2.add_cycles(cycles);
|
||||
}
|
||||
|
||||
uint32 bAPU::cycles_executed() {
|
||||
uint32 r = status.cycles_executed;
|
||||
status.cycles_executed = 0;
|
||||
return (r << 4) + (r << 3);
|
||||
}
|
||||
|
||||
uint8 bAPU::op_read() {
|
||||
uint8 r;
|
||||
r = spcram_read(regs.pc);
|
||||
regs.pc++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_read(uint8 mode, uint16 addr) {
|
||||
uint8 r;
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
r = spcram_read(addr);
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
r = spcram_read(((regs.p.p)?0x100:0x000) + (addr & 0xff));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void bAPU::op_write(uint8 mode, uint16 addr, uint8 value) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
spcram_write(addr, value);
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
spcram_write(((regs.p.p)?0x100:0x000) + (addr & 0xff), value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bAPU::stack_read() {
|
||||
regs.sp++;
|
||||
return spcram_read(0x0100 | regs.sp);
|
||||
}
|
||||
|
||||
void bAPU::stack_write(uint8 value) {
|
||||
spcram_write(0x0100 | regs.sp, value);
|
||||
regs.sp--;
|
||||
}
|
||||
|
||||
uint8 *bAPU::get_spcram_handle() {
|
||||
if(!spcram) {
|
||||
alert("bAPU::get_spcram_handle() -- spcram uninitialized");
|
||||
}
|
||||
|
||||
return spcram;
|
||||
}
|
||||
#include "core/core.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
void bAPU::run() {
|
||||
exec_cycle();
|
||||
exec();
|
||||
}
|
||||
|
||||
void bAPU::power() {
|
||||
@@ -281,25 +62,3 @@ bAPU::bAPU() {
|
||||
bAPU::~bAPU() {
|
||||
if(spcram)free(spcram);
|
||||
}
|
||||
|
||||
//cycles should never be greater than 12. since the minimum
|
||||
//cycle_frequency value is 16, we don't have to worry about
|
||||
//two ticks occuring in one call to this function.
|
||||
void bAPUTimer::add_cycles(int cycles) {
|
||||
//stage 1 increment
|
||||
stage1_ticks += cycles;
|
||||
if(stage1_ticks < cycle_frequency)return;
|
||||
|
||||
stage1_ticks -= cycle_frequency;
|
||||
if(enabled == false)return;
|
||||
|
||||
//stage 2 increment
|
||||
stage2_ticks++;
|
||||
|
||||
if(stage2_ticks != target)return;
|
||||
|
||||
//stage 3 increment
|
||||
stage2_ticks = 0;
|
||||
stage3_ticks++;
|
||||
stage3_ticks &= 15;
|
||||
}
|
||||
+7
-64
@@ -1,20 +1,8 @@
|
||||
class bAPU;
|
||||
|
||||
class bAPUTimer {
|
||||
public:
|
||||
uint8 cycle_frequency, target;
|
||||
uint8 stage1_ticks, stage2_ticks, stage3_ticks;
|
||||
bool enabled;
|
||||
inline void add_cycles(int cycles);
|
||||
};
|
||||
|
||||
class bAPU : public APU {
|
||||
private:
|
||||
typedef void (bAPU::*op)();
|
||||
op optbl[256];
|
||||
|
||||
public:
|
||||
uint16 dp, sp, rd, wr, bit, ya;
|
||||
#include "core/core.h"
|
||||
#include "memory/memory.h"
|
||||
#include "timing/timing.h"
|
||||
|
||||
struct {
|
||||
uint8 cycle_pos, opcode;
|
||||
@@ -25,56 +13,11 @@ struct {
|
||||
|
||||
//$f2
|
||||
uint8 dsp_addr;
|
||||
}status;
|
||||
} status;
|
||||
|
||||
bAPUTimer t0, t1, t2;
|
||||
|
||||
uint8 *spcram;
|
||||
inline uint8 spcram_read (uint16 addr);
|
||||
inline void spcram_write(uint16 addr, uint8 value);
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
inline uint8 *get_spcram_handle();
|
||||
inline void run();
|
||||
inline uint32 cycles_executed();
|
||||
inline void power();
|
||||
inline void reset();
|
||||
|
||||
inline void add_cycles(int cycles);
|
||||
|
||||
enum {
|
||||
OPMODE_ADDR = 0,
|
||||
OPMODE_DP = 1
|
||||
};
|
||||
inline uint8 op_read();
|
||||
inline uint8 op_read (uint8 mode, uint16 addr);
|
||||
inline void op_write(uint8 mode, uint16 addr, uint8 value);
|
||||
inline uint8 stack_read();
|
||||
inline void stack_write(uint8 value);
|
||||
|
||||
inline void exec_cycle();
|
||||
inline bool in_opcode();
|
||||
inline void init_op_table();
|
||||
|
||||
inline uint8 op_adc (uint8 x, uint8 y);
|
||||
inline uint16 op_addw(uint16 x, uint16 y);
|
||||
inline uint8 op_and (uint8 x, uint8 y);
|
||||
inline uint8 op_cmp (uint8 x, uint8 y);
|
||||
inline uint16 op_cmpw(uint16 x, uint16 y);
|
||||
inline uint8 op_eor (uint8 x, uint8 y);
|
||||
inline uint8 op_inc (uint8 x);
|
||||
inline uint16 op_incw(uint16 x);
|
||||
inline uint8 op_dec (uint8 x);
|
||||
inline uint16 op_decw(uint16 x);
|
||||
inline uint8 op_or (uint8 x, uint8 y);
|
||||
inline uint8 op_sbc (uint8 x, uint8 y);
|
||||
inline uint16 op_subw(uint16 x, uint16 y);
|
||||
inline uint8 op_asl (uint8 x);
|
||||
inline uint8 op_lsr (uint8 x);
|
||||
inline uint8 op_rol (uint8 x);
|
||||
inline uint8 op_ror (uint8 x);
|
||||
#include "bapu_op.h"
|
||||
inline void run();
|
||||
inline void power();
|
||||
inline void reset();
|
||||
|
||||
bAPU();
|
||||
~bAPU();
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
#include "../../lib/libbase.h"
|
||||
#include "../../lib/libstring.h"
|
||||
#include "../../lib/libstring.cpp"
|
||||
|
||||
FILE *fp, *fph, *fpt;
|
||||
|
||||
string data, line, part, subpart;
|
||||
string output_table, output_header, output_op;
|
||||
|
||||
int op_count;
|
||||
struct _op_list {
|
||||
string name;
|
||||
string arg;
|
||||
}op_list[64];
|
||||
|
||||
int line_num;
|
||||
|
||||
void clear_op_list() {
|
||||
op_count = 0;
|
||||
for(int i=0;i<64;i++) {
|
||||
strcpy(op_list[i].name, "");
|
||||
for(int l=0;l<8;l++) {
|
||||
strcpy(op_list[i].arg[l], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_header() {
|
||||
int i = line_num, l, n, z;
|
||||
char t[4096];
|
||||
clear_op_list();
|
||||
while(1) {
|
||||
z = op_count++;
|
||||
strcpy(part, line[i]);
|
||||
strrtrim(part, "),");
|
||||
strrtrim(part, ") {");
|
||||
split(subpart, "(", part);
|
||||
strcpy(op_list[z].name, subpart[0]);
|
||||
split(part, ", ", subpart[1]);
|
||||
for(l=0;l<count(part);l++) {
|
||||
strcpy(op_list[z].arg[l], part[l]);
|
||||
}
|
||||
if(!strend(line[i], " {"))break;
|
||||
i++;
|
||||
}
|
||||
|
||||
sprintf(output_op, "void bAPU::op_$$() {\r\n switch(status.cycle_pos++) {\r\n");
|
||||
sprintf(output_header, "void op_$$();\r\n");
|
||||
sprintf(output_table, "optbl[$0] = &bAPU::op_$$;\r\n");
|
||||
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void update_line(int i, int n) {
|
||||
replace(line[i], "end;", "status.cycle_pos = 0;");
|
||||
}
|
||||
|
||||
void gen_op() {
|
||||
int i = line_num, n;
|
||||
char t[4096];
|
||||
while(1) {
|
||||
if(!strcmp(line[i], "}"))break;
|
||||
|
||||
n = strdec(line[i]);
|
||||
sprintf(t, "%d:", n);
|
||||
strltrim(line[i], t);
|
||||
sprintf(t, " case %d:\r\n", n);
|
||||
strcat(output_op, t);
|
||||
|
||||
update_line(i, n);
|
||||
if(strcmp(line[i], "")) {
|
||||
strcat(output_op, " ");
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
}
|
||||
|
||||
i++;
|
||||
while(1) {
|
||||
if((strptr(line[i])[1]) == ':' || (strptr(line[i])[2]) == ':' || !strcmp(line[i], "}"))break;
|
||||
|
||||
update_line(i, n);
|
||||
strcat(output_op, " ");
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
if(!strcmp(line[i], "}"))strcat(output_op, " status.cycle_pos = 0;\r\n");
|
||||
strcat(output_op, " break;\r\n");
|
||||
}
|
||||
strcat(output_op, " }\r\n}");
|
||||
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void gen_final() {
|
||||
string t;
|
||||
int i, l;
|
||||
for(i=0;i<op_count;i++) {
|
||||
strcpy(t, output_op);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
replace(t, "$1", op_list[i].arg[1]);
|
||||
replace(t, "$2", op_list[i].arg[2]);
|
||||
replace(t, "$3", op_list[i].arg[3]);
|
||||
replace(t, "$4", op_list[i].arg[4]);
|
||||
replace(t, "$5", op_list[i].arg[5]);
|
||||
replace(t, "$6", op_list[i].arg[6]);
|
||||
replace(t, "$7", op_list[i].arg[7]);
|
||||
fprintf(fp, "%s\r\n\r\n", strptr(t));
|
||||
|
||||
strcpy(t, output_header);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
fprintf(fph, "%s", strptr(t));
|
||||
|
||||
strcpy(t, output_table);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
fprintf(fpt, "%s", strptr(t));
|
||||
}
|
||||
}
|
||||
|
||||
void generate(char *dest, char *src) {
|
||||
fp = fopen(src, "rb");
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
int fsize = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
char *buf = (char*)malloc(fsize + 1);
|
||||
fread(buf, 1, fsize, fp);
|
||||
fclose(fp);
|
||||
buf[fsize] = 0;
|
||||
|
||||
strcpy(data, buf);
|
||||
free(buf);
|
||||
replace(data, "\r\n", "\n");
|
||||
split(line, "\n", data);
|
||||
|
||||
fp = fopen(dest, "wb");
|
||||
|
||||
line_num = 0;
|
||||
while(line_num < count(line)) {
|
||||
while(!strcmp(line[line_num], "") && line_num < count(line))line_num++;
|
||||
if(line_num >= count(line))break;
|
||||
|
||||
gen_header();
|
||||
gen_op();
|
||||
gen_final();
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int main() {
|
||||
fph = fopen("bapu_op.h", "wb");
|
||||
fpt = fopen("bapu_optable.cpp", "wb");
|
||||
|
||||
generate("bapu_op_mov.cpp", "op_mov.b");
|
||||
generate("bapu_op_pc.cpp", "op_pc.b");
|
||||
generate("bapu_op_read.cpp", "op_read.b");
|
||||
generate("bapu_op_rmw.cpp", "op_rmw.b");
|
||||
generate("bapu_op_misc.cpp", "op_misc.b");
|
||||
|
||||
fclose(fph);
|
||||
fclose(fpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
cl /ML /O2 bapugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -1 +0,0 @@
|
||||
@del *.exe
|
||||
@@ -0,0 +1,18 @@
|
||||
#define CLASS_NAME "bAPU"
|
||||
#include "../../../lib/opgen.cpp"
|
||||
|
||||
int main() {
|
||||
fph = fopen("op.h", "wb");
|
||||
fpt = fopen("optable.cpp", "wb");
|
||||
|
||||
generate("op_mov.cpp", "op_mov.b");
|
||||
generate("op_pc.cpp", "op_pc.b");
|
||||
generate("op_read.cpp", "op_read.b");
|
||||
generate("op_rmw.cpp", "op_rmw.b");
|
||||
generate("op_misc.cpp", "op_misc.b");
|
||||
|
||||
fclose(fph);
|
||||
fclose(fpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
cl /O2 /wd4996 bapugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -0,0 +1,8 @@
|
||||
@del *.exe
|
||||
@del op.h
|
||||
@del optable.cpp
|
||||
@del op_mov.cpp
|
||||
@del op_pc.cpp
|
||||
@del op_read.cpp
|
||||
@del op_rmw.cpp
|
||||
@del op_misc.cpp
|
||||
@@ -1,4 +1,11 @@
|
||||
void bAPU::exec_cycle() {
|
||||
#include "opfn.cpp"
|
||||
#include "op_mov.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_read.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_misc.cpp"
|
||||
|
||||
void bAPU::exec() {
|
||||
if(status.cycle_pos) {
|
||||
(this->*optbl[status.opcode])();
|
||||
add_cycles(1);
|
||||
@@ -25,5 +32,5 @@ bool bAPU::in_opcode() {
|
||||
}
|
||||
|
||||
void bAPU::init_op_table() {
|
||||
#include "bapu_optable.cpp"
|
||||
#include "optable.cpp"
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
void (bAPU::*optbl[256])();
|
||||
uint16 dp, sp, rd, wr, bit, ya;
|
||||
inline uint8 op_adc (uint8 x, uint8 y);
|
||||
inline uint16 op_addw(uint16 x, uint16 y);
|
||||
inline uint8 op_and (uint8 x, uint8 y);
|
||||
inline uint8 op_cmp (uint8 x, uint8 y);
|
||||
inline uint16 op_cmpw(uint16 x, uint16 y);
|
||||
inline uint8 op_eor (uint8 x, uint8 y);
|
||||
inline uint8 op_inc (uint8 x);
|
||||
inline uint16 op_incw(uint16 x);
|
||||
inline uint8 op_dec (uint8 x);
|
||||
inline uint16 op_decw(uint16 x);
|
||||
inline uint8 op_or (uint8 x, uint8 y);
|
||||
inline uint8 op_sbc (uint8 x, uint8 y);
|
||||
inline uint16 op_subw(uint16 x, uint16 y);
|
||||
inline uint8 op_asl (uint8 x);
|
||||
inline uint8 op_lsr (uint8 x);
|
||||
inline uint8 op_rol (uint8 x);
|
||||
inline uint8 op_ror (uint8 x);
|
||||
|
||||
inline void exec();
|
||||
inline bool in_opcode();
|
||||
inline void init_op_table();
|
||||
|
||||
#include "op.h"
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,55 +1,55 @@
|
||||
void bAPU::op_nop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_sleep() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
regs.pc--;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_stop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
regs.pc--;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_xcn() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_daa() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
@@ -60,15 +60,15 @@ void bAPU::op_daa() {
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_das() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
@@ -79,512 +79,512 @@ void bAPU::op_das() {
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clrc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.p.c = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clrp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.p.p = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_setc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.p.c = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_setp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.p.p = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clrv() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_notc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
regs.p.c ^= 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ei() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
regs.p.i = 1;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_di() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
regs.p.i = 0;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set0_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x01;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr0_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x01;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set1_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x02;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr1_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x02;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set2_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x04;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr2_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x04;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set3_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x08;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr3_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x08;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set4_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x10;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr4_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x10;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set5_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x20;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr5_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x20;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set6_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x40;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr6_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x40;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_set7_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= 0x80;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_clr7_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd &= ~0x80;
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_tset_addr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
regs.p.n = !!((rd & regs.a) & 0x80);
|
||||
regs.p.z = ((rd & regs.a) == 0);
|
||||
rd |= regs.a;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_tclr_addr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
regs.p.n = !!((rd & regs.a) & 0x80);
|
||||
regs.p.z = ((rd & regs.a) == 0);
|
||||
rd &=~ regs.a;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
stack_write(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
stack_write(regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
stack_write(regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_push_p() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
stack_write(regs.p);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.a = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.x = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.y = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_pop_p() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.p = stack_read();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mul_ya() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
} break;
|
||||
case 5: {
|
||||
} break;
|
||||
case 6: {
|
||||
} break;
|
||||
case 7: {
|
||||
} break;
|
||||
case 8: {
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
@@ -592,33 +592,33 @@ void bAPU::op_mul_ya() {
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_div_ya_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
case 9:
|
||||
break;
|
||||
case 10:
|
||||
break;
|
||||
case 11:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
} break;
|
||||
case 5: {
|
||||
} break;
|
||||
case 6: {
|
||||
} break;
|
||||
case 7: {
|
||||
} break;
|
||||
case 8: {
|
||||
} break;
|
||||
case 9: {
|
||||
} break;
|
||||
case 10: {
|
||||
} break;
|
||||
case 11: {
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
@@ -637,7 +637,7 @@ void bAPU::op_div_ya_x() {
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -1,710 +1,710 @@
|
||||
void bAPU::op_mov_a_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = regs.x;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = regs.y;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.x = regs.a;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.y = regs.a;
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_sp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.x = regs.sp;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_sp_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.sp = regs.x;
|
||||
regs.p.n = !!(regs.sp & 0x80);
|
||||
regs.p.z = (regs.sp == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_read();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.x = op_read();
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.y = op_read();
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_ix() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
regs.a = op_read(OPMODE_DP, regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_ixinc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.a = op_read(OPMODE_DP, regs.x++);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
regs.a = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
regs.x = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
regs.y = op_read(OPMODE_DP, sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.a = op_read(OPMODE_DP, sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_dpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.x = op_read(OPMODE_DP, sp + regs.y);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.y = op_read(OPMODE_DP, sp + regs.x);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
regs.a = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_x_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
regs.x = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_y_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
regs.y = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
regs.a = op_read(OPMODE_ADDR, sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_addry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
regs.a = op_read(OPMODE_ADDR, sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_idpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read() + regs.x;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
sp = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
sp |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
regs.a = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_a_idpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
sp = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
sp |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
regs.a = op_read(OPMODE_ADDR, sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_const() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
rd = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_ix_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
op_write(OPMODE_DP, regs.x, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_ixinc_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
case 1: {
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
op_write(OPMODE_DP, regs.x++, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
op_write(OPMODE_DP, dp, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
op_write(OPMODE_DP, dp, regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dp_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
op_write(OPMODE_DP, dp, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dpx_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_DP, dp + regs.x, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dpy_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_DP, dp + regs.y, regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_dpx_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_DP, dp + regs.x, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_ADDR, dp, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addr_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_ADDR, dp, regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addr_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_ADDR, dp, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addrx_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
} break;
|
||||
case 5: {
|
||||
op_write(OPMODE_ADDR, dp + regs.x, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_addry_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 3: {
|
||||
} break;
|
||||
case 4: {
|
||||
} break;
|
||||
case 5: {
|
||||
op_write(OPMODE_ADDR, dp + regs.y, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_idpx_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read() + regs.x;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
dp = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
dp |= op_read(OPMODE_DP, sp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 5: {
|
||||
} break;
|
||||
case 6: {
|
||||
op_write(OPMODE_ADDR, dp, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov_idpy_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
dp = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
dp |= op_read(OPMODE_DP, sp + 1) << 8;
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 5: {
|
||||
} break;
|
||||
case 6: {
|
||||
op_write(OPMODE_ADDR, dp + regs.y, regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_movw_ya_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
regs.a = op_read(OPMODE_DP, sp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
regs.y = op_read(OPMODE_DP, sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_movw_dp_ya() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
op_write(OPMODE_DP, dp, regs.a);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_DP, dp + 1, regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov1_c_bit() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
sp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_read(OPMODE_ADDR, sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_mov1_bit_c() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
File renamed without changes.
File diff suppressed because it is too large.
Load diff
File renamed without changes.
File diff suppressed because it is too large.
Load diff
File renamed without changes.
@@ -1,452 +1,452 @@
|
||||
void bAPU::op_inc_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_inc(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.x = op_inc(regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.y = op_inc(regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_dec(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_x() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.x = op_dec(regs.x);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_y() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.y = op_dec(regs.y);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_asl(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_lsr(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_rol(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_a() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
regs.a = op_ror(regs.a);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_inc(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_dec(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_asl(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_lsr(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_rol(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_ror(rd);
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_inc(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_dec(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_asl(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_lsr(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_rol(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 2: {
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_DP, dp + regs.x);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_ror(rd);
|
||||
op_write(OPMODE_DP, dp + regs.x, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_inc_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_inc(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_dec_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_dec(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_asl_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_asl(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_lsr_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_lsr(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_rol_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_rol(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_ror_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
dp |= op_read() << 8;
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd = op_read(OPMODE_ADDR, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_ror(rd);
|
||||
op_write(OPMODE_ADDR, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_incw_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_incw(rd);
|
||||
op_write(OPMODE_DP, dp + 1, rd >> 8);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bAPU::op_decw_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd |= op_read(OPMODE_DP, dp + 1) << 8;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd = op_decw(rd);
|
||||
op_write(OPMODE_DP, dp + 1, rd >> 8);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
op_write(OPMODE_DP, dp, rd);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ int16 r = x + y + regs.p.c;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_addw(uint16 x, uint16 y) {
|
||||
int32 r = x + y;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(x ^ y) & (y ^ (uint16)r) & 0x8000);
|
||||
regs.p.h = !!((x ^ y ^ (uint16)r) & 0x10);
|
||||
int16 r;
|
||||
regs.p.c = 0;
|
||||
r = op_adc(x, y);
|
||||
r |= op_adc(x >> 8, y >> 8) << 8;
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r > 0xffff);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -66,12 +65,11 @@ int16 r = x - y - !regs.p.c;
|
||||
}
|
||||
|
||||
uint16 bAPU::op_subw(uint16 x, uint16 y) {
|
||||
int32 r = x - y;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!((x ^ y) & (x ^ (uint16)r) & 0x8000);
|
||||
regs.p.h = !((x ^ y ^ (uint16)r) & 0x10);
|
||||
int16 r;
|
||||
regs.p.c = 1;
|
||||
r = op_sbc(x, y);
|
||||
r |= op_sbc(x >> 8, y >> 8) << 8;
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,199 @@
|
||||
uint8 bAPU::spcram_read(uint16 addr) {
|
||||
uint8 r;
|
||||
if(addr >= 0x00f0 && addr <= 0x00ff) {
|
||||
switch(addr) {
|
||||
case 0xf0: //TEST -- operation unknown, supposedly returns 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xf1: //CONTROL -- write-only register, always returns 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xf2: //DSPADDR
|
||||
r = status.dsp_addr;
|
||||
break;
|
||||
case 0xf3: //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
r = r_dsp->read(status.dsp_addr & 0x7f);
|
||||
break;
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
r = r_cpu->port_read(addr & 3);
|
||||
break;
|
||||
case 0xf8: //???
|
||||
case 0xf9: //??? -- Mapped to SPCRAM
|
||||
r = spcram[addr];
|
||||
break;
|
||||
case 0xfa: //T0TARGET
|
||||
case 0xfb: //T1TARGET
|
||||
case 0xfc: //T2TARGET -- write-only registers, always return 0x00
|
||||
r = 0x00;
|
||||
break;
|
||||
case 0xfd: //T0OUT -- 4-bit counter value
|
||||
r = t0.stage3_ticks & 15;
|
||||
t0.stage3_ticks = 0;
|
||||
break;
|
||||
case 0xfe: //T1OUT -- 4-bit counter value
|
||||
r = t1.stage3_ticks & 15;
|
||||
t1.stage3_ticks = 0;
|
||||
break;
|
||||
case 0xff: //T2OUT -- 4-bit counter value
|
||||
r = t2.stage3_ticks & 15;
|
||||
t2.stage3_ticks = 0;
|
||||
break;
|
||||
}
|
||||
} else if(addr < 0xffc0) {
|
||||
r = spcram[addr];
|
||||
} else {
|
||||
if(status.iplrom_enabled == true) {
|
||||
r = iplrom[addr & 0x3f];
|
||||
} else {
|
||||
r = spcram[addr];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
snes->notify(SNES::SPCRAM_READ, addr, r);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
void bAPU::spcram_write(uint16 addr, uint8 value) {
|
||||
if(addr >= 0x00f0 && addr <= 0x00ff) {
|
||||
switch(addr) {
|
||||
case 0xf0: //TEST -- operation unknown
|
||||
break;
|
||||
case 0xf1: //CONTROL
|
||||
status.iplrom_enabled = !!(value & 0x80);
|
||||
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
if(value & 0x20) {
|
||||
r_cpu->port_write(2, 0x00);
|
||||
r_cpu->port_write(3, 0x00);
|
||||
}
|
||||
if(value & 0x10) {
|
||||
r_cpu->port_write(0, 0x00);
|
||||
r_cpu->port_write(1, 0x00);
|
||||
}
|
||||
|
||||
//0->1 transistion resets timers
|
||||
if(t2.enabled == false && (value & 0x04)) {
|
||||
t2.stage2_ticks = 0;
|
||||
t2.stage3_ticks = 0;
|
||||
}
|
||||
t2.enabled = !!(value & 0x04);
|
||||
|
||||
if(t1.enabled == false && (value & 0x02)) {
|
||||
t1.stage2_ticks = 0;
|
||||
t1.stage3_ticks = 0;
|
||||
}
|
||||
t1.enabled = !!(value & 0x02);
|
||||
|
||||
if(t0.enabled == false && (value & 0x01)) {
|
||||
t0.stage2_ticks = 0;
|
||||
t0.stage3_ticks = 0;
|
||||
}
|
||||
t0.enabled = !!(value & 0x01);
|
||||
break;
|
||||
case 0xf2: //DSPADDR
|
||||
status.dsp_addr = value;
|
||||
break;
|
||||
case 0xf3: //DSPDATA
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
if(status.dsp_addr < 0x80) {
|
||||
r_dsp->write(status.dsp_addr & 0x7f, value);
|
||||
}
|
||||
break;
|
||||
case 0xf4: //CPUIO0
|
||||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
port_write(addr & 3, value);
|
||||
break;
|
||||
case 0xf8: //???
|
||||
case 0xf9: //??? - Mapped to SPCRAM
|
||||
spcram[addr] = value;
|
||||
break;
|
||||
case 0xfa: //T0TARGET
|
||||
t0.target = value;
|
||||
break;
|
||||
case 0xfb: //T1TARGET
|
||||
t1.target = value;
|
||||
break;
|
||||
case 0xfc: //T2TARGET
|
||||
t2.target = value;
|
||||
break;
|
||||
case 0xfd: //T0OUT
|
||||
case 0xfe: //T1OUT
|
||||
case 0xff: //T2OUT -- read-only registers
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//writes to $ffc0-$ffff always go to spcram,
|
||||
//even if the iplrom is enabled.
|
||||
spcram[addr] = value;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
snes->notify(SNES::SPCRAM_WRITE, addr, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8 bAPU::port_read(uint8 port) {
|
||||
return spcram[0xf4 + (port & 3)];
|
||||
}
|
||||
|
||||
void bAPU::port_write(uint8 port, uint8 value) {
|
||||
spcram[0xf4 + (port & 0x03)] = value;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_read() {
|
||||
uint8 r;
|
||||
r = spcram_read(regs.pc);
|
||||
regs.pc++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bAPU::op_read(uint8 mode, uint16 addr) {
|
||||
uint8 r;
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
r = spcram_read(addr);
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
r = spcram_read(((regs.p.p)?0x100:0x000) + (addr & 0xff));
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void bAPU::op_write(uint8 mode, uint16 addr, uint8 value) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
spcram_write(addr, value);
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
spcram_write(((regs.p.p)?0x100:0x000) + (addr & 0xff), value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bAPU::stack_read() {
|
||||
regs.sp++;
|
||||
return spcram_read(0x0100 | regs.sp);
|
||||
}
|
||||
|
||||
void bAPU::stack_write(uint8 value) {
|
||||
spcram_write(0x0100 | regs.sp, value);
|
||||
regs.sp--;
|
||||
}
|
||||
|
||||
uint8 *bAPU::get_spcram_handle() {
|
||||
if(!spcram) {
|
||||
alert("bAPU::get_spcram_handle() -- spcram uninitialized");
|
||||
}
|
||||
|
||||
return spcram;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
enum { OPMODE_ADDR, OPMODE_DP };
|
||||
uint8 *spcram;
|
||||
inline uint8 spcram_read (uint16 addr);
|
||||
inline void spcram_write(uint16 addr, uint8 value);
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
inline uint8 *get_spcram_handle();
|
||||
|
||||
inline uint8 op_read();
|
||||
inline uint8 op_read (uint8 mode, uint16 addr);
|
||||
inline void op_write(uint8 mode, uint16 addr, uint8 value);
|
||||
inline uint8 stack_read();
|
||||
inline void stack_write(uint8 value);
|
||||
@@ -0,0 +1,35 @@
|
||||
void bAPU::add_cycles(int cycles) {
|
||||
status.cycles_executed += cycles;
|
||||
|
||||
t0.add_cycles(cycles);
|
||||
t1.add_cycles(cycles);
|
||||
t2.add_cycles(cycles);
|
||||
}
|
||||
|
||||
uint32 bAPU::cycles_executed() {
|
||||
uint32 r = status.cycles_executed;
|
||||
status.cycles_executed = 0;
|
||||
return (r << 4) + (r << 3);
|
||||
}
|
||||
|
||||
//cycles should never be greater than 12. since the minimum
|
||||
//cycle_frequency value is 16, we don't have to worry about
|
||||
//two ticks occuring in one call to this function.
|
||||
void bAPU::bAPUTimer::add_cycles(int cycles) {
|
||||
//stage 1 increment
|
||||
stage1_ticks += cycles;
|
||||
if(stage1_ticks < cycle_frequency)return;
|
||||
|
||||
stage1_ticks -= cycle_frequency;
|
||||
if(enabled == false)return;
|
||||
|
||||
//stage 2 increment
|
||||
stage2_ticks++;
|
||||
|
||||
if(stage2_ticks != target)return;
|
||||
|
||||
//stage 3 increment
|
||||
stage2_ticks = 0;
|
||||
stage3_ticks++;
|
||||
stage3_ticks &= 15;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class bAPUTimer {
|
||||
public:
|
||||
uint8 cycle_frequency, target;
|
||||
uint8 stage1_ticks, stage2_ticks, stage3_ticks;
|
||||
bool enabled;
|
||||
inline void add_cycles(int cycles);
|
||||
} t0, t1, t2;
|
||||
inline void add_cycles(int cycles);
|
||||
inline uint32 cycles_executed();
|
||||
+37
-17
@@ -1,4 +1,26 @@
|
||||
//#define DEBUGGER
|
||||
#define BSNES_VERSION "0.016"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define MEMCORE bMemBus
|
||||
#define CPUCORE bCPU
|
||||
#define APUCORE bAPU
|
||||
#define DSPCORE bDSP
|
||||
#define PPUCORE bPPU
|
||||
|
||||
//game genie + pro action replay code support (~1-3% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
//enable GZ, ZIP format support
|
||||
//#define GZIP_SUPPORT
|
||||
|
||||
//enable JMA support
|
||||
//#define JMA_SUPPORT
|
||||
|
||||
//debugging extensions (~10% speed hit)
|
||||
#define DEBUGGER
|
||||
|
||||
//snes core polymorphism
|
||||
//(allow mem/cpu/apu/ppu overriding, ~10% speed hit)
|
||||
//#define POLYMORPHISM
|
||||
|
||||
//this should be declared in the port-specific makefiles
|
||||
@@ -11,20 +33,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libvector.h"
|
||||
#include "lib/libstring.h"
|
||||
#include "lib/libconfig.h"
|
||||
|
||||
inline uint16 read16(uint8 *addr, uint pos) {
|
||||
#ifdef ARCH_LSB
|
||||
return *((uint16*)(addr + pos));
|
||||
#else
|
||||
return (addr[pos]) | (addr[pos + 1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define _WIN32_
|
||||
#undef _UNIX_
|
||||
@@ -35,9 +43,21 @@ inline uint16 read16(uint8 *addr, uint pos) {
|
||||
#error "unknown architecture"
|
||||
#endif
|
||||
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libvector.h"
|
||||
#include "lib/libstring.h"
|
||||
#include "lib/libconfig.h"
|
||||
#include "lib/libbpf.h"
|
||||
|
||||
inline uint16 read16(uint8 *addr, uint pos) {
|
||||
#ifdef ARCH_LSB
|
||||
return *((uint16*)(addr + pos));
|
||||
#else
|
||||
return (addr[pos]) | (addr[pos + 1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
//platform-specific global functions
|
||||
void *memalloc(uint32 size, char *name = 0, ...);
|
||||
void memfree(void *mem, char *name = 0, ...);
|
||||
void alert(char *s, ...);
|
||||
void dprintf(char *s, ...);
|
||||
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
#include "../base.h"
|
||||
|
||||
void Cartridge::read_header() {
|
||||
cart.srtc = false;
|
||||
cart.sdd1 = false;
|
||||
cart.c4 = false;
|
||||
cart.dsp2 = false;
|
||||
cart.obc1 = false;
|
||||
|
||||
if(cart.header_index == 0x7fc0 && cart.rom_size >= 0x401000) {
|
||||
cart.mapper = EXLOROM;
|
||||
} else if(cart.header_index == 0x7fc0 && rom[cart.header_index + MAPPER] == 0x32) {
|
||||
cart.mapper = EXLOROM;
|
||||
} else if(cart.header_index == 0x7fc0) {
|
||||
cart.mapper = LOROM;
|
||||
} else if(cart.header_index == 0xffc0) {
|
||||
cart.mapper = HIROM;
|
||||
} else { //cart.header_index == 0x40ffc0
|
||||
cart.mapper = EXHIROM;
|
||||
}
|
||||
|
||||
uint8 mapper = rom[cart.header_index + MAPPER];
|
||||
uint8 rom_type = rom[cart.header_index + ROM_TYPE];
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
cart.srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
cart.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
cart.c4 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
cart.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
cart.obc1 = true;
|
||||
}
|
||||
|
||||
cart.cart_mmio = cart.c4 | cart.dsp2 | cart.obc1;
|
||||
|
||||
if(rom[cart.header_index + SRAM_SIZE] & 7) {
|
||||
cart.sram_size = 1024 << (rom[cart.header_index + SRAM_SIZE] & 7);
|
||||
} else {
|
||||
cart.sram_size = 0;
|
||||
}
|
||||
|
||||
cart.region = ((rom[cart.header_index + REGION] & 0x7f) < 2) ? NTSC : PAL;
|
||||
|
||||
memcpy(&cart.name, &rom[cart.header_index + CART_NAME], 21);
|
||||
cart.name[21] = 0;
|
||||
|
||||
for(int i = 0; i < 22; i++) {
|
||||
if(cart.name[i] & 0x80) {
|
||||
cart.name[i] = '?';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0,
|
||||
score_hi = 0,
|
||||
score_ex = 0;
|
||||
|
||||
if(rom_size < 0x010000) {
|
||||
//cart too small to be anything else
|
||||
cart.header_index = 0x007fc0;
|
||||
return;
|
||||
}
|
||||
|
||||
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
|
||||
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
|
||||
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + SRAM_SIZE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + SRAM_SIZE] < 0x08)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + REGION] < 14)score_lo++;
|
||||
if(rom[0xffc0 + REGION] < 14)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
|
||||
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
|
||||
|
||||
uint16 cksum, icksum;
|
||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_lo += 8;
|
||||
}
|
||||
|
||||
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(rom_size < 0x401000) {
|
||||
score_ex = 0;
|
||||
} else {
|
||||
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
|
||||
else score_ex += 16;
|
||||
}
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
cart.header_index = 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
cart.header_index = 0x00ffc0;
|
||||
} else {
|
||||
cart.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_sram() {
|
||||
if(cart.sram_size == 0) {
|
||||
sram = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
FileReader ff(sram_fn);
|
||||
if(!ff.ready()) {
|
||||
sram = (uint8*)malloc(cart.sram_size);
|
||||
memset(sram, 0, cart.sram_size);
|
||||
return;
|
||||
}
|
||||
|
||||
sram = ff.read(cart.sram_size);
|
||||
}
|
||||
|
||||
void Cartridge::save_sram() {
|
||||
if(cart.sram_size == 0)return;
|
||||
|
||||
FileWriter ff(sram_fn);
|
||||
if(!ff.ready())return;
|
||||
|
||||
ff.write(sram, cart.sram_size);
|
||||
}
|
||||
|
||||
void Cartridge::load_rom(Reader *rf) {
|
||||
base_rom = rf->read();
|
||||
rom_size = rf->size();
|
||||
|
||||
if((rom_size & 0x7fff) == 0x0200) {
|
||||
rom = base_rom + 512;
|
||||
rom_size -= 512;
|
||||
} else {
|
||||
rom = base_rom;
|
||||
}
|
||||
|
||||
cart.rom_size = rom_size;
|
||||
|
||||
cart.crc32 = 0xffffffff;
|
||||
for(int32 i = 0; i < cart.rom_size; i++) {
|
||||
cart.crc32 = crc32_adjust(cart.crc32, rom[i]);
|
||||
}
|
||||
cart.crc32 = ~cart.crc32;
|
||||
}
|
||||
|
||||
void Cartridge::patch_rom(Reader *rf) {
|
||||
uint8 *patch_data = rf->read();
|
||||
uint32 patch_size = rf->size();
|
||||
BPF bpf;
|
||||
if(patch_size < 34)return;
|
||||
|
||||
uint32 target;
|
||||
target = patch_data[BPF::INDEX_FORMAT + 0] << 0;
|
||||
target |= patch_data[BPF::INDEX_FORMAT + 1] << 8;
|
||||
target |= patch_data[BPF::INDEX_FORMAT + 2] << 16;
|
||||
target |= patch_data[BPF::INDEX_FORMAT + 3] << 24;
|
||||
if(target != BPF::FORMAT_SNES) {
|
||||
alert("Warning: BPF patch file is not in SNES format!\n\n"
|
||||
"The patch will still be applied, but it will not be "
|
||||
"possible to determine whether the patch was created "
|
||||
"against an image with a header or without a header.\n\n"
|
||||
"bsnes is now forced to assume the patch was created "
|
||||
"against a headerless source image. If this is not the "
|
||||
"case, then patching will fail!\n\n"
|
||||
"If you are the author of this patch, please recreate "
|
||||
"the patch in SNES format.\n\n"
|
||||
"If you are not the patch author, please contact the "
|
||||
"author and ask them to create an SNES format BPF patch.");
|
||||
}
|
||||
|
||||
if(bpf.apply_patch(patch_size, patch_data, rom_size, rom) == true) {
|
||||
SafeFree(base_rom);
|
||||
uint8 *temp = bpf.get_output_handle(rom_size);
|
||||
base_rom = (uint8*)malloc(rom_size);
|
||||
memcpy(base_rom, temp, rom_size);
|
||||
rom = base_rom;
|
||||
cart.rom_size = rom_size;
|
||||
} else {
|
||||
alert("Failed to apply patch.\n\nThis could be because the patch itself "
|
||||
"does not match its internal checksum, because the ROM loaded does not "
|
||||
"match the patch information for either the original or modified file, "
|
||||
"or because the patched file does not match the checksum of either the "
|
||||
"original or modified file that is stored inside the patch.\n\n"
|
||||
"The original ROM image will be used instead.");
|
||||
}
|
||||
SafeFree(patch_data);
|
||||
}
|
||||
|
||||
bool Cartridge::load(const char *fn) {
|
||||
if(cart_loaded == true)return false;
|
||||
if(strlen(fn) < 3)return false;
|
||||
|
||||
dprintf("* Loading \"%s\"...", fn);
|
||||
|
||||
strcpy(rom_fn, fn);
|
||||
|
||||
switch(Reader::detect(rom_fn)) {
|
||||
case Reader::RF_NORMAL: {
|
||||
FileReader ff(rom_fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
load_rom(static_cast<Reader*>(&ff));
|
||||
break;
|
||||
}
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(rom_fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
load_rom(static_cast<Reader*>(&gf));
|
||||
break;
|
||||
}
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(rom_fn);
|
||||
load_rom(static_cast<Reader*>(&zf));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(rom_fn);
|
||||
load_rom(static_cast<Reader*>(&jf));
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//remove ROM extension
|
||||
strcpy(sram_fn, fn);
|
||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
||||
if(sram_fn[i] == '.') {
|
||||
sram_fn[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//check for bpf patch
|
||||
#ifdef GZIP_SUPPORT
|
||||
strcpy(patch_fn, sram_fn);
|
||||
strcat(patch_fn, ".bpz");
|
||||
if(fexists(patch_fn)) {
|
||||
ZipReader zf(patch_fn);
|
||||
patch_rom(static_cast<Reader*>(&zf));
|
||||
} else {
|
||||
#endif
|
||||
strcpy(patch_fn, sram_fn);
|
||||
strcat(patch_fn, ".bpf");
|
||||
if(fexists(patch_fn)) {
|
||||
FileReader ff(patch_fn);
|
||||
patch_rom(static_cast<Reader*>(&ff));
|
||||
}
|
||||
#ifdef GZIP_SUPPORT
|
||||
}
|
||||
#endif
|
||||
|
||||
//add SRAM extension
|
||||
strcat(sram_fn, ".");
|
||||
strcat(sram_fn, config::fs.save_ext.sget());
|
||||
|
||||
//override default path (current directory)?
|
||||
if(strmatch(config::fs.save_path.sget(), "") == false) {
|
||||
//remove path if fs.sram_path was specified
|
||||
string new_fn, parts;
|
||||
strcpy(new_fn, sram_fn);
|
||||
replace(new_fn, "\\", "/");
|
||||
split(parts, "/", new_fn);
|
||||
|
||||
//add new SRAM path
|
||||
strcpy(new_fn, config::fs.save_path.sget());
|
||||
|
||||
//append fs.base_path if fs.sram_path is not fully-qualified path
|
||||
if(strbegin(new_fn, "./") == true) {
|
||||
strltrim(new_fn, "./");
|
||||
strcpy(new_fn[1], new_fn[0]);
|
||||
strcpy(new_fn[0], config::fs.base_path.sget());
|
||||
strcat(new_fn[0], new_fn[1]);
|
||||
}
|
||||
|
||||
//finally, append SRAM file name
|
||||
strcat(new_fn, parts[count(parts) - 1]);
|
||||
strcpy(sram_fn, strptr(new_fn));
|
||||
}
|
||||
|
||||
//load cheat file if it exists
|
||||
strcpy(cheat_fn, sram_fn);
|
||||
strrtrim(cheat_fn, config::fs.save_ext.sget());
|
||||
strrtrim(cheat_fn, ".");
|
||||
strcat(cheat_fn, ".cht");
|
||||
if(fexists(cheat_fn) == true) {
|
||||
FileReader ff(cheat_fn);
|
||||
cheat.load(static_cast<Reader*>(&ff));
|
||||
}
|
||||
|
||||
find_header();
|
||||
read_header();
|
||||
load_sram();
|
||||
cart_loaded = true;
|
||||
r_mem->load_cart();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::unload() {
|
||||
if(cart_loaded == false)return false;
|
||||
|
||||
r_mem->unload_cart();
|
||||
|
||||
if(base_rom) {
|
||||
SafeFree(base_rom);
|
||||
}
|
||||
|
||||
if(sram) {
|
||||
save_sram();
|
||||
SafeFree(sram);
|
||||
}
|
||||
|
||||
if(cheat.count() > 0 || fexists(cheat_fn)) {
|
||||
FileWriter ff(cheat_fn);
|
||||
cheat.save(static_cast<Writer*>(&ff));
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
cart_loaded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
cart_loaded = false;
|
||||
|
||||
base_rom = 0;
|
||||
rom = 0;
|
||||
sram = 0;
|
||||
rom_size = 0;
|
||||
}
|
||||
|
||||
Cartridge::~Cartridge() {
|
||||
if(cart_loaded == true) {
|
||||
unload();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
class Cartridge {
|
||||
public:
|
||||
bool cart_loaded;
|
||||
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096];
|
||||
|
||||
uint8 *base_rom, *rom, *sram;
|
||||
uint32 rom_size;
|
||||
|
||||
enum {
|
||||
//header fields
|
||||
CART_NAME = 0x00,
|
||||
MAPPER = 0x15,
|
||||
ROM_TYPE = 0x16,
|
||||
ROM_SIZE = 0x17,
|
||||
SRAM_SIZE = 0x18,
|
||||
REGION = 0x19,
|
||||
LICENSE = 0x1a,
|
||||
VERSION = 0x1b,
|
||||
ICKSUM = 0x1c,
|
||||
CKSUM = 0x1e,
|
||||
|
||||
//regions
|
||||
NTSC = 0,
|
||||
PAL = 1,
|
||||
|
||||
//memory mappers
|
||||
LOROM = 0x20,
|
||||
HIROM = 0x21,
|
||||
EXLOROM = 0x22,
|
||||
EXHIROM = 0x25,
|
||||
};
|
||||
|
||||
struct {
|
||||
uint32 crc32;
|
||||
uint32 header_index;
|
||||
|
||||
char name[32];
|
||||
uint32 rom_size;
|
||||
uint32 sram_size;
|
||||
bool region;
|
||||
|
||||
uint32 mapper;
|
||||
|
||||
//set to true for games that need cart MMIO mapping (c4, dsp-n, ...),
|
||||
//for games that map outside the standard MMIO range of $2000-$5fff
|
||||
bool cart_mmio;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool c4;
|
||||
bool dsp2;
|
||||
bool obc1;
|
||||
} cart;
|
||||
|
||||
void load_rom(Reader *rf);
|
||||
void patch_rom(Reader *rf);
|
||||
void load_sram();
|
||||
void save_sram();
|
||||
void find_header();
|
||||
void read_header();
|
||||
bool loaded() { return cart_loaded; }
|
||||
bool load(const char *fn);
|
||||
bool unload();
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
@@ -0,0 +1,334 @@
|
||||
#include "../base.h"
|
||||
|
||||
/*****
|
||||
* string <> binary code translation routines
|
||||
* decode() "7e1234:56" -> 0x7e123456
|
||||
* encode() 0x7e123456 -> "7e1234:56"
|
||||
*****/
|
||||
|
||||
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
||||
string t, part;
|
||||
strcpy(t, str);
|
||||
strlower(t);
|
||||
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
|
||||
type = CT_PRO_ACTION_REPLAY;
|
||||
replace(t, ":", "");
|
||||
uint32 r = strhex(t);
|
||||
addr = r >> 8;
|
||||
data = r & 0xff;
|
||||
return true;
|
||||
} else if(strlen(t) == 9 && strptr(t)[4] == '-') {
|
||||
type = CT_GAME_GENIE;
|
||||
replace(t, "-", "");
|
||||
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
||||
uint32 r = strhex(t);
|
||||
//8421 8421 8421 8421 8421 8421
|
||||
//abcd efgh ijkl mnop qrst uvwx
|
||||
//ijkl qrst opab cduv wxef ghmn
|
||||
addr = (!!(r & 0x002000) << 23) | (!!(r & 0x001000) << 22) |
|
||||
(!!(r & 0x000800) << 21) | (!!(r & 0x000400) << 20) |
|
||||
(!!(r & 0x000020) << 19) | (!!(r & 0x000010) << 18) |
|
||||
(!!(r & 0x000008) << 17) | (!!(r & 0x000004) << 16) |
|
||||
(!!(r & 0x800000) << 15) | (!!(r & 0x400000) << 14) |
|
||||
(!!(r & 0x200000) << 13) | (!!(r & 0x100000) << 12) |
|
||||
(!!(r & 0x000002) << 11) | (!!(r & 0x000001) << 10) |
|
||||
(!!(r & 0x008000) << 9) | (!!(r & 0x004000) << 8) |
|
||||
(!!(r & 0x080000) << 7) | (!!(r & 0x040000) << 6) |
|
||||
(!!(r & 0x020000) << 5) | (!!(r & 0x010000) << 4) |
|
||||
(!!(r & 0x000200) << 3) | (!!(r & 0x000100) << 2) |
|
||||
(!!(r & 0x000080) << 1) | (!!(r & 0x000040) << 0);
|
||||
data = r >> 24;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
||||
if(type == CT_PRO_ACTION_REPLAY) {
|
||||
sprintf(str, "%0.6x:%0.2x", addr, data);
|
||||
return true;
|
||||
} else if(type == CT_GAME_GENIE) {
|
||||
uint32 r = addr;
|
||||
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
||||
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
||||
(!!(r & 0x000080) << 19) | (!!(r & 0x000040) << 18) |
|
||||
(!!(r & 0x000020) << 17) | (!!(r & 0x000010) << 16) |
|
||||
(!!(r & 0x000200) << 15) | (!!(r & 0x000100) << 14) |
|
||||
(!!(r & 0x800000) << 13) | (!!(r & 0x400000) << 12) |
|
||||
(!!(r & 0x200000) << 11) | (!!(r & 0x100000) << 10) |
|
||||
(!!(r & 0x000008) << 9) | (!!(r & 0x000004) << 8) |
|
||||
(!!(r & 0x000002) << 7) | (!!(r & 0x000001) << 6) |
|
||||
(!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4) |
|
||||
(!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2) |
|
||||
(!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
|
||||
sprintf(str, "%0.2x%0.2x-%0.4x", data, addr >> 16, addr & 0xffff);
|
||||
strtr(str, "0123456789abcdef", "df4709156bc8a23e");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* address lookup table manipulation and mirroring
|
||||
* mirror_address() 0x000000 -> 0x7e0000
|
||||
* set() enable specified address, mirror accordingly
|
||||
* clear() disable specified address, mirror accordingly
|
||||
*****/
|
||||
|
||||
uint Cheat::mirror_address(uint addr) {
|
||||
if((addr & 0x40e000) != 0x0000)return addr;
|
||||
//8k WRAM mirror
|
||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||
return (0x7e0000 + (addr & 0x1fff));
|
||||
}
|
||||
|
||||
void Cheat::set(uint32 addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
mask[addr >> 3] |= 1 << (addr & 7);
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||
uint mirror;
|
||||
for(int x = 0; x <= 0x3f; x++) {
|
||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cheat::clear(uint32 addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
//is there more than one cheat code using the same address
|
||||
//(and likely a different override value) that is enabled?
|
||||
//if so, do not clear code lookup table entry for this address.
|
||||
uint8 r;
|
||||
if(read(addr, r) == true)return;
|
||||
|
||||
mask[addr >> 3] &= ~(1 << (addr & 7));
|
||||
if((addr & 0xffe000) == 0x7e0000) {
|
||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||
uint mirror;
|
||||
for(int x = 0; x <= 0x3f; x++) {
|
||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
* read() is used by MemBus::read() if Cheat::enabled(addr)
|
||||
* returns true to look up cheat code.
|
||||
* returns true if cheat code was found, false if it was not.
|
||||
* when true, cheat code substitution value is stored in data.
|
||||
*****/
|
||||
|
||||
bool Cheat::read(uint32 addr, uint8 &data) {
|
||||
addr = mirror_address(addr);
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
if(enabled(i) == false)continue;
|
||||
if(addr == mirror_address(index[i].addr)) {
|
||||
data = index[i].data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//code not found, or code is disabled
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* update_cheat_status() will scan to see if any codes are
|
||||
* enabled. if any are, make sure the cheat system is on.
|
||||
* otherwise, turn cheat system off to speed up emulation.
|
||||
*****/
|
||||
void Cheat::update_cheat_status() {
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
if(index[i].enabled) {
|
||||
cheat_enabled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
cheat_enabled = false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* cheat list manipulation routines
|
||||
*****/
|
||||
|
||||
bool Cheat::add(bool enable, char *code, char *desc) {
|
||||
if(cheat_count >= CHEAT_LIMIT)return false;
|
||||
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false)return false;
|
||||
|
||||
index[cheat_count].enabled = enable;
|
||||
index[cheat_count].addr = addr;
|
||||
index[cheat_count].data = data;
|
||||
len = strlen(code);
|
||||
len = len > 16 ? 16 : len;
|
||||
memcpy(index[cheat_count].code, code, len);
|
||||
index[cheat_count].code[len] = 0;
|
||||
len = strlen(desc);
|
||||
len = len > 128 ? 128 : len;
|
||||
memcpy(index[cheat_count].desc, desc, len);
|
||||
index[cheat_count].desc[len] = 0;
|
||||
cheat_count++;
|
||||
(enable) ? set(addr) : clear(addr);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
|
||||
if(n >= cheat_count)return false;
|
||||
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false)return false;
|
||||
|
||||
//disable current code and clear from code lookup table
|
||||
index[n].enabled = false;
|
||||
clear(index[n].addr);
|
||||
|
||||
//update code and enable in code lookup table
|
||||
index[n].enabled = enable;
|
||||
index[n].addr = addr;
|
||||
index[n].data = data;
|
||||
len = strlen(code);
|
||||
len = len > 16 ? 16 : len;
|
||||
memcpy(index[n].code, code, len);
|
||||
index[n].code[len] = 0;
|
||||
len = strlen(desc);
|
||||
len = len > 128 ? 128 : len;
|
||||
memcpy(index[n].desc, desc, len);
|
||||
index[n].desc[len] = 0;
|
||||
set(addr);
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::remove(uint32 n) {
|
||||
if(n >= cheat_count)return false;
|
||||
|
||||
for(int i = n; i < cheat_count; i++) {
|
||||
index[i].enabled = index[i + 1].enabled;
|
||||
index[i].addr = index[i + 1].addr;
|
||||
index[i].data = index[i + 1].data;
|
||||
strcpy(index[i].desc, index[i + 1].desc);
|
||||
}
|
||||
|
||||
cheat_count--;
|
||||
|
||||
update_cheat_status();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
|
||||
if(n >= cheat_count)return false;
|
||||
enable = index[n].enabled;
|
||||
addr = index[n].addr;
|
||||
data = index[n].data;
|
||||
strcpy(code, index[n].code);
|
||||
strcpy(desc, index[n].desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****
|
||||
* code status modifier routines
|
||||
*****/
|
||||
|
||||
bool Cheat::enabled(uint32 n) {
|
||||
if(n >= cheat_count)return false;
|
||||
return index[n].enabled;
|
||||
}
|
||||
|
||||
void Cheat::enable(uint32 n) {
|
||||
if(n >= cheat_count)return;
|
||||
index[n].enabled = true;
|
||||
set(index[n].addr);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
void Cheat::disable(uint32 n) {
|
||||
if(n >= cheat_count)return;
|
||||
index[n].enabled = false;
|
||||
clear(index[n].addr);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
/*****
|
||||
* cheat file manipulation routines
|
||||
*****/
|
||||
|
||||
bool Cheat::load(Reader *rf) {
|
||||
if(!rf->ready())return false;
|
||||
|
||||
uint8 *raw_data = rf->read();
|
||||
string data;
|
||||
raw_data[rf->size()] = 0;
|
||||
strcpy(data, (char*)raw_data);
|
||||
SafeFree(raw_data);
|
||||
replace(data, "\r\n", "\n");
|
||||
string line;
|
||||
split(line, "\n", data);
|
||||
for(int i = 0; i < ::count(line); i++) {
|
||||
string part;
|
||||
uint8 en = *(strptr(line[i]));
|
||||
if(en == '+') {
|
||||
strltrim(line[i], "+");
|
||||
} else if(en == '-') {
|
||||
strltrim(line[i], "-");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
qreplace(line[i], " ", "");
|
||||
qsplit(part, ",", line[i]);
|
||||
if(::count(part) != 2)continue;
|
||||
strunquote(part[1]);
|
||||
add(en == '+', strptr(part[0]), strptr(part[1]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::save(Writer *wf) {
|
||||
if(!wf->ready())return false;
|
||||
|
||||
string data;
|
||||
char t[4096];
|
||||
strcpy(data, "");
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
sprintf(t, "%c%s, \"%s\"\r\n", index[i].enabled ? '+' : '-', index[i].code, index[i].desc);
|
||||
strcat(data, t);
|
||||
}
|
||||
|
||||
wf->write((uint8*)strptr(data), strlen(data));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****
|
||||
* initialization routines
|
||||
*****/
|
||||
|
||||
void Cheat::clear() {
|
||||
cheat_enabled = false;
|
||||
cheat_count = 0;
|
||||
memset(mask, 0, 0x200000);
|
||||
for(int i = 0; i < CHEAT_LIMIT + 1; i++) {
|
||||
index[i].enabled = false;
|
||||
index[i].addr = 0x000000;
|
||||
index[i].data = 0x00;
|
||||
strcpy(index[i].code, "");
|
||||
strcpy(index[i].desc, "");
|
||||
}
|
||||
}
|
||||
|
||||
Cheat::Cheat() {
|
||||
clear();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#define CHEAT_LIMIT 1024
|
||||
|
||||
class Cheat {
|
||||
public:
|
||||
enum { CT_PRO_ACTION_REPLAY, CT_GAME_GENIE };
|
||||
|
||||
struct CheatIndex {
|
||||
bool enabled;
|
||||
uint32 addr;
|
||||
uint8 data;
|
||||
char code[ 16 + 1];
|
||||
char desc[128 + 1];
|
||||
} index[CHEAT_LIMIT + 1];
|
||||
bool cheat_enabled;
|
||||
uint32 cheat_count;
|
||||
uint8 mask[0x200000];
|
||||
|
||||
inline bool enabled() { return cheat_enabled; }
|
||||
inline uint count() { return cheat_count; }
|
||||
inline bool exists(uint32 addr) { return bool(mask[addr >> 3] & 1 << (addr & 7)); }
|
||||
|
||||
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
|
||||
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
|
||||
|
||||
private:
|
||||
uint mirror_address(uint addr);
|
||||
void set(uint32 addr);
|
||||
void clear(uint32 addr);
|
||||
public:
|
||||
|
||||
bool read(uint32 addr, uint8 &data);
|
||||
|
||||
void update_cheat_status();
|
||||
bool add(bool enable, char *code, char *desc);
|
||||
bool edit(uint32 n, bool enable, char *code, char *desc);
|
||||
bool get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc);
|
||||
bool remove (uint32 n);
|
||||
bool enabled(uint32 n);
|
||||
void enable (uint32 n);
|
||||
void disable(uint32 n);
|
||||
bool load(Reader *rf);
|
||||
bool save(Writer *wf);
|
||||
void clear();
|
||||
|
||||
Cheat();
|
||||
};
|
||||
|
||||
extern Cheat cheat;
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
C4 emulation
|
||||
|
||||
Used in Rockman X2/X3 (Megaman X2/X3)
|
||||
Portions (c) anomie, Overload, zsKnight, Nach, byuu
|
||||
*/
|
||||
|
||||
#include "../../base.h"
|
||||
|
||||
#include "c4data.cpp"
|
||||
#include "c4fn.cpp"
|
||||
#include "c4oam.cpp"
|
||||
#include "c4ops.cpp"
|
||||
|
||||
void C4::init() {}
|
||||
void C4::enable() {}
|
||||
|
||||
uint32 C4::ldr(uint8 r) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
|
||||
}
|
||||
|
||||
void C4::str(uint8 r, uint32 data) {
|
||||
uint16 addr = 0x0080 + (r * 3);
|
||||
reg[addr ] = (data);
|
||||
reg[addr + 1] = (data >> 8);
|
||||
reg[addr + 2] = (data >> 16);
|
||||
}
|
||||
|
||||
void C4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
|
||||
int64 rx = x & 0xffffff;
|
||||
int64 ry = y & 0xffffff;
|
||||
if(rx & 0x800000)rx |= ~0x7fffff;
|
||||
if(ry & 0x800000)ry |= ~0x7fffff;
|
||||
|
||||
rx *= ry;
|
||||
|
||||
rl = (rx) & 0xffffff;
|
||||
rh = (rx >> 24) & 0xffffff;
|
||||
}
|
||||
|
||||
uint32 C4::sin(uint32 rx) {
|
||||
r0 = rx & 0x1ff;
|
||||
if(r0 & 0x100)r0 ^= 0x1ff;
|
||||
if(r0 & 0x080)r0 ^= 0x0ff;
|
||||
if(rx & 0x100) {
|
||||
return sin_table[r0 + 0x80];
|
||||
} else {
|
||||
return sin_table[r0];
|
||||
}
|
||||
}
|
||||
|
||||
uint32 C4::cos(uint32 rx) {
|
||||
return sin(rx + 0x080);
|
||||
}
|
||||
|
||||
void C4::immediate_reg(uint32 start) {
|
||||
r0 = ldr(0);
|
||||
for(uint32 i=start;i<48;i++) {
|
||||
if((r0 & 0x0fff) < 0x0c00) {
|
||||
ram[r0 & 0x0fff] = immediate_data[i];
|
||||
}
|
||||
r0++;
|
||||
}
|
||||
str(0, r0);
|
||||
}
|
||||
|
||||
void C4::transfer_data() {
|
||||
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);
|
||||
|
||||
for(uint32 i=0;i<count;i++) {
|
||||
write(dest++, r_mem->read(src++));
|
||||
}
|
||||
}
|
||||
|
||||
void C4::write(uint16 addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
//ram
|
||||
ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr < 0x1f00) {
|
||||
//unmapped
|
||||
return;
|
||||
}
|
||||
|
||||
//command register
|
||||
reg[addr & 0xff] = data;
|
||||
|
||||
if(addr == 0x1f47) {
|
||||
//memory transfer
|
||||
transfer_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr == 0x1f4f) {
|
||||
//c4 command
|
||||
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
|
||||
//c4 test command
|
||||
reg[0x80] = data >> 2;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(data) {
|
||||
case 0x00:op00();break;
|
||||
case 0x01:op01();break;
|
||||
case 0x05:op05();break;
|
||||
case 0x0d:op0d();break;
|
||||
case 0x10:op10();break;
|
||||
case 0x13:op13();break;
|
||||
case 0x15:op15();break;
|
||||
case 0x1f:op1f();break;
|
||||
case 0x22:op22();break;
|
||||
case 0x25:op25();break;
|
||||
case 0x2d:op2d();break;
|
||||
case 0x40:op40();break;
|
||||
case 0x54:op54();break;
|
||||
case 0x5c:op5c();break;
|
||||
case 0x5e:op5e();break;
|
||||
case 0x60:op60();break;
|
||||
case 0x62:op62();break;
|
||||
case 0x64:op64();break;
|
||||
case 0x66:op66();break;
|
||||
case 0x68:op68();break;
|
||||
case 0x6a:op6a();break;
|
||||
case 0x6c:op6c();break;
|
||||
case 0x6e:op6e();break;
|
||||
case 0x70:op70();break;
|
||||
case 0x72:op72();break;
|
||||
case 0x74:op74();break;
|
||||
case 0x76:op76();break;
|
||||
case 0x78:op78();break;
|
||||
case 0x7a:op7a();break;
|
||||
case 0x7c:op7c();break;
|
||||
case 0x89:op89();break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C4::writeb(uint16 addr, uint8 data) {
|
||||
write(addr, data);
|
||||
}
|
||||
|
||||
void C4::writew(uint16 addr, uint16 data) {
|
||||
write(addr, data);
|
||||
write(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void C4::writel(uint16 addr, uint32 data) {
|
||||
write(addr, data);
|
||||
write(addr + 1, data >> 8);
|
||||
write(addr + 2, data >> 16);
|
||||
}
|
||||
|
||||
uint8 C4::read(uint16 addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if(addr < 0x0c00) {
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
if(addr >= 0x1f00) {
|
||||
return reg[addr & 0xff];
|
||||
}
|
||||
|
||||
return r_cpu->regs.mdr;
|
||||
}
|
||||
|
||||
uint8 C4::readb(uint16 addr) {
|
||||
return read(addr);
|
||||
}
|
||||
|
||||
uint16 C4::readw(uint16 addr) {
|
||||
return read(addr) | (read(addr + 1) << 8);
|
||||
}
|
||||
|
||||
uint32 C4::readl(uint16 addr) {
|
||||
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
|
||||
}
|
||||
|
||||
void C4::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void C4::reset() {
|
||||
memset(ram, 0, 0x0c00);
|
||||
memset(reg, 0, 0x0100);
|
||||
}
|
||||
|
||||
C4::C4() {}
|
||||
@@ -0,0 +1,94 @@
|
||||
class C4 {
|
||||
private:
|
||||
uint8 ram[0x0c00];
|
||||
uint8 reg[0x0100];
|
||||
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
|
||||
r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
|
||||
static const uint8 immediate_data[48];
|
||||
static const uint16 wave_data[40];
|
||||
static const uint32 sin_table[256];
|
||||
|
||||
static const int16 SinTable[512];
|
||||
static const int16 CosTable[512];
|
||||
|
||||
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
||||
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
||||
|
||||
double tanval;
|
||||
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
||||
|
||||
void C4TransfWireFrame();
|
||||
void C4TransfWireFrame2();
|
||||
void C4CalcWireFrame();
|
||||
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
|
||||
void C4DrawWireFrame();
|
||||
void C4DoScaleRotate(int row_padding);
|
||||
|
||||
public:
|
||||
uint32 ldr(uint8 r);
|
||||
void str(uint8 r, uint32 data);
|
||||
void mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh);
|
||||
uint32 sin(uint32 rx);
|
||||
uint32 cos(uint32 rx);
|
||||
|
||||
void transfer_data();
|
||||
void immediate_reg(uint32 num);
|
||||
|
||||
void op00_00();
|
||||
void op00_03();
|
||||
void op00_05();
|
||||
void op00_07();
|
||||
void op00_08();
|
||||
void op00_0b();
|
||||
void op00_0c();
|
||||
|
||||
void op00();
|
||||
void op01();
|
||||
void op05();
|
||||
void op0d();
|
||||
void op10();
|
||||
void op13();
|
||||
void op15();
|
||||
void op1f();
|
||||
void op22();
|
||||
void op25();
|
||||
void op2d();
|
||||
void op40();
|
||||
void op54();
|
||||
void op5c();
|
||||
void op5e();
|
||||
void op60();
|
||||
void op62();
|
||||
void op64();
|
||||
void op66();
|
||||
void op68();
|
||||
void op6a();
|
||||
void op6c();
|
||||
void op6e();
|
||||
void op70();
|
||||
void op72();
|
||||
void op74();
|
||||
void op76();
|
||||
void op78();
|
||||
void op7a();
|
||||
void op7c();
|
||||
void op89();
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void write (uint16 addr, uint8 data);
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
void writel(uint16 addr, uint32 data);
|
||||
|
||||
uint8 read (uint16 addr);
|
||||
uint8 readb(uint16 addr);
|
||||
uint16 readw(uint16 addr);
|
||||
uint32 readl(uint16 addr);
|
||||
|
||||
C4();
|
||||
};
|
||||
@@ -0,0 +1,183 @@
|
||||
const uint8 C4::immediate_data[48] = {
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
|
||||
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
|
||||
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
|
||||
};
|
||||
|
||||
const uint16 C4::wave_data[40] = {
|
||||
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
|
||||
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
|
||||
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
|
||||
0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060a, 0x060c, 0x060e,
|
||||
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
|
||||
};
|
||||
|
||||
const uint32 C4::sin_table[256] = {
|
||||
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
|
||||
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
|
||||
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
|
||||
0x004a50, 0x004d50, 0x00504d, 0x005347, 0x00563e, 0x005931, 0x005c22, 0x005f0e,
|
||||
0x0061f7, 0x0064dc, 0x0067bd, 0x006a9b, 0x006d74, 0x007049, 0x007319, 0x0075e5,
|
||||
0x0078ad, 0x007b70, 0x007e2e, 0x0080e7, 0x00839c, 0x00864b, 0x0088f5, 0x008b9a,
|
||||
0x008e39, 0x0090d3, 0x009368, 0x0095f6, 0x00987f, 0x009b02, 0x009d7f, 0x009ff6,
|
||||
0x00a267, 0x00a4d2, 0x00a736, 0x00a994, 0x00abeb, 0x00ae3b, 0x00b085, 0x00b2c8,
|
||||
0x00b504, 0x00b73a, 0x00b968, 0x00bb8f, 0x00bdae, 0x00bfc7, 0x00c1d8, 0x00c3e2,
|
||||
0x00c5e4, 0x00c7de, 0x00c9d1, 0x00cbbb, 0x00cd9f, 0x00cf7a, 0x00d14d, 0x00d318,
|
||||
0x00d4db, 0x00d695, 0x00d848, 0x00d9f2, 0x00db94, 0x00dd2d, 0x00debe, 0x00e046,
|
||||
0x00e1c5, 0x00e33c, 0x00e4aa, 0x00e60f, 0x00e76b, 0x00e8bf, 0x00ea09, 0x00eb4b,
|
||||
0x00ec83, 0x00edb2, 0x00eed8, 0x00eff5, 0x00f109, 0x00f213, 0x00f314, 0x00f40b,
|
||||
0x00f4fa, 0x00f5de, 0x00f6ba, 0x00f78b, 0x00f853, 0x00f912, 0x00f9c7, 0x00fa73,
|
||||
0x00fb14, 0x00fbac, 0x00fc3b, 0x00fcbf, 0x00fd3a, 0x00fdab, 0x00fe13, 0x00fe70,
|
||||
0x00fec4, 0x00ff0e, 0x00ff4e, 0x00ff84, 0x00ffb1, 0x00ffd3, 0x00ffec, 0x00fffb,
|
||||
0x000000, 0xfffcdb, 0xfff9b7, 0xfff693, 0xfff370, 0xfff04d, 0xffed2a, 0xffea09,
|
||||
0xffe6e8, 0xffe3c8, 0xffe0a9, 0xffdd8c, 0xffda6f, 0xffd755, 0xffd43b, 0xffd124,
|
||||
0xffce0e, 0xffcafa, 0xffc7e8, 0xffc4d9, 0xffc1cc, 0xffbec1, 0xffbbb8, 0xffb8b2,
|
||||
0xffb5af, 0xffb2af, 0xffafb2, 0xffacb8, 0xffa9c1, 0xffa6ce, 0xffa3dd, 0xffa0f1,
|
||||
0xff9e08, 0xff9b23, 0xff9842, 0xff9564, 0xff928b, 0xff8fb6, 0xff8ce6, 0xff8a1a,
|
||||
0xff8752, 0xff848f, 0xff81d1, 0xff7f18, 0xff7c63, 0xff79b4, 0xff770a, 0xff7465,
|
||||
0xff71c6, 0xff6f2c, 0xff6c97, 0xff6a09, 0xff6780, 0xff64fd, 0xff6280, 0xff6009,
|
||||
0xff5d98, 0xff5b2d, 0xff58c9, 0xff566b, 0xff5414, 0xff51c4, 0xff4f7a, 0xff4d37,
|
||||
0xff4afb, 0xff48c5, 0xff4697, 0xff4470, 0xff4251, 0xff4038, 0xff3e27, 0xff3c1e,
|
||||
0xff3a1b, 0xff3821, 0xff362e, 0xff3444, 0xff3260, 0xff3085, 0xff2eb2, 0xff2ce7,
|
||||
0xff2b24, 0xff296a, 0xff27b7, 0xff260d, 0xff246b, 0xff22d2, 0xff2141, 0xff1fb9,
|
||||
0xff1e3a, 0xff1cc3, 0xff1b55, 0xff19f0, 0xff1894, 0xff1740, 0xff15f6, 0xff14b4,
|
||||
0xff137c, 0xff124d, 0xff1127, 0xff100a, 0xff0ef6, 0xff0dec, 0xff0ceb, 0xff0bf4,
|
||||
0xff0b05, 0xff0a21, 0xff0945, 0xff0874, 0xff07ac, 0xff06ed, 0xff0638, 0xff058d,
|
||||
0xff04eb, 0xff0453, 0xff03c4, 0xff0340, 0xff02c5, 0xff0254, 0xff01ec, 0xff018f,
|
||||
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
|
||||
};
|
||||
|
||||
const int16 C4::SinTable[512] = {
|
||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
|
||||
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
|
||||
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
|
||||
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
|
||||
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
|
||||
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
|
||||
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
|
||||
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
|
||||
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
|
||||
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
|
||||
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765,
|
||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
|
||||
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
|
||||
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
|
||||
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
|
||||
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
|
||||
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
|
||||
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
|
||||
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
|
||||
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
|
||||
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
|
||||
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
|
||||
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
|
||||
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
|
||||
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
|
||||
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
|
||||
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
|
||||
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
|
||||
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
|
||||
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
|
||||
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
|
||||
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
|
||||
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
|
||||
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
|
||||
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
|
||||
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
|
||||
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
|
||||
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
|
||||
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
|
||||
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
|
||||
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
|
||||
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
|
||||
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
|
||||
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
|
||||
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
|
||||
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
|
||||
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
|
||||
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
|
||||
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
|
||||
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
|
||||
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
|
||||
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
|
||||
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
|
||||
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
|
||||
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
|
||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
|
||||
};
|
||||
|
||||
const int16 C4::CosTable[512] = {
|
||||
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
|
||||
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
|
||||
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
|
||||
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
|
||||
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
|
||||
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
|
||||
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
|
||||
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
|
||||
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
|
||||
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
|
||||
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
|
||||
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
|
||||
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
|
||||
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
|
||||
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
|
||||
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
|
||||
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
|
||||
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
|
||||
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
|
||||
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
|
||||
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
|
||||
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
|
||||
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
|
||||
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
|
||||
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
|
||||
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
|
||||
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
|
||||
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
|
||||
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
|
||||
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
|
||||
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
|
||||
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
|
||||
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
|
||||
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
|
||||
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
|
||||
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
|
||||
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
|
||||
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
|
||||
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
|
||||
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
|
||||
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
|
||||
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
|
||||
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
|
||||
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
|
||||
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
|
||||
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
|
||||
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
|
||||
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402,
|
||||
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
|
||||
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
|
||||
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
|
||||
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
|
||||
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
|
||||
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
|
||||
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
|
||||
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
|
||||
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
|
||||
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
|
||||
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
|
||||
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
|
||||
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
|
||||
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
|
||||
};
|
||||
@@ -0,0 +1,242 @@
|
||||
#include <math.h>
|
||||
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
|
||||
#define sar(b, n) ((b) >> (n))
|
||||
#ifdef PI
|
||||
#undef PI
|
||||
#endif
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
//Wireframe Helpers
|
||||
void C4::C4TransfWireFrame() {
|
||||
c4x = (double)C4WFXVal;
|
||||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal - 0x95;
|
||||
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
|
||||
}
|
||||
|
||||
void C4::C4CalcWireFrame() {
|
||||
C4WFXVal = C4WFX2Val - C4WFXVal;
|
||||
C4WFYVal = C4WFY2Val - C4WFYVal;
|
||||
|
||||
if(abs(C4WFXVal) > abs(C4WFYVal)) {
|
||||
C4WFDist = abs(C4WFXVal) + 1;
|
||||
C4WFYVal = (256 * (long)C4WFYVal) / abs(C4WFXVal);
|
||||
C4WFXVal = (C4WFXVal < 0) ? -256 : 256;
|
||||
} else if(C4WFYVal != 0) {
|
||||
C4WFDist = abs(C4WFYVal) + 1;
|
||||
C4WFXVal = (256 * (long)C4WFXVal) / abs(C4WFYVal);
|
||||
C4WFYVal = (C4WFYVal < 0) ? -256 : 256;
|
||||
} else {
|
||||
C4WFDist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void C4::C4TransfWireFrame2() {
|
||||
c4x = (double)C4WFXVal;
|
||||
c4y = (double)C4WFYVal;
|
||||
c4z = (double)C4WFZVal;
|
||||
|
||||
//Rotate X
|
||||
tanval = -(double)C4WFX2Val * PI * 2 / 128;
|
||||
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
|
||||
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
|
||||
|
||||
//Rotate Y
|
||||
tanval = -(double)C4WFY2Val * PI * 2 / 128;
|
||||
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
|
||||
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
|
||||
|
||||
//Rotate Z
|
||||
tanval = -(double)C4WFDist * PI * 2 / 128;
|
||||
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
|
||||
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
|
||||
|
||||
//Scale
|
||||
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
|
||||
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
|
||||
}
|
||||
|
||||
void C4::C4DrawWireFrame() {
|
||||
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(r_mem->read(line) == 0xff && r_mem->read(line + 1) == 0xff) {
|
||||
int32 tmp = line - 5;
|
||||
while(r_mem->read(tmp + 2) == 0xff && r_mem->read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
|
||||
point1 = (read(0x1f82) << 16) | (r_mem->read(tmp + 2) << 8) | r_mem->read(tmp + 3);
|
||||
} else {
|
||||
point1 = (read(0x1f82) << 16) | (r_mem->read(line) << 8) | r_mem->read(line + 1);
|
||||
}
|
||||
point2 = (read(0x1f82) << 16) | (r_mem->read(line + 2) << 8) | r_mem->read(line + 3);
|
||||
|
||||
X1=(r_mem->read(point1 + 0) << 8) | r_mem->read(point1 + 1);
|
||||
Y1=(r_mem->read(point1 + 2) << 8) | r_mem->read(point1 + 3);
|
||||
Z1=(r_mem->read(point1 + 4) << 8) | r_mem->read(point1 + 5);
|
||||
X2=(r_mem->read(point2 + 0) << 8) | r_mem->read(point2 + 1);
|
||||
Y2=(r_mem->read(point2 + 2) << 8) | r_mem->read(point2 + 3);
|
||||
Z2=(r_mem->read(point2 + 4) << 8) | r_mem->read(point2 + 5);
|
||||
Color = r_mem->read(line + 4);
|
||||
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
|
||||
}
|
||||
}
|
||||
|
||||
void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
|
||||
//Transform coordinates
|
||||
C4WFXVal = (int16)X1;
|
||||
C4WFYVal = (int16)Y1;
|
||||
C4WFZVal = Z1;
|
||||
C4WFScale = read(0x1f90);
|
||||
C4WFX2Val = read(0x1f86);
|
||||
C4WFY2Val = read(0x1f87);
|
||||
C4WFDist = read(0x1f88);
|
||||
C4TransfWireFrame2();
|
||||
X1 = (C4WFXVal + 48) << 8;
|
||||
Y1 = (C4WFYVal + 48) << 8;
|
||||
|
||||
C4WFXVal = (int16)X2;
|
||||
C4WFYVal = (int16)Y2;
|
||||
C4WFZVal = Z2;
|
||||
C4TransfWireFrame2();
|
||||
X2 = (C4WFXVal + 48) << 8;
|
||||
Y2 = (C4WFYVal + 48) << 8;
|
||||
|
||||
//Get line info
|
||||
C4WFXVal = (int16)(X1 >> 8);
|
||||
C4WFYVal = (int16)(Y1 >> 8);
|
||||
C4WFX2Val = (int16)(X2 >> 8);
|
||||
C4WFY2Val = (int16)(Y2 >> 8);
|
||||
C4CalcWireFrame();
|
||||
X2 = (int16)C4WFXVal;
|
||||
Y2 = (int16)C4WFYVal;
|
||||
|
||||
//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);
|
||||
ram[addr + 0x300] &= ~bit;
|
||||
ram[addr + 0x301] &= ~bit;
|
||||
if(Color & 1) { ram[addr + 0x300] |= bit; }
|
||||
if(Color & 2) { ram[addr + 0x301] |= bit; }
|
||||
}
|
||||
X1 += X2;
|
||||
Y1 += Y2;
|
||||
}
|
||||
}
|
||||
|
||||
void C4::C4DoScaleRotate(int row_padding) {
|
||||
int16 A, B, C, D;
|
||||
|
||||
//Calculate matrix
|
||||
int32 XScale = readw(0x1f8f);
|
||||
int32 YScale = readw(0x1f92);
|
||||
if(XScale & 0x8000)XScale = 0x7fff;
|
||||
if(YScale & 0x8000)YScale = 0x7fff;
|
||||
|
||||
if(readw(0x1f80) == 0) { //no rotation
|
||||
A = (int16)XScale;
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)YScale;
|
||||
} else if(readw(0x1f80) == 128) { //90 degree rotation
|
||||
A = 0;
|
||||
B = (int16)(-YScale);
|
||||
C = (int16)XScale;
|
||||
D = 0;
|
||||
} else if(readw(0x1f80) == 256) { //180 degree rotation
|
||||
A = (int16)(-XScale);
|
||||
B = 0;
|
||||
C = 0;
|
||||
D = (int16)(-YScale);
|
||||
} else if(readw(0x1f80) == 384) { //270 degree rotation
|
||||
A = 0;
|
||||
B = (int16)YScale;
|
||||
C = (int16)(-XScale);
|
||||
D = 0;
|
||||
} else {
|
||||
A = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * XScale, 15);
|
||||
B = (int16)(-sar(SinTable[readw(0x1f80) & 0x1ff] * YScale, 15));
|
||||
C = (int16) sar(SinTable[readw(0x1f80) & 0x1ff] * XScale, 15);
|
||||
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
|
||||
}
|
||||
|
||||
//Calculate Pixel Resolution
|
||||
uint8 w = read(0x1f89) & ~7;
|
||||
uint8 h = read(0x1f8c) & ~7;
|
||||
|
||||
//Clear the output RAM
|
||||
memset(ram, 0, (w + row_padding / 4) * h / 2);
|
||||
|
||||
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;
|
||||
|
||||
//Start loop
|
||||
uint32 X, Y;
|
||||
uint8 byte;
|
||||
int32 outidx = 0;
|
||||
uint8 bit = 0x80;
|
||||
for(int32 y = 0; y < h; y++) {
|
||||
X = LineX;
|
||||
Y = LineY;
|
||||
for(int32 x = 0; x < w; x++) {
|
||||
if((X >> 12) >= w || (Y >> 12) >= h) {
|
||||
byte = 0;
|
||||
} else {
|
||||
uint32 addr = (Y >> 12) * w + (X >> 12);
|
||||
byte = read(0x600 + (addr >> 1));
|
||||
if(addr & 1) { byte >>= 4; }
|
||||
}
|
||||
|
||||
//De-bitplanify
|
||||
if(byte & 1) { ram[outidx ] |= bit; }
|
||||
if(byte & 2) { ram[outidx + 1] |= bit; }
|
||||
if(byte & 4) { ram[outidx + 16] |= bit; }
|
||||
if(byte & 8) { ram[outidx + 17] |= bit; }
|
||||
|
||||
bit >>= 1;
|
||||
if(!bit) {
|
||||
bit = 0x80;
|
||||
outidx += 32;
|
||||
}
|
||||
|
||||
X += A; //Add 1 to output x => add an A and a C
|
||||
Y += C;
|
||||
}
|
||||
outidx += 2 + row_padding;
|
||||
if(outidx & 0x10) {
|
||||
outidx &= ~0x10;
|
||||
} else {
|
||||
outidx -= w * 4 + row_padding;
|
||||
}
|
||||
LineX += B; //Add 1 to output y => add a B and a D
|
||||
LineY += D;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
//Build OAM
|
||||
void C4::op00_00() {
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
for(int32 i=0x1fd;i>oamptr && i>=0;i-=4) {
|
||||
//clear oam-to-be
|
||||
if(i >= 0)ram[i] = 0xe0;
|
||||
}
|
||||
|
||||
uint16 globalx, globaly;
|
||||
uint32 oamptr2;
|
||||
int16 sprx, spry;
|
||||
uint8 sprname, sprattr;
|
||||
uint8 sprcount;
|
||||
globalx = readw(0x621);
|
||||
globaly = readw(0x623);
|
||||
oamptr2 = 0x200 + (ram[0x626] >> 2);
|
||||
|
||||
if(!ram[0x620])return;
|
||||
|
||||
sprcount = 128 - ram[0x626];
|
||||
uint8 offset = (ram[0x626] & 3) * 2;
|
||||
for(int pri=0x30;pri>=0;pri-=0x10) {
|
||||
uint32 srcptr = 0x220;
|
||||
for(int i=ram[0x620];i>0 && sprcount>0;i--, srcptr+=16) {
|
||||
if((ram[srcptr + 4] & 0x30) != pri)continue;
|
||||
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);
|
||||
if(r_mem->read(spraddr)) {
|
||||
int16 x, y;
|
||||
for(int sprcnt=r_mem->read(spraddr++);sprcnt>0 && sprcount>0;sprcnt--, spraddr+=4) {
|
||||
x = (int8)r_mem->read(spraddr + 1);
|
||||
if(sprattr & 0x40) {
|
||||
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
|
||||
}
|
||||
x += sprx;
|
||||
if(x >= -16 && x <= 272) {
|
||||
y = (int8)r_mem->read(spraddr + 2);
|
||||
if(sprattr & 0x80) {
|
||||
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
|
||||
}
|
||||
y += spry;
|
||||
if(y >= -16 && y <= 224) {
|
||||
ram[oamptr ] = (uint8)x;
|
||||
ram[oamptr + 1] = (uint8)y;
|
||||
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
|
||||
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(x & 0x100)ram[oamptr2] |= 1 << offset;
|
||||
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset)oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(sprcount > 0) {
|
||||
ram[oamptr ] = (uint8)sprx;
|
||||
ram[oamptr + 1] = (uint8)spry;
|
||||
ram[oamptr + 2] = sprname;
|
||||
ram[oamptr + 3] = sprattr;
|
||||
ram[oamptr2] &= ~(3 << offset);
|
||||
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
|
||||
else ram[oamptr2] |= 2 << offset;
|
||||
oamptr += 4;
|
||||
sprcount--;
|
||||
offset = (offset + 2) & 6;
|
||||
if(!offset)oamptr2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Scale and Rotate
|
||||
void C4::op00_03() {
|
||||
C4DoScaleRotate(0);
|
||||
}
|
||||
|
||||
//Transform Lines
|
||||
void C4::op00_05() {
|
||||
C4WFX2Val = read(0x1f83);
|
||||
C4WFY2Val = read(0x1f86);
|
||||
C4WFDist = read(0x1f89);
|
||||
C4WFScale = read(0x1f8c);
|
||||
|
||||
//Transform Vertices
|
||||
uint32 ptr = 0;
|
||||
for(int32 i = readw(0x1f80); i > 0; i--, ptr += 0x10) {
|
||||
C4WFXVal = readw(ptr + 1);
|
||||
C4WFYVal = readw(ptr + 5);
|
||||
C4WFZVal = readw(ptr + 9);
|
||||
C4TransfWireFrame();
|
||||
|
||||
//Displace
|
||||
writew(ptr + 1, C4WFXVal + 0x80);
|
||||
writew(ptr + 5, C4WFYVal + 0x50);
|
||||
}
|
||||
|
||||
writew(0x600, 23);
|
||||
writew(0x602, 0x60);
|
||||
writew(0x605, 0x40);
|
||||
writew(0x600 + 8, 23);
|
||||
writew(0x602 + 8, 0x60);
|
||||
writew(0x605 + 8, 0x40);
|
||||
|
||||
ptr = 0xb02;
|
||||
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);
|
||||
C4WFX2Val = readw((read(ptr + 1) << 4) + 1);
|
||||
C4WFY2Val = readw((read(ptr + 1) << 4) + 5);
|
||||
C4CalcWireFrame();
|
||||
writew(ptr2 + 0x600, C4WFDist ? C4WFDist : 1);
|
||||
writew(ptr2 + 0x602, C4WFXVal);
|
||||
writew(ptr2 + 0x605, C4WFYVal);
|
||||
}
|
||||
}
|
||||
|
||||
//Scale and Rotate
|
||||
void C4::op00_07() {
|
||||
C4DoScaleRotate(64);
|
||||
}
|
||||
|
||||
//Draw Wireframe
|
||||
void C4::op00_08() {
|
||||
C4DrawWireFrame();
|
||||
}
|
||||
|
||||
//Disintegrate
|
||||
void C4::op00_0b() {
|
||||
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);
|
||||
cy = readw(0x1f83);
|
||||
|
||||
scalex = (int16)readw(0x1f86);
|
||||
scaley = (int16)readw(0x1f8f);
|
||||
startx = -cx * scalex + (cx << 8);
|
||||
starty = -cy * scaley + (cy << 8);
|
||||
srcptr = 0x600;
|
||||
|
||||
for(i = 0; i < (width * height) >> 1; i++) {
|
||||
write(i, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
if(pixel & 1)ram[index ] |= mask;
|
||||
if(pixel & 2)ram[index + 1] |= mask;
|
||||
if(pixel & 4)ram[index + 16] |= mask;
|
||||
if(pixel & 8)ram[index + 17] |= mask;
|
||||
}
|
||||
if(j & 1)srcptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bitplane Wave
|
||||
void C4::op00_0c() {
|
||||
uint32 destptr = 0;
|
||||
uint32 waveptr = read(0x1f83);
|
||||
uint16 mask1 = 0xc0c0;
|
||||
uint16 mask2 = 0x3f3f;
|
||||
|
||||
int32 i, j;
|
||||
int16 height, temp;
|
||||
for(j = 0; j < 0x10; j++) {
|
||||
do {
|
||||
height = -((int8)ram[waveptr + 0xb00]) - 16;
|
||||
for(i = 0; i < 40; i++) {
|
||||
temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa00 + height * 2);
|
||||
} else {
|
||||
temp |= mask1 & 0xff00;
|
||||
}
|
||||
}
|
||||
writew(destptr + wave_data[i], temp);
|
||||
height++;
|
||||
}
|
||||
waveptr = (waveptr + 1) & 0x7f;
|
||||
mask1 = (mask1 >> 2) | (mask1 << 6);
|
||||
mask2 = (mask2 >> 2) | (mask2 << 6);
|
||||
} while(mask1 != 0xc0c0);
|
||||
destptr += 16;
|
||||
|
||||
do {
|
||||
height = -((int8)ram[waveptr + 0xb00]) - 16;
|
||||
for(i = 0; i < 40; i++) {
|
||||
temp = readw(destptr + wave_data[i]) & mask2;
|
||||
if(height >= 0) {
|
||||
if(height < 8) {
|
||||
temp |= mask1 & readw(0xa10 + height * 2);
|
||||
} else {
|
||||
temp |= mask1 & 0xff00;
|
||||
}
|
||||
writew(destptr + wave_data[i], temp);
|
||||
height++;
|
||||
}
|
||||
waveptr = (waveptr + 1) & 0x7f;
|
||||
mask1 = (mask1 >> 2) | (mask1 << 6);
|
||||
mask2 = (mask2 >> 2) | (mask2 << 6);
|
||||
}
|
||||
} while(mask1 != 0xc0c0);
|
||||
destptr += 16;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
//Sprite Functions
|
||||
void C4::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;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw Wireframe
|
||||
void C4::op01() {
|
||||
memset(ram + 0x300, 0, 2304);
|
||||
C4DrawWireFrame();
|
||||
}
|
||||
|
||||
//Propulsion
|
||||
void C4::op05() {
|
||||
int32 temp = 0x10000;
|
||||
if(readw(0x1f83)) {
|
||||
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
|
||||
}
|
||||
writew(0x1f80, temp);
|
||||
}
|
||||
|
||||
//Set Vector length
|
||||
void C4::op0d() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDistVal = readw(0x1f86);
|
||||
tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
|
||||
tanval = (double)C41FDistVal / tanval;
|
||||
C41FYVal = (int16)(((double)C41FYVal * tanval) * 0.99);
|
||||
C41FXVal = (int16)(((double)C41FXVal * tanval) * 0.98);
|
||||
writew(0x1f89, C41FXVal);
|
||||
writew(0x1f8c, C41FYVal);
|
||||
}
|
||||
|
||||
//Triangle
|
||||
void C4::op10() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
|
||||
r4 = r0 & 0x1ff;
|
||||
if(r1 & 0x8000)r1 |= ~0x7fff;
|
||||
|
||||
mul(cos(r4), r1, r5, r2);
|
||||
r5 = (r5 >> 16) & 0xff;
|
||||
r2 = (r2 << 8) + r5;
|
||||
|
||||
mul(sin(r4), r1, r5, r3);
|
||||
r5 = (r5 >> 16) & 0xff;
|
||||
r3 = (r3 << 8) + r5;
|
||||
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
str(3, r3);
|
||||
str(4, r4);
|
||||
str(5, r5);
|
||||
}
|
||||
|
||||
//Triangle
|
||||
void C4::op13() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
|
||||
r4 = r0 & 0x1ff;
|
||||
|
||||
mul(cos(r4), r1, r5, r2);
|
||||
r5 = (r5 >> 8) & 0xffff;
|
||||
r2 = (r2 << 16) + r5;
|
||||
|
||||
mul(sin(r4), r1, r5, r3);
|
||||
r5 = (r5 >> 8) & 0xffff;
|
||||
r3 = (r3 << 16) + r5;
|
||||
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
str(3, r3);
|
||||
str(4, r4);
|
||||
str(5, r5);
|
||||
}
|
||||
|
||||
//Pythagorean
|
||||
void C4::op15() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
|
||||
writew(0x1f80, C41FDist);
|
||||
}
|
||||
|
||||
//Calculate distance
|
||||
void C4::op1f() {
|
||||
C41FXVal = readw(0x1f80);
|
||||
C41FYVal = readw(0x1f83);
|
||||
if(!C41FXVal) {
|
||||
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
|
||||
} else {
|
||||
tanval = ((double)C41FYVal) / ((double)C41FXVal);
|
||||
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
|
||||
C41FAngleRes = C41FAngleRes;
|
||||
if(C41FXVal < 0) {
|
||||
C41FAngleRes += 0x100;
|
||||
}
|
||||
C41FAngleRes &= 0x1ff;
|
||||
}
|
||||
writew(0x1f86, C41FAngleRes);
|
||||
}
|
||||
|
||||
//Trapezoid
|
||||
void C4::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;
|
||||
for(int32 j = 0; j < 225; j++, y++) {
|
||||
if(y >= 0) {
|
||||
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
|
||||
right = sar((int32)tan2 * y, 16) - readw(0x1f80) + readw(0x1f86) + readw(0x1f93);
|
||||
|
||||
if(left < 0 && right < 0) {
|
||||
left = 1;
|
||||
right = 0;
|
||||
} else if(left < 0) {
|
||||
left = 0;
|
||||
} else if(right < 0) {
|
||||
right = 0;
|
||||
}
|
||||
|
||||
if(left > 255 && right > 255) {
|
||||
left = 255;
|
||||
right = 254;
|
||||
} else if(left > 255) {
|
||||
left = 255;
|
||||
} else if(right > 255) {
|
||||
right = 255;
|
||||
}
|
||||
} else {
|
||||
left = 1;
|
||||
right = 0;
|
||||
}
|
||||
ram[j + 0x800] = (uint8)left;
|
||||
ram[j + 0x900] = (uint8)right;
|
||||
}
|
||||
}
|
||||
|
||||
//Multiply
|
||||
void C4::op25() {
|
||||
r0 = ldr(0);
|
||||
r1 = ldr(1);
|
||||
mul(r0, r1, r0, r1);
|
||||
str(0, r0);
|
||||
str(1, r1);
|
||||
}
|
||||
|
||||
//Transform Coords
|
||||
void C4::op2d() {
|
||||
C4WFXVal = readw(0x1f81);
|
||||
C4WFYVal = readw(0x1f84);
|
||||
C4WFZVal = readw(0x1f87);
|
||||
C4WFX2Val = read (0x1f89);
|
||||
C4WFY2Val = read (0x1f8a);
|
||||
C4WFDist = read (0x1f8b);
|
||||
C4WFScale = readw(0x1f90);
|
||||
C4TransfWireFrame2();
|
||||
writew(0x1f80, C4WFXVal);
|
||||
writew(0x1f83, C4WFYVal);
|
||||
}
|
||||
|
||||
//Sum
|
||||
void C4::op40() {
|
||||
r0 = 0;
|
||||
for(uint32 i=0;i<0x800;i++) {
|
||||
r0 += ram[i];
|
||||
}
|
||||
str(0, r0);
|
||||
}
|
||||
|
||||
//Square
|
||||
void C4::op54() {
|
||||
r0 = ldr(0);
|
||||
mul(r0, r0, r1, r2);
|
||||
str(1, r1);
|
||||
str(2, r2);
|
||||
}
|
||||
|
||||
//Immediate Register
|
||||
void C4::op5c() {
|
||||
str(0, 0x000000);
|
||||
immediate_reg(0);
|
||||
}
|
||||
|
||||
//Immediate Register (Multiple)
|
||||
void C4::op5e() { immediate_reg( 0); }
|
||||
void C4::op60() { immediate_reg( 3); }
|
||||
void C4::op62() { immediate_reg( 6); }
|
||||
void C4::op64() { immediate_reg( 9); }
|
||||
void C4::op66() { immediate_reg(12); }
|
||||
void C4::op68() { immediate_reg(15); }
|
||||
void C4::op6a() { immediate_reg(18); }
|
||||
void C4::op6c() { immediate_reg(21); }
|
||||
void C4::op6e() { immediate_reg(24); }
|
||||
void C4::op70() { immediate_reg(27); }
|
||||
void C4::op72() { immediate_reg(30); }
|
||||
void C4::op74() { immediate_reg(33); }
|
||||
void C4::op76() { immediate_reg(36); }
|
||||
void C4::op78() { immediate_reg(39); }
|
||||
void C4::op7a() { immediate_reg(42); }
|
||||
void C4::op7c() { immediate_reg(45); }
|
||||
|
||||
//Immediate ROM
|
||||
void C4::op89() {
|
||||
str(0, 0x054336);
|
||||
str(1, 0xffffff);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "../../base.h"
|
||||
#include "dsp2_op.cpp"
|
||||
|
||||
void DSP2::init() {}
|
||||
void DSP2::enable() {}
|
||||
|
||||
void DSP2::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void DSP2::reset() {
|
||||
status.waiting_for_command = true;
|
||||
status.in_count = 0;
|
||||
status.in_index = 0;
|
||||
status.out_count = 0;
|
||||
status.out_index = 0;
|
||||
|
||||
status.op05transparent = 0;
|
||||
status.op05haslen = false;
|
||||
status.op05len = 0;
|
||||
status.op06haslen = false;
|
||||
status.op06len = 0;
|
||||
status.op09word1 = 0;
|
||||
status.op09word2 = 0;
|
||||
status.op0dhaslen = false;
|
||||
status.op0doutlen = 0;
|
||||
status.op0dinlen = 0;
|
||||
}
|
||||
|
||||
uint8 DSP2::read(uint16 addr) {
|
||||
uint8 r = 0xff;
|
||||
if(status.out_count) {
|
||||
r = status.output[status.out_index++];
|
||||
status.out_index &= 511;
|
||||
if(status.out_count == status.out_index) {
|
||||
status.out_count = 0;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void DSP2::write(uint16 addr, uint8 data) {
|
||||
if(status.waiting_for_command) {
|
||||
status.command = data;
|
||||
status.in_index = 0;
|
||||
status.waiting_for_command = false;
|
||||
|
||||
switch(data) {
|
||||
case 0x01: status.in_count = 32; break;
|
||||
case 0x03: status.in_count = 1; break;
|
||||
case 0x05: status.in_count = 1; break;
|
||||
case 0x06: status.in_count = 1; break;
|
||||
case 0x07: break;
|
||||
case 0x08: break;
|
||||
case 0x09: status.in_count = 4; break;
|
||||
case 0x0d: status.in_count = 2; break;
|
||||
case 0x0f: status.in_count = 0; break;
|
||||
}
|
||||
} else {
|
||||
status.parameters[status.in_index++] = data;
|
||||
status.in_index &= 511;
|
||||
}
|
||||
|
||||
if(status.in_count == status.in_index) {
|
||||
status.waiting_for_command = true;
|
||||
status.out_index = 0;
|
||||
switch(status.command) {
|
||||
case 0x01: {
|
||||
status.out_count = 32;
|
||||
op01();
|
||||
} break;
|
||||
|
||||
case 0x03: {
|
||||
op03();
|
||||
} break;
|
||||
|
||||
case 0x05: {
|
||||
if(status.op05haslen) {
|
||||
status.op05haslen = false;
|
||||
status.out_count = status.op05len;
|
||||
op05();
|
||||
} else {
|
||||
status.op05len = status.parameters[0];
|
||||
status.in_index = 0;
|
||||
status.in_count = status.op05len * 2;
|
||||
status.op05haslen = true;
|
||||
if(data)status.waiting_for_command = false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x06: {
|
||||
if(status.op06haslen) {
|
||||
status.op06haslen = false;
|
||||
status.out_count = status.op06len;
|
||||
op06();
|
||||
} else {
|
||||
status.op06len = status.parameters[0];
|
||||
status.in_index = 0;
|
||||
status.in_count = status.op06len;
|
||||
status.op06haslen = true;
|
||||
if(data)status.waiting_for_command = false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x07: break;
|
||||
case 0x08: break;
|
||||
|
||||
case 0x09: {
|
||||
op09();
|
||||
} break;
|
||||
|
||||
case 0x0d: {
|
||||
if(status.op0dhaslen) {
|
||||
status.op0dhaslen = false;
|
||||
status.out_count = status.op0doutlen;
|
||||
op0d();
|
||||
} else {
|
||||
status.op0dinlen = status.parameters[0];
|
||||
status.op0doutlen = status.parameters[1];
|
||||
status.in_index = 0;
|
||||
status.in_count = (status.op0dinlen + 1) >> 1;
|
||||
status.op0dhaslen = true;
|
||||
if(data)status.waiting_for_command = false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x0f: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DSP2::DSP2() {}
|
||||
DSP2::~DSP2() {}
|
||||
@@ -0,0 +1,40 @@
|
||||
class DSP2 {
|
||||
public:
|
||||
struct {
|
||||
bool waiting_for_command;
|
||||
uint command;
|
||||
uint in_count, in_index;
|
||||
uint out_count, out_index;
|
||||
|
||||
uint8 parameters[512];
|
||||
uint8 output[512];
|
||||
|
||||
uint8 op05transparent;
|
||||
bool op05haslen;
|
||||
int op05len;
|
||||
bool op06haslen;
|
||||
int op06len;
|
||||
uint16 op09word1;
|
||||
uint16 op09word2;
|
||||
bool op0dhaslen;
|
||||
int op0doutlen;
|
||||
int op0dinlen;
|
||||
} status;
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void op01();
|
||||
void op03();
|
||||
void op05();
|
||||
void op06();
|
||||
void op09();
|
||||
void op0d();
|
||||
|
||||
uint8 read (uint16 addr);
|
||||
void write(uint16 addr, uint8 data);
|
||||
|
||||
DSP2();
|
||||
~DSP2();
|
||||
};
|
||||
@@ -0,0 +1,173 @@
|
||||
//convert bitmap to bitplane tile
|
||||
void DSP2::op01() {
|
||||
//op01 size is always 32 bytes input and output
|
||||
//the hardware does strange things if you vary the size
|
||||
|
||||
unsigned char c0, c1, c2, c3;
|
||||
unsigned char *p1 = status.parameters;
|
||||
unsigned char *p2a = status.output;
|
||||
unsigned char *p2b = status.output + 16; //halfway
|
||||
|
||||
//process 8 blocks of 4 bytes each
|
||||
for(int j = 0; j < 8; j++) {
|
||||
c0 = *p1++;
|
||||
c1 = *p1++;
|
||||
c2 = *p1++;
|
||||
c3 = *p1++;
|
||||
|
||||
*p2a++ = (c0 & 0x10) << 3 |
|
||||
(c0 & 0x01) << 6 |
|
||||
(c1 & 0x10) << 1 |
|
||||
(c1 & 0x01) << 4 |
|
||||
(c2 & 0x10) >> 1 |
|
||||
(c2 & 0x01) << 2 |
|
||||
(c3 & 0x10) >> 3 |
|
||||
(c3 & 0x01);
|
||||
|
||||
*p2a++ = (c0 & 0x20) << 2 |
|
||||
(c0 & 0x02) << 5 |
|
||||
(c1 & 0x20) |
|
||||
(c1 & 0x02) << 3 |
|
||||
(c2 & 0x20) >> 2 |
|
||||
(c2 & 0x02) << 1 |
|
||||
(c3 & 0x20) >> 4 |
|
||||
(c3 & 0x02) >> 1;
|
||||
|
||||
*p2b++ = (c0 & 0x40) << 1 |
|
||||
(c0 & 0x04) << 4 |
|
||||
(c1 & 0x40) >> 1 |
|
||||
(c1 & 0x04) << 2 |
|
||||
(c2 & 0x40) >> 3 |
|
||||
(c2 & 0x04) |
|
||||
(c3 & 0x40) >> 5 |
|
||||
(c3 & 0x04) >> 2;
|
||||
|
||||
*p2b++ = (c0 & 0x80) |
|
||||
(c0 & 0x08) << 3 |
|
||||
(c1 & 0x80) >> 2 |
|
||||
(c1 & 0x08) << 1 |
|
||||
(c2 & 0x80) >> 4 |
|
||||
(c2 & 0x08) >> 1 |
|
||||
(c3 & 0x80) >> 6 |
|
||||
(c3 & 0x08) >> 3;
|
||||
}
|
||||
}
|
||||
|
||||
//set transparent color
|
||||
void DSP2::op03() {
|
||||
status.op05transparent = status.parameters[0];
|
||||
}
|
||||
|
||||
//replace bitmap using transparent color
|
||||
void DSP2::op05() {
|
||||
uint8 color;
|
||||
// Overlay bitmap with transparency.
|
||||
// Input:
|
||||
//
|
||||
// Bitmap 1: i[0] <=> i[size-1]
|
||||
// Bitmap 2: i[size] <=> i[2*size-1]
|
||||
//
|
||||
// Output:
|
||||
//
|
||||
// Bitmap 3: o[0] <=> o[size-1]
|
||||
//
|
||||
// Processing:
|
||||
//
|
||||
// Process all 4-bit pixels (nibbles) in the bitmap
|
||||
//
|
||||
// if ( BM2_pixel == transparent_color )
|
||||
// pixelout = BM1_pixel
|
||||
// else
|
||||
// pixelout = BM2_pixel
|
||||
|
||||
// The max size bitmap is limited to 255 because the size parameter is a byte
|
||||
// I think size=0 is an error. The behavior of the chip on size=0 is to
|
||||
// return the last value written to DR if you read DR on Op05 with
|
||||
// size = 0. I don't think it's worth implementing this quirk unless it's
|
||||
// proven necessary.
|
||||
|
||||
unsigned char c1, c2;
|
||||
unsigned char *p1 = status.parameters;
|
||||
unsigned char *p2 = status.parameters + status.op05len;
|
||||
unsigned char *p3 = status.output;
|
||||
|
||||
color = status.op05transparent & 0x0f;
|
||||
|
||||
for(int n = 0; n < status.op05len; n++) {
|
||||
c1 = *p1++;
|
||||
c2 = *p2++;
|
||||
*p3++ = ( ((c2 >> 4) == color ) ? c1 & 0xf0 : c2 & 0xf0 ) |
|
||||
( ((c2 & 0x0f) == color ) ? c1 & 0x0f : c2 & 0x0f );
|
||||
}
|
||||
}
|
||||
|
||||
//reverse bitmap
|
||||
void DSP2::op06() {
|
||||
// Input:
|
||||
// size
|
||||
// bitmap
|
||||
|
||||
int i, j;
|
||||
for(i = 0, j = status.op06len - 1; i < status.op06len; i++, j--) {
|
||||
status.output[j] = (status.parameters[i] << 4) | (status.parameters[i] >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
//multiply
|
||||
void DSP2::op09() {
|
||||
status.out_count = 4;
|
||||
|
||||
status.op09word1 = status.parameters[0] | (status.parameters[1] << 8);
|
||||
status.op09word2 = status.parameters[2] | (status.parameters[3] << 8);
|
||||
|
||||
uint32 r;
|
||||
r = status.op09word1 * status.op09word2;
|
||||
status.output[0] = r;
|
||||
status.output[1] = r >> 8;
|
||||
status.output[2] = r >> 16;
|
||||
status.output[3] = r >> 24;
|
||||
}
|
||||
|
||||
//scale bitmap
|
||||
void DSP2::op0d() {
|
||||
// Bit accurate hardware algorithm - uses fixed point math
|
||||
// This should match the DSP2 Op0D output exactly
|
||||
// I wouldn't recommend using this unless you're doing hardware debug.
|
||||
// In some situations it has small visual artifacts that
|
||||
// are not readily apparent on a TV screen but show up clearly
|
||||
// on a monitor. Use Overload's scaling instead.
|
||||
// This is for hardware verification testing.
|
||||
//
|
||||
// One note: the HW can do odd byte scaling but since we divide
|
||||
// by two to get the count of bytes this won't work well for
|
||||
// odd byte scaling (in any of the current algorithm implementations).
|
||||
// So far I haven't seen Dungeon Master use it.
|
||||
// If it does we can adjust the parameters and code to work with it
|
||||
|
||||
uint32 multiplier; // Any size int >= 32-bits
|
||||
uint32 pixloc; // match size of multiplier
|
||||
int i, j;
|
||||
uint8 pixelarray[512];
|
||||
if(status.op0dinlen <= status.op0doutlen) {
|
||||
multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1
|
||||
} else {
|
||||
multiplier = (status.op0dinlen << 17) / ((status.op0doutlen << 1) + 1);
|
||||
}
|
||||
|
||||
pixloc = 0;
|
||||
for(i = 0; i < status.op0doutlen * 2; i++) {
|
||||
j = pixloc >> 16;
|
||||
|
||||
if(j & 1) {
|
||||
pixelarray[i] = (status.parameters[j >> 1] & 0x0f);
|
||||
} else {
|
||||
pixelarray[i] = (status.parameters[j >> 1] & 0xf0) >> 4;
|
||||
}
|
||||
|
||||
pixloc += multiplier;
|
||||
}
|
||||
|
||||
for(i = 0; i < status.op0doutlen; i++) {
|
||||
status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "../../base.h"
|
||||
|
||||
void OBC1::init() {}
|
||||
void OBC1::enable() {}
|
||||
|
||||
void OBC1::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void OBC1::reset() {
|
||||
memset(cartridge.sram, 0xff, 0x2000);
|
||||
status.baseptr = (cartridge.sram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
|
||||
status.address = (cartridge.sram[0x1ff6] & 0x7f);
|
||||
status.shift = (cartridge.sram[0x1ff6] & 3) << 1;
|
||||
}
|
||||
|
||||
uint8 OBC1::read(uint16 addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if((addr & 0x1ff8) != 0x1ff0) {
|
||||
return cartridge.sram[addr];
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 0];
|
||||
case 0x1ff1:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 1];
|
||||
case 0x1ff2:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 2];
|
||||
case 0x1ff3:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 3];
|
||||
case 0x1ff4:
|
||||
return cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
case 0x1ff5:
|
||||
case 0x1ff6:
|
||||
case 0x1ff7:
|
||||
return cartridge.sram[addr];
|
||||
}
|
||||
|
||||
//never used, blocks compiler warning
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void OBC1::write(uint16 addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if((addr & 0x1ff8) != 0x1ff0) {
|
||||
cartridge.sram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 0] = data;
|
||||
break;
|
||||
case 0x1ff1:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 1] = data;
|
||||
break;
|
||||
case 0x1ff2:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 2] = data;
|
||||
break;
|
||||
case 0x1ff3:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 3] = data;
|
||||
break;
|
||||
case 0x1ff4: {
|
||||
uint8 temp;
|
||||
temp = cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||
cartridge.sram[status.baseptr + (status.address >> 2) + 0x200] = temp;
|
||||
} break;
|
||||
case 0x1ff5:
|
||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||
cartridge.sram[addr] = data;
|
||||
break;
|
||||
case 0x1ff6:
|
||||
status.address = (data & 0x7f);
|
||||
status.shift = (data & 3) << 1;
|
||||
cartridge.sram[addr] = data;
|
||||
break;
|
||||
case 0x1ff7:
|
||||
cartridge.sram[addr] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OBC1::OBC1() {}
|
||||
OBC1::~OBC1() {}
|
||||
@@ -0,0 +1,18 @@
|
||||
class OBC1 {
|
||||
public:
|
||||
struct {
|
||||
uint16 address;
|
||||
uint16 baseptr;
|
||||
uint16 shift;
|
||||
} status;
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read (uint16 addr);
|
||||
void write(uint16 addr, uint8 data);
|
||||
|
||||
OBC1();
|
||||
~OBC1();
|
||||
};
|
||||
+5
-17
@@ -1,12 +1,11 @@
|
||||
#include "../../base.h"
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
void SDD1::init() {
|
||||
}
|
||||
void SDD1::init() {}
|
||||
|
||||
void SDD1::enable() {
|
||||
for(int i=0x4800;i<=0x4807;i++) {
|
||||
r_mem->set_mmio_mapper(i, mmio);
|
||||
for(int i = 0x4800; i <= 0x4807; i++) {
|
||||
r_mem->set_mmio_mapper(i, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,10 +50,9 @@ uint8 SDD1::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void SDD1::mmio_write(uint16 addr, uint8 data) {
|
||||
int i;
|
||||
switch(addr) {
|
||||
case 0x4801:
|
||||
for(i=0;i<8;i++) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
sdd1.active[i] = !!(data & (1 << i));
|
||||
}
|
||||
break;
|
||||
@@ -90,14 +88,4 @@ uint8 SDD1::dma_read() {
|
||||
return sdd1.buffer[sdd1.buffer_index++];
|
||||
}
|
||||
|
||||
SDD1::SDD1() {
|
||||
mmio = new SDD1MMIO();
|
||||
}
|
||||
|
||||
uint8 SDD1MMIO::read(uint32 addr) {
|
||||
return sdd1->mmio_read(addr);
|
||||
}
|
||||
|
||||
void SDD1MMIO::write(uint32 addr, uint8 value) {
|
||||
sdd1->mmio_write(addr, value);
|
||||
}
|
||||
SDD1::SDD1() {}
|
||||
+3
-10
@@ -1,15 +1,8 @@
|
||||
#include "sdd1emu.h"
|
||||
|
||||
class SDD1MMIO : public MMIO {
|
||||
public:
|
||||
inline uint8 read (uint32 addr);
|
||||
inline void write(uint32 addr, uint8 value);
|
||||
};
|
||||
|
||||
class SDD1 {
|
||||
class SDD1 : public MMIO {
|
||||
public:
|
||||
SDD1emu sdd1emu;
|
||||
SDD1MMIO *mmio;
|
||||
|
||||
struct {
|
||||
uint32 index[4]; //memory mapping registers
|
||||
@@ -19,7 +12,7 @@ struct {
|
||||
uint16 buffer_size;
|
||||
bool active[8]; //true when DMA channel should pass through S-DD1
|
||||
bool dma_active;
|
||||
}sdd1;
|
||||
} sdd1;
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
@@ -30,7 +23,7 @@ struct {
|
||||
bool dma_active();
|
||||
uint8 dma_read();
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
uint8 mmio_read (uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
SDD1();
|
||||
|
||||
+86
-83
@@ -74,12 +74,11 @@ tm *t;
|
||||
srtc.data[12] = t->tm_wday;
|
||||
}
|
||||
|
||||
void SRTC::init() {
|
||||
}
|
||||
void SRTC::init() {}
|
||||
|
||||
void SRTC::enable() {
|
||||
r_mem->set_mmio_mapper(0x2800, mmio);
|
||||
r_mem->set_mmio_mapper(0x2801, mmio);
|
||||
r_mem->set_mmio_mapper(0x2800, this);
|
||||
r_mem->set_mmio_mapper(0x2801, this);
|
||||
}
|
||||
|
||||
void SRTC::power() {
|
||||
@@ -89,7 +88,35 @@ void SRTC::power() {
|
||||
|
||||
void SRTC::reset() {
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.mode = SRTC_READ;
|
||||
}
|
||||
|
||||
uint8 SRTC::mmio_read(uint16 addr) {
|
||||
switch(addr) {
|
||||
|
||||
case 0x2800: {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
if(srtc.index < 0) {
|
||||
set_time();
|
||||
srtc.index++;
|
||||
return 0x0f; //send start message
|
||||
} else if(srtc.index > MAX_SRTC_INDEX) {
|
||||
srtc.index = -1;
|
||||
return 0x0f; //send finished message
|
||||
} else {
|
||||
return srtc.data[srtc.index++];
|
||||
}
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x2801: {
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return r_cpu->regs.mdr;
|
||||
}
|
||||
|
||||
//Please see notes above about the implementation of the S-RTC
|
||||
@@ -97,90 +124,66 @@ void SRTC::reset() {
|
||||
//as reads will refresh the data array with the current system
|
||||
//time. The write method is only here for the sake of faux
|
||||
//emulation of the real hardware.
|
||||
void SRTC::write(uint8 data) {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
void SRTC::mmio_write(uint16 addr, uint8 data) {
|
||||
switch(addr) {
|
||||
|
||||
if(data >= 0x0d) {
|
||||
switch(data) {
|
||||
case 0x0d:
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.index = -1;
|
||||
break;
|
||||
case 0x0e:
|
||||
srtc.mode = SRTC_COMMAND;
|
||||
break;
|
||||
case 0x0f:
|
||||
//unknown behaviour
|
||||
break;
|
||||
case 0x2800: {
|
||||
} break;
|
||||
|
||||
case 0x2801: {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
|
||||
if(data >= 0x0d) {
|
||||
switch(data) {
|
||||
case 0x0d:
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.index = -1;
|
||||
break;
|
||||
case 0x0e:
|
||||
srtc.mode = SRTC_COMMAND;
|
||||
break;
|
||||
case 0x0f:
|
||||
//unknown behaviour
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(srtc.mode == SRTC_WRITE) {
|
||||
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
|
||||
srtc.data[srtc.index++] = data;
|
||||
if(srtc.mode == SRTC_WRITE) {
|
||||
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
|
||||
srtc.data[srtc.index++] = data;
|
||||
|
||||
if(srtc.index == MAX_SRTC_INDEX) {
|
||||
//all S-RTC data has been loaded by program
|
||||
srtc.data[srtc.index++] = 0x00; //day_of_week
|
||||
if(srtc.index == MAX_SRTC_INDEX) {
|
||||
//all S-RTC data has been loaded by program
|
||||
srtc.data[srtc.index++] = 0x00; //day_of_week
|
||||
}
|
||||
}
|
||||
} else if(srtc.mode == SRTC_COMMAND) {
|
||||
switch(data) {
|
||||
case SRTC_COMMAND_CLEAR:
|
||||
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
case SRTC_COMMAND_WRITE:
|
||||
srtc.index = 0;
|
||||
srtc.mode = SRTC_WRITE;
|
||||
break;
|
||||
default:
|
||||
//unknown behaviour
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
//ignore writes while in read mode
|
||||
} else if(srtc.mode == SRTC_READY) {
|
||||
//unknown behaviour
|
||||
}
|
||||
}
|
||||
} else if(srtc.mode == SRTC_COMMAND) {
|
||||
switch(data) {
|
||||
case SRTC_COMMAND_CLEAR:
|
||||
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
case SRTC_COMMAND_WRITE:
|
||||
srtc.index = 0;
|
||||
srtc.mode = SRTC_WRITE;
|
||||
break;
|
||||
default:
|
||||
//unknown behaviour
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
//ignore writes while in read mode
|
||||
} else if(srtc.mode == SRTC_READY) {
|
||||
//unknown behaviour
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SRTC::read() {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
if(srtc.index < 0) {
|
||||
set_time();
|
||||
srtc.index++;
|
||||
return 0x0f; //send start message
|
||||
} else if(srtc.index > MAX_SRTC_INDEX) {
|
||||
srtc.index = -1;
|
||||
return 0x0f; //send finished message
|
||||
} else {
|
||||
return srtc.data[srtc.index++];
|
||||
}
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
SRTC::SRTC() {
|
||||
mmio = new SRTCMMIO();
|
||||
}
|
||||
|
||||
uint8 SRTCMMIO::read(uint32 addr) {
|
||||
switch(addr) {
|
||||
case 0x2800:return srtc->read();
|
||||
}
|
||||
|
||||
return r_cpu->regs.mdr;
|
||||
}
|
||||
|
||||
void SRTCMMIO::write(uint32 addr, uint8 value) {
|
||||
switch(addr) {
|
||||
case 0x2801:srtc->write(value);break;
|
||||
}
|
||||
}
|
||||
SRTC::SRTC() {}
|
||||
+4
-11
@@ -1,10 +1,4 @@
|
||||
class SRTCMMIO : public MMIO {
|
||||
public:
|
||||
inline uint8 read (uint32 addr);
|
||||
inline void write(uint32 addr, uint8 value);
|
||||
};
|
||||
|
||||
class SRTC {
|
||||
class SRTC : public MMIO {
|
||||
public:
|
||||
enum { MAX_SRTC_INDEX = 0x0c };
|
||||
|
||||
@@ -20,8 +14,6 @@ enum {
|
||||
SRTC_COMMAND_CLEAR = 4
|
||||
};
|
||||
|
||||
SRTCMMIO *mmio;
|
||||
|
||||
/******************************
|
||||
[srtc.data structure]
|
||||
Index Description Range
|
||||
@@ -50,8 +42,9 @@ struct {
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
void write(uint8 data);
|
||||
uint8 read();
|
||||
|
||||
uint8 mmio_read (uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
SRTC();
|
||||
};
|
||||
+68
-16
@@ -2,27 +2,79 @@ Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
SNES::VideoColorAdjust SNES::video_color_curve(&config_file, "snes.video_color_curve",
|
||||
"Applies contrast adjust filter to video output when enabled\n"
|
||||
"Works by lowering the brightness of darker colors,\n"
|
||||
"while leaving brighter colors alone; thus reducing saturation",
|
||||
true, Setting::TRUE_FALSE);
|
||||
FS::Path FS::base_path(0, "fs.base_path", "Directory that bsnes resides in", "");
|
||||
|
||||
SNES::VideoColorAdjust SNES::video_color_adjust_mode(&config_file, "snes.video_color_adjust_mode",
|
||||
"Selects color adjustment filter for video output\n"
|
||||
" 0 = Normal (no filter, rgb555)\n"
|
||||
" 1 = Grayscale mode (l5)\n"
|
||||
" 2 = VGA mode (rgb332)\n"
|
||||
" 3 = Genesis mode (rgb333)",
|
||||
0, Setting::DEC);
|
||||
FS::Path FS::rom_path(&config_file, "fs.rom_path",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
FS::Path FS::save_path(&config_file, "fs.save_path",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
|
||||
void FS::Path::sset(const char *_data) {
|
||||
string path;
|
||||
strcpy(path, _data);
|
||||
strunquote(path);
|
||||
replace(path, "\\", "/");
|
||||
|
||||
//blank path?
|
||||
if(strlen(path) == 0) {
|
||||
Setting::sset(strptr(path));
|
||||
return;
|
||||
}
|
||||
|
||||
//missing final directory marker?
|
||||
if(strptr(path)[strlen(path) - 1] != '/') {
|
||||
strcat(path, "/");
|
||||
}
|
||||
|
||||
Setting::sset(strptr(path));
|
||||
}
|
||||
|
||||
Setting FS::save_ext(&config_file, "fs.save_ext",
|
||||
"Extension to be used for all save RAM files", "srm");
|
||||
|
||||
SNES::VideoColorAdjust SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
|
||||
"Use precalculated TV-style gamma ramp", true, Setting::TRUE_FALSE);
|
||||
SNES::VideoColorAdjust SNES::sepia(&config_file, "snes.colorfilter.sepia",
|
||||
"Convert color to sepia tone", false, Setting::TRUE_FALSE);
|
||||
SNES::VideoColorAdjust SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
|
||||
"Convert color to grayscale tone", false, Setting::TRUE_FALSE);
|
||||
SNES::VideoColorAdjust SNES::invert(&config_file, "snes.colorfilter.invert",
|
||||
"Invert output image colors", false, Setting::TRUE_FALSE);
|
||||
SNES::VideoColorAdjust SNES::contrast(&config_file, "snes.colorfilter.contrast",
|
||||
"", 0, Setting::DEC);
|
||||
SNES::VideoColorAdjust SNES::brightness(&config_file, "snes.colorfilter.brightness",
|
||||
"", 0, Setting::DEC);
|
||||
SNES::VideoColorAdjust SNES::gamma(&config_file, "snes.colorfilter.gamma",
|
||||
"", 100, Setting::DEC);
|
||||
|
||||
void SNES::VideoColorAdjust::set(uint32 _data) {
|
||||
data = _data;
|
||||
Setting::set(_data);
|
||||
::snes->update_color_lookup_table();
|
||||
}
|
||||
|
||||
Setting SNES::mute(&config_file, "snes.mute",
|
||||
"Mutes SNES audio output when enabled",
|
||||
true, Setting::TRUE_FALSE);
|
||||
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
|
||||
"Merge fields in NTSC video filter\n"
|
||||
"Set to true if using filter at any refresh rate other than 60hz\n"
|
||||
"", false, Setting::TRUE_FALSE);
|
||||
|
||||
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
|
||||
false, Setting::TRUE_FALSE);
|
||||
|
||||
//do not save these settings to config_file
|
||||
Setting CPU::hdma_enable(0, "cpu.hdma_enable", "Enable HDMA effects", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE);
|
||||
|
||||
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::TRUE_FALSE);
|
||||
|
||||
};
|
||||
+26
-1
@@ -2,14 +2,39 @@ extern Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
extern struct FS {
|
||||
static class Path : public Setting {
|
||||
public:
|
||||
void sset(const char *_data);
|
||||
SettingOperators(Path);
|
||||
} base_path, rom_path, save_path;
|
||||
static Setting save_ext;
|
||||
} fs;
|
||||
|
||||
extern struct SNES {
|
||||
static class VideoColorAdjust : public Setting {
|
||||
public:
|
||||
void set(uint32 _data);
|
||||
SettingOperators(VideoColorAdjust);
|
||||
} video_color_curve, video_color_adjust_mode;
|
||||
} gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
|
||||
|
||||
static Setting ntsc_merge_fields;
|
||||
static Setting mute;
|
||||
} snes;
|
||||
|
||||
extern struct CPU {
|
||||
static Setting hdma_enable;
|
||||
} cpu;
|
||||
|
||||
extern struct PPU {
|
||||
static Setting opt_enable;
|
||||
|
||||
static Setting bg1_pri0_enable, bg1_pri1_enable;
|
||||
static Setting bg2_pri0_enable, bg2_pri1_enable;
|
||||
static Setting bg3_pri0_enable, bg3_pri1_enable;
|
||||
static Setting bg4_pri0_enable, bg4_pri1_enable;
|
||||
static Setting oam_pri0_enable, oam_pri1_enable;
|
||||
static Setting oam_pri2_enable, oam_pri3_enable;
|
||||
} ppu;
|
||||
|
||||
};
|
||||
+12
-136
@@ -1,18 +1,12 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "bcpu_opfn.cpp"
|
||||
#include "bcpu_op_read.cpp"
|
||||
#include "bcpu_op_rmw.cpp"
|
||||
#include "bcpu_op_write.cpp"
|
||||
#include "bcpu_op_pc.cpp"
|
||||
#include "bcpu_op_misc.cpp"
|
||||
#include "core/core.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
#include "bcpu_exec.cpp"
|
||||
#include "bcpu_mmio.cpp"
|
||||
#include "bcpu_dma.cpp"
|
||||
|
||||
#include "bcpu_timing.cpp"
|
||||
|
||||
#include "bcpu_int.cpp"
|
||||
|
||||
uint8 bCPU::pio_status() { return status.pio; }
|
||||
@@ -49,7 +43,7 @@ void bCPU::run() {
|
||||
void bCPU::scanline() {
|
||||
time.hdma_triggered = false;
|
||||
|
||||
if(vcounter() == 225 && status.auto_joypad_poll == true) {
|
||||
if(vcounter() == (overscan() == false ? 227 : 242) && status.auto_joypad_poll == true) {
|
||||
snes->poll_input(SNES::DEV_JOYPAD1);
|
||||
snes->poll_input(SNES::DEV_JOYPAD2);
|
||||
//When the SNES auto-polls the joypads, it writes 1, then 0 to
|
||||
@@ -85,7 +79,9 @@ void bCPU::power() {
|
||||
|
||||
void bCPU::reset() {
|
||||
//reset vector location
|
||||
regs.pc = r_mem->read(0xfffc) | (r_mem->read(0xfffd) << 8);
|
||||
regs.pc.d = 0;
|
||||
regs.pc.l = r_mem->read(0xfffc);
|
||||
regs.pc.h = r_mem->read(0xfffd);
|
||||
|
||||
//registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
@@ -97,6 +93,9 @@ void bCPU::reset() {
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
|
||||
//simulate pbr:pc push during reset irq vector
|
||||
regs.s.l -= 3;
|
||||
|
||||
time_reset();
|
||||
mmio_reset();
|
||||
dma_reset();
|
||||
@@ -124,131 +123,8 @@ void bCPU::reset() {
|
||||
add_cycles(186);
|
||||
}
|
||||
|
||||
uint8 bCPU::port_read(uint8 port) {
|
||||
return apu_port[port & 3];
|
||||
}
|
||||
|
||||
void bCPU::port_write(uint8 port, uint8 value) {
|
||||
apu_port[port & 3] = value;
|
||||
}
|
||||
|
||||
void bCPU::cpu_c2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
/* The next 3 functions control bus timing for the CPU.
|
||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||
* mem_read / mem_write indicate memory access bus cycle,
|
||||
* they are either 6, 8, or 12 bus cycles long, depending
|
||||
* both on location and the $420d.d0 FastROM enable bit.
|
||||
*/
|
||||
|
||||
void bCPU::cpu_io() {
|
||||
status.cycle_count = 6;
|
||||
pre_exec_cycle();
|
||||
add_cycles(6);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
uint8 bCPU::mem_read(uint32 addr) {
|
||||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count - 4);
|
||||
regs.mdr = r_mem->read(addr);
|
||||
add_cycles(4);
|
||||
cycle_edge();
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void bCPU::mem_write(uint32 addr, uint8 value) {
|
||||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count);
|
||||
r_mem->write(addr, value);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
addr &= 0xffff;
|
||||
break;
|
||||
case OPMODE_LONG:
|
||||
addr &= 0xffffff;
|
||||
break;
|
||||
case OPMODE_DBR:
|
||||
addr = ((regs.db << 16) + addr) & 0xffffff;
|
||||
break;
|
||||
case OPMODE_PBR:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.pc.b << 16) + addr;
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.d + addr) & 0xffff;
|
||||
break;
|
||||
case OPMODE_SP:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.s + addr) & 0xffff;
|
||||
break;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read() {
|
||||
uint8 r;
|
||||
r = mem_read(regs.pc.d);
|
||||
regs.pc.w++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
|
||||
addr = op_addr(mode, addr);
|
||||
return mem_read(addr);
|
||||
}
|
||||
|
||||
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
|
||||
addr = op_addr(mode, addr);
|
||||
mem_write(addr, value);
|
||||
}
|
||||
|
||||
uint8 bCPU::stack_read() {
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
}
|
||||
return mem_read(regs.s);
|
||||
}
|
||||
|
||||
void bCPU::stack_write(uint8 value) {
|
||||
mem_write(regs.s, value);
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
bCPU::bCPU() {
|
||||
mmio = new bCPUMMIO(this);
|
||||
init_op_tables();
|
||||
}
|
||||
|
||||
bCPU::~bCPU() {
|
||||
delete(mmio);
|
||||
}
|
||||
bCPU::~bCPU() {}
|
||||
+11
-160
@@ -1,36 +1,13 @@
|
||||
class bCPU;
|
||||
|
||||
class bCPUMMIO : public MMIO {
|
||||
public:
|
||||
bCPU *cpu;
|
||||
inline uint8 read (uint32 addr);
|
||||
inline void write(uint32 addr, uint8 value);
|
||||
bCPUMMIO(bCPU *_cpu);
|
||||
};
|
||||
|
||||
class bCPU : public CPU {
|
||||
private:
|
||||
void (bCPU::*optbl[256])();
|
||||
public:
|
||||
#include "core/core.h"
|
||||
#include "memory/memory.h"
|
||||
#include "dma/dma.h"
|
||||
#include "timing/timing.h"
|
||||
|
||||
enum { NTSC = 0, PAL = 1 };
|
||||
uint8 region;
|
||||
|
||||
public:
|
||||
#include "bcpu_timing.h"
|
||||
|
||||
uint8 apu_port[4];
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
enum {
|
||||
OPMODE_ADDR = 1, OPMODE_LONG = 2,
|
||||
OPMODE_DBR = 3, OPMODE_PBR = 4,
|
||||
OPMODE_DP = 5, OPMODE_SP = 6
|
||||
};
|
||||
|
||||
CPUReg24 aa, rd;
|
||||
uint8 dp, sp;
|
||||
|
||||
enum {
|
||||
DMASTATE_DMASYNC,
|
||||
DMASTATE_DMASYNC2,
|
||||
@@ -73,8 +50,8 @@ struct {
|
||||
uint32 wram_addr;
|
||||
|
||||
//$4016-$4017
|
||||
uint8 joypad1_strobe_value, joypad2_strobe_value;
|
||||
uint8 joypad1_read_pos, joypad2_read_pos;
|
||||
bool joypad_strobe_latch;
|
||||
uint8 joypad1_read_pos, joypad2_read_pos;
|
||||
|
||||
//$4200
|
||||
bool nmi_enabled;
|
||||
@@ -99,51 +76,6 @@ struct {
|
||||
uint16 r4216;
|
||||
} status;
|
||||
|
||||
//$43x0.d7
|
||||
enum {
|
||||
DMA_CPUTOMMIO = 0,
|
||||
DMA_MMIOTOCPU = 1
|
||||
};
|
||||
|
||||
struct {
|
||||
uint32 read_index; //set to 0 at beginning of DMA/HDMA
|
||||
|
||||
//$420b
|
||||
bool active;
|
||||
//$420c
|
||||
bool hdma_enabled;
|
||||
//$43x0
|
||||
uint8 dmap;
|
||||
bool direction;
|
||||
bool hdma_indirect;
|
||||
int8 incmode;
|
||||
bool fixedxfer;
|
||||
uint8 xfermode;
|
||||
//$43x1
|
||||
uint8 destaddr;
|
||||
//$43x2-$43x3
|
||||
uint16 srcaddr;
|
||||
//$43x4
|
||||
uint8 srcbank;
|
||||
//$43x5-$43x6
|
||||
union {
|
||||
uint16 xfersize;
|
||||
uint16 hdma_iaddr;
|
||||
};
|
||||
//$43x7
|
||||
uint8 hdma_ibank;
|
||||
//$43x8-$43x9
|
||||
uint16 hdma_addr;
|
||||
//$43xa
|
||||
uint8 hdma_line_counter;
|
||||
//$43xb/$43xf
|
||||
uint8 hdma_unknown;
|
||||
|
||||
//hdma-specific
|
||||
bool hdma_active;
|
||||
bool hdma_do_transfer;
|
||||
} channel[8];
|
||||
|
||||
inline bool hdma_test();
|
||||
inline bool nmi_test();
|
||||
inline bool irq_test();
|
||||
@@ -158,27 +90,6 @@ struct {
|
||||
|
||||
inline void irq_run();
|
||||
|
||||
//dma commands
|
||||
inline void dma_add_cycles(uint32 cycles);
|
||||
inline void hdma_add_cycles(uint32 cycles);
|
||||
inline void dma_run();
|
||||
inline void hdma_run();
|
||||
inline void hdma_update(uint8 i);
|
||||
inline uint8 hdma_enabled_channels();
|
||||
inline uint8 hdma_active_channels();
|
||||
inline void hdmainit_activate();
|
||||
inline void hdma_activate();
|
||||
inline void dma_cputommio(uint8 i, uint8 index);
|
||||
inline void dma_mmiotocpu(uint8 i, uint8 index);
|
||||
inline void dma_write(uint8 i, uint8 index);
|
||||
inline uint32 dma_addr(uint8 i);
|
||||
inline uint32 hdma_addr(uint8 i);
|
||||
inline uint32 hdma_iaddr(uint8 i);
|
||||
inline uint16 hdma_mmio(uint8 i);
|
||||
inline uint8 hdma_read(uint8 i);
|
||||
inline void hdma_write(uint8 i, uint8 x);
|
||||
inline void dma_reset();
|
||||
|
||||
//mmio commands
|
||||
void mmio_reset();
|
||||
uint8 mmio_r2180();
|
||||
@@ -213,7 +124,6 @@ struct {
|
||||
void mmio_w2182(uint8 value);
|
||||
void mmio_w2183(uint8 value);
|
||||
void mmio_w4016(uint8 value);
|
||||
void mmio_w4017(uint8 value);
|
||||
void mmio_w4200(uint8 value);
|
||||
void mmio_w4201(uint8 value);
|
||||
void mmio_w4202(uint8 value);
|
||||
@@ -241,7 +151,10 @@ struct {
|
||||
void mmio_w43xa(uint8 value, uint8 i);
|
||||
void mmio_w43xb(uint8 value, uint8 i);
|
||||
|
||||
enum { CYCLE_OPREAD = 0, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
|
||||
uint8 mmio_read (uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
enum { CYCLE_OPREAD, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
|
||||
inline void pre_exec_cycle();
|
||||
inline void exec_hdma();
|
||||
inline void exec_dma();
|
||||
@@ -249,68 +162,6 @@ enum { CYCLE_OPREAD = 0, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
|
||||
inline void last_cycle();
|
||||
inline bool in_opcode();
|
||||
|
||||
//cpu extra-cycle conditions
|
||||
inline void cpu_c2();
|
||||
inline void cpu_c4(uint16 x, uint16 y);
|
||||
inline void cpu_c6(uint16 addr);
|
||||
inline void cpu_io();
|
||||
|
||||
inline uint8 mem_read (uint32 addr);
|
||||
inline void mem_write(uint32 addr, uint8 value);
|
||||
inline uint32 op_addr(uint8 mode, uint32 addr);
|
||||
inline uint8 op_read();
|
||||
inline uint8 op_read(uint8 mode, uint32 addr);
|
||||
inline void op_write(uint8 mode, uint32 addr, uint8 value);
|
||||
inline uint8 stack_read();
|
||||
inline void stack_write(uint8 value);
|
||||
|
||||
//opcode functions
|
||||
inline void init_op_tables();
|
||||
|
||||
//op_read
|
||||
inline void op_adc_b();
|
||||
inline void op_adc_w();
|
||||
inline void op_and_b();
|
||||
inline void op_and_w();
|
||||
inline void op_bit_b();
|
||||
inline void op_bit_w();
|
||||
inline void op_cmp_b();
|
||||
inline void op_cmp_w();
|
||||
inline void op_cpx_b();
|
||||
inline void op_cpx_w();
|
||||
inline void op_cpy_b();
|
||||
inline void op_cpy_w();
|
||||
inline void op_eor_b();
|
||||
inline void op_eor_w();
|
||||
inline void op_lda_b();
|
||||
inline void op_lda_w();
|
||||
inline void op_ldx_b();
|
||||
inline void op_ldx_w();
|
||||
inline void op_ldy_b();
|
||||
inline void op_ldy_w();
|
||||
inline void op_ora_b();
|
||||
inline void op_ora_w();
|
||||
inline void op_sbc_b();
|
||||
inline void op_sbc_w();
|
||||
//op_rmw
|
||||
inline void op_inc_b();
|
||||
inline void op_inc_w();
|
||||
inline void op_dec_b();
|
||||
inline void op_dec_w();
|
||||
inline void op_asl_b();
|
||||
inline void op_asl_w();
|
||||
inline void op_lsr_b();
|
||||
inline void op_lsr_w();
|
||||
inline void op_rol_b();
|
||||
inline void op_rol_w();
|
||||
inline void op_ror_b();
|
||||
inline void op_ror_w();
|
||||
inline void op_trb_b();
|
||||
inline void op_trb_w();
|
||||
inline void op_tsb_b();
|
||||
inline void op_tsb_w();
|
||||
#include "bcpu_op.h"
|
||||
|
||||
bCPU();
|
||||
~bCPU();
|
||||
};
|
||||
@@ -1,250 +0,0 @@
|
||||
void bCPU::dma_add_cycles(uint32 cycles) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
void bCPU::hdma_add_cycles(uint32 cycles) {
|
||||
if(run_state.dma) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
status.hdma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
uint32 bCPU::dma_addr(uint8 i) {
|
||||
uint32 r;
|
||||
r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||
|
||||
if(channel[i].fixedxfer == false) {
|
||||
channel[i].srcaddr += channel[i].incmode;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::dma_cputommio(uint8 i, uint8 index) {
|
||||
uint8 x;
|
||||
if(sdd1->dma_active() == true) {
|
||||
x = sdd1->dma_read();
|
||||
} else {
|
||||
x = r_mem->read(dma_addr(i));
|
||||
}
|
||||
|
||||
r_mem->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
|
||||
uint8 x;
|
||||
x = r_mem->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
|
||||
r_mem->write(dma_addr(i), x);
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_write(uint8 i, uint8 index) {
|
||||
if(channel[i].direction == 0) {
|
||||
dma_cputommio(i, index);
|
||||
} else {
|
||||
dma_mmiotocpu(i, index);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_run() {
|
||||
int i;
|
||||
for(i=0;i<8;i++) {
|
||||
if(channel[i].active == false)continue;
|
||||
|
||||
//first byte transferred?
|
||||
if(channel[i].read_index == 0) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
channel[i].xfersize);
|
||||
}
|
||||
|
||||
switch(channel[i].xfermode) {
|
||||
case 0:dma_write(i, 0); break; //0
|
||||
case 1:dma_write(i, channel[i].read_index & 1); break; //0,1
|
||||
case 2:dma_write(i, 0); break; //0,0
|
||||
case 3:dma_write(i, (channel[i].read_index >> 1) & 1);break; //0,0,1,1
|
||||
case 4:dma_write(i, channel[i].read_index & 3); break; //0,1,2,3
|
||||
case 5:dma_write(i, channel[i].read_index & 1); break; //0,1,0,1
|
||||
case 6:dma_write(i, 0); break; //0,0 [2]
|
||||
case 7:dma_write(i, (channel[i].read_index >> 1) & 1);break; //0,0,1,1 [3]
|
||||
}
|
||||
|
||||
channel[i].read_index++;
|
||||
dma_add_cycles(8);
|
||||
|
||||
if(channel[i].xfersize == 0) {
|
||||
channel[i].active = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_addr(uint8 i) {
|
||||
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_iaddr(uint8 i) {
|
||||
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
|
||||
}
|
||||
|
||||
uint16 bCPU::hdma_mmio(uint8 i) {
|
||||
uint8 l = channel[i].read_index;
|
||||
uint16 index;
|
||||
switch(channel[i].xfermode) {
|
||||
case 0:index = 0; break; //0
|
||||
case 1:index = l & 1; break; //0,1
|
||||
case 2:index = 0; break; //0,0
|
||||
case 3:index = (l >> 1) & 1;break; //0,0,1,1
|
||||
case 4:index = l & 3; break; //0,1,2,3
|
||||
case 5:index = l & 1; break; //0,1,0,1
|
||||
case 6:index = 0; break; //0,0 [2]
|
||||
case 7:index = (l >> 1) & 1;break; //0,0,1,1 [3]
|
||||
}
|
||||
|
||||
return (0x2100 | ((channel[i].destaddr + index) & 0xff));
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_read(uint8 i) {
|
||||
if(channel[i].direction == DMA_MMIOTOCPU) {
|
||||
return r_mem->read(hdma_mmio(i));
|
||||
} else if(!channel[i].hdma_indirect) {
|
||||
return r_mem->read(hdma_addr(i));
|
||||
} else {
|
||||
return r_mem->read(hdma_iaddr(i));
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_write(uint8 i, uint8 x) {
|
||||
if(channel[i].direction == DMA_CPUTOMMIO) {
|
||||
r_mem->write(hdma_mmio(i), x);
|
||||
} else if(!channel[i].hdma_indirect) {
|
||||
r_mem->write(hdma_addr(i), x);
|
||||
} else {
|
||||
r_mem->write(hdma_iaddr(i), x);
|
||||
}
|
||||
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
|
||||
void bCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
|
||||
if(channel[i].hdma_line_counter == 0) {
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
return;
|
||||
}
|
||||
|
||||
channel[i].hdma_do_transfer = true;
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_run() {
|
||||
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
for(int i=0;i<8;i++) {
|
||||
if(!channel[i].hdma_enabled || !channel[i].hdma_active)continue;
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
for(channel[i].read_index=0;channel[i].read_index<xferlen;channel[i].read_index++) {
|
||||
hdma_write(i, hdma_read(i));
|
||||
}
|
||||
}
|
||||
|
||||
channel[i].hdma_line_counter--;
|
||||
channel[i].hdma_do_transfer = !!(channel[i].hdma_line_counter & 0x80);
|
||||
if((channel[i].hdma_line_counter & 0x7f) == 0) {
|
||||
hdma_update(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_enabled_channels() {
|
||||
int r = 0;
|
||||
for(int i=0;i<8;i++) {
|
||||
if(channel[i].hdma_enabled)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_active_channels() {
|
||||
int r = 0;
|
||||
for(int i=0;i<8;i++) {
|
||||
if(channel[i].hdma_enabled && channel[i].hdma_active)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* hdmainit_activate()
|
||||
* hdma_activate()
|
||||
*
|
||||
* Functions are called by CPU timing routine
|
||||
* when an HDMA event (init or run) occurs.
|
||||
*/
|
||||
|
||||
void bCPU::hdmainit_activate() {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
|
||||
if(hdma_enabled_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_IDMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_activate() {
|
||||
if(hdma_active_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_DMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_reset() {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].read_index = 0;
|
||||
channel[i].active = false;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].dmap = 0x00;
|
||||
channel[i].direction = 0;
|
||||
channel[i].hdma_indirect = false;
|
||||
channel[i].incmode = 1;
|
||||
channel[i].fixedxfer = false;
|
||||
channel[i].xfermode = 0;
|
||||
channel[i].destaddr = 0;
|
||||
channel[i].srcaddr = 0;
|
||||
channel[i].xfersize = 0x0000;
|
||||
//xfersize and hdma_iaddr are of union { uint16 };
|
||||
//channel[i].hdma_iaddr = 0x0000;
|
||||
channel[i].hdma_ibank = 0;
|
||||
channel[i].hdma_addr = 0x0000;
|
||||
channel[i].hdma_line_counter = 0x00;
|
||||
channel[i].hdma_unknown = 0x00;
|
||||
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
void bCPU::last_cycle() {
|
||||
time.nmi_pending = nmi_test();
|
||||
//DMV27: keep previous nmi value,
|
||||
//to allow wai and irq to work properly
|
||||
time.nmi_pending = nmi_test() || time.nmi_pending;
|
||||
time.irq_pending = irq_test();
|
||||
}
|
||||
|
||||
@@ -170,7 +172,3 @@ void bCPU::exec_cycle() {
|
||||
bool bCPU::in_opcode() {
|
||||
return (status.cycle_pos != 0);
|
||||
}
|
||||
|
||||
void bCPU::init_op_tables() {
|
||||
#include "bcpu_optable.cpp"
|
||||
}
|
||||
@@ -13,18 +13,37 @@ void bCPU::irq_run() {
|
||||
//WDC documentation is incorrect, first cycle
|
||||
//is a memory read fetch from PBR:PC
|
||||
switch(status.cycle_pos++) {
|
||||
case 0: add_cycles(r_mem->speed(regs.pc.d)); break;
|
||||
case 1: add_cycles(6); break;
|
||||
case 2: stack_write(regs.pc.b); break;
|
||||
case 3: stack_write(regs.pc.h); break;
|
||||
case 4: stack_write(regs.pc.l); break;
|
||||
case 5: stack_write(regs.p); break;
|
||||
case 6: rd.l = op_read(OPMODE_ADDR, aa.w); break;
|
||||
case 7: rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
case 0:
|
||||
//read from PBR:PC, but do not increment PC counter
|
||||
mem_read(regs.pc.d);
|
||||
break;
|
||||
case 1:
|
||||
cpu_io();
|
||||
if(regs.e)status.cycle_pos++;
|
||||
break;
|
||||
case 2:
|
||||
stack_write(regs.pc.b);
|
||||
break;
|
||||
case 3:
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 4:
|
||||
stack_write(regs.pc.l);
|
||||
break;
|
||||
case 5:
|
||||
//emulation-mode irqs clear brk bit 0x10
|
||||
stack_write((regs.e) ? (regs.p & ~0x10) : regs.p);
|
||||
break;
|
||||
case 6:
|
||||
//todo: test if NMI can override IRQ here...
|
||||
rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
break;
|
||||
case 7:
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
#ifdef DEBUGGER
|
||||
//let debugger know the new IRQ opcode address
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_END);
|
||||
|
||||
+149
-150
@@ -3,10 +3,9 @@ void bCPU::mmio_reset() {
|
||||
status.wram_addr = 0x000000;
|
||||
|
||||
//$4016-$4017
|
||||
status.joypad1_strobe_value = 0x00;
|
||||
status.joypad2_strobe_value = 0x00;
|
||||
status.joypad1_read_pos = 0;
|
||||
status.joypad2_read_pos = 0;
|
||||
status.joypad_strobe_latch = 0;
|
||||
status.joypad1_read_pos = 0;
|
||||
status.joypad2_read_pos = 0;
|
||||
|
||||
//$4200
|
||||
status.nmi_enabled = false;
|
||||
@@ -18,16 +17,16 @@ void bCPU::mmio_reset() {
|
||||
status.pio = 0xff;
|
||||
|
||||
//$4202-$4203
|
||||
status.mul_a = 0x00;
|
||||
status.mul_b = 0x00;
|
||||
status.mul_a = 0xff;
|
||||
status.mul_b = 0xff;
|
||||
|
||||
//$4204-$4206
|
||||
status.div_a = 0x0000;
|
||||
status.div_b = 0x00;
|
||||
status.div_a = 0xffff;
|
||||
status.div_b = 0xff;
|
||||
|
||||
//$4207-$420a
|
||||
status.hirq_pos = 0;
|
||||
status.virq_pos = 0;
|
||||
status.hirq_pos = 0x01ff;
|
||||
status.virq_pos = 0x01ff;
|
||||
|
||||
//$4214-$4217
|
||||
status.r4214 = 0x0000;
|
||||
@@ -59,26 +58,30 @@ uint8 bCPU::mmio_r4016() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0xfc;
|
||||
|
||||
if(status.joypad1_strobe_value == 1) {
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B);
|
||||
} else {
|
||||
switch(status.joypad1_read_pos) {
|
||||
case 0:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B); break;
|
||||
case 1:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y); break;
|
||||
case 2:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT);break;
|
||||
case 3:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START); break;
|
||||
case 4:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP); break;
|
||||
case 5:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN); break;
|
||||
case 6:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT); break;
|
||||
case 7:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT); break;
|
||||
case 8:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A); break;
|
||||
case 9:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X); break;
|
||||
case 10:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L); break;
|
||||
case 11:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R); break;
|
||||
case 16:r |= 1;break; //joypad connected bit
|
||||
default:r |= 1;break; //after 16th read, all subsequent reads return 1
|
||||
case 0: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B); break;
|
||||
case 1: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y); break;
|
||||
case 2: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT); break;
|
||||
case 3: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_START); break;
|
||||
case 4: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_UP); break;
|
||||
case 5: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_DOWN); break;
|
||||
case 6: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_LEFT); break;
|
||||
case 7: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_RIGHT); break;
|
||||
case 8: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A); break;
|
||||
case 9: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X); break;
|
||||
case 10: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L); break;
|
||||
case 11: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_R); break;
|
||||
case 12: break;
|
||||
case 13: break;
|
||||
case 14: break;
|
||||
case 15: break; //bits 12-15 always return 0
|
||||
//all subsequent reads return joypad connection status
|
||||
case 16: r |= 1; break; //joypad connected bit
|
||||
}
|
||||
if(++status.joypad1_read_pos > 17)status.joypad1_read_pos = 17;
|
||||
if(++status.joypad1_read_pos > 16)status.joypad1_read_pos = 16;
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -86,33 +89,37 @@ uint8 r;
|
||||
|
||||
//JOYSER1
|
||||
//7-5 = MDR
|
||||
//4-2 = Always 1
|
||||
//4-2 = Always 1 (pins are connected to GND)
|
||||
//1-0 = Joypad serial data
|
||||
uint8 bCPU::mmio_r4017() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0xe0;
|
||||
r |= 0x1c;
|
||||
|
||||
if(status.joypad2_strobe_value == 1) {
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B);
|
||||
} else {
|
||||
switch(status.joypad2_read_pos) {
|
||||
case 0:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B); break;
|
||||
case 1:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y); break;
|
||||
case 2:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT);break;
|
||||
case 3:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START); break;
|
||||
case 4:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP); break;
|
||||
case 5:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN); break;
|
||||
case 6:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT); break;
|
||||
case 7:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT); break;
|
||||
case 8:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A); break;
|
||||
case 9:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X); break;
|
||||
case 10:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L); break;
|
||||
case 11:r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R); break;
|
||||
case 16:r |= 1;break; //joypad connected bit
|
||||
default:r |= 1;break; //after 16th read, all subsequent reads return 1
|
||||
case 0: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_B); break;
|
||||
case 1: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_Y); break;
|
||||
case 2: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_SELECT); break;
|
||||
case 3: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_START); break;
|
||||
case 4: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_UP); break;
|
||||
case 5: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_DOWN); break;
|
||||
case 6: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_LEFT); break;
|
||||
case 7: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_RIGHT); break;
|
||||
case 8: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_A); break;
|
||||
case 9: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_X); break;
|
||||
case 10: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_L); break;
|
||||
case 11: r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD2, SNES::JOYPAD_R); break;
|
||||
case 12: break;
|
||||
case 13: break;
|
||||
case 14: break;
|
||||
case 15: break; //bits 12-15 always return 0
|
||||
//all subsequent reads return joypad connection status
|
||||
case 16: r |= 1; break; //joypad connected bit
|
||||
}
|
||||
if(++status.joypad2_read_pos > 17)status.joypad2_read_pos = 17;
|
||||
if(++status.joypad2_read_pos > 16)status.joypad2_read_pos = 16;
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -320,8 +327,7 @@ uint8 bCPU::mmio_r43xb(uint8 i) {
|
||||
return channel[i].hdma_unknown;
|
||||
}
|
||||
|
||||
uint8 bCPUMMIO::read(uint32 addr) {
|
||||
uint i;
|
||||
uint8 bCPU::mmio_read(uint16 addr) {
|
||||
//APU
|
||||
if(addr >= 0x2140 && addr <= 0x217f) {
|
||||
return r_apu->port_read(addr & 3);
|
||||
@@ -329,47 +335,50 @@ uint i;
|
||||
|
||||
//HDMA
|
||||
if(addr >= 0x4300 && addr <= 0x437f) {
|
||||
i = (addr >> 4) & 7;
|
||||
uint i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
case 0x0:return cpu->mmio_r43x0(i);
|
||||
case 0x1:return cpu->mmio_r43x1(i);
|
||||
case 0x2:return cpu->mmio_r43x2(i);
|
||||
case 0x3:return cpu->mmio_r43x3(i);
|
||||
case 0x4:return cpu->mmio_r43x4(i);
|
||||
case 0x5:return cpu->mmio_r43x5(i);
|
||||
case 0x6:return cpu->mmio_r43x6(i);
|
||||
case 0x7:return cpu->mmio_r43x7(i);
|
||||
case 0x8:return cpu->mmio_r43x8(i);
|
||||
case 0x9:return cpu->mmio_r43x9(i);
|
||||
case 0xa:return cpu->mmio_r43xa(i);
|
||||
case 0xb:return cpu->mmio_r43xb(i);
|
||||
case 0xc:return cpu->regs.mdr; //unmapped
|
||||
case 0xd:return cpu->regs.mdr; //unmapped
|
||||
case 0xe:return cpu->regs.mdr; //unmapped
|
||||
case 0xf:return cpu->mmio_r43xb(i); //mirror of 43xb
|
||||
case 0x0: return mmio_r43x0(i);
|
||||
case 0x1: return mmio_r43x1(i);
|
||||
case 0x2: return mmio_r43x2(i);
|
||||
case 0x3: return mmio_r43x3(i);
|
||||
case 0x4: return mmio_r43x4(i);
|
||||
case 0x5: return mmio_r43x5(i);
|
||||
case 0x6: return mmio_r43x6(i);
|
||||
case 0x7: return mmio_r43x7(i);
|
||||
case 0x8: return mmio_r43x8(i);
|
||||
case 0x9: return mmio_r43x9(i);
|
||||
case 0xa: return mmio_r43xa(i);
|
||||
case 0xb: return mmio_r43xb(i);
|
||||
case 0xc: return regs.mdr; //unmapped
|
||||
case 0xd: return regs.mdr; //unmapped
|
||||
case 0xe: return regs.mdr; //unmapped
|
||||
case 0xf: return mmio_r43xb(i); //mirror of 43xb
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x2180:return cpu->mmio_r2180(); //WMDATA
|
||||
case 0x4016:return cpu->mmio_r4016(); //JOYSER0
|
||||
case 0x4017:return cpu->mmio_r4017(); //JOYSER1
|
||||
case 0x4210:return cpu->mmio_r4210(); //RDNMI
|
||||
case 0x4211:return cpu->mmio_r4211(); //TIMEUP
|
||||
case 0x4212:return cpu->mmio_r4212(); //HVBJOY
|
||||
case 0x4213:return cpu->mmio_r4213(); //RDIO
|
||||
case 0x4214:return cpu->mmio_r4214(); //RDDIVL
|
||||
case 0x4215:return cpu->mmio_r4215(); //RDDIVH
|
||||
case 0x4216:return cpu->mmio_r4216(); //RDMPYL
|
||||
case 0x4217:return cpu->mmio_r4217(); //RDMPYH
|
||||
case 0x4218:return cpu->mmio_r4218(); //JOY1L
|
||||
case 0x4219:return cpu->mmio_r4219(); //JOY1H
|
||||
case 0x421a:return cpu->mmio_r421a(); //JOY2L
|
||||
case 0x421b:return cpu->mmio_r421b(); //JOY2H
|
||||
case 0x421c:case 0x421d:case 0x421e:case 0x421f:return 0x00;
|
||||
case 0x2180: return mmio_r2180(); //WMDATA
|
||||
case 0x4016: return mmio_r4016(); //JOYSER0
|
||||
case 0x4017: return mmio_r4017(); //JOYSER1
|
||||
case 0x4210: return mmio_r4210(); //RDNMI
|
||||
case 0x4211: return mmio_r4211(); //TIMEUP
|
||||
case 0x4212: return mmio_r4212(); //HVBJOY
|
||||
case 0x4213: return mmio_r4213(); //RDIO
|
||||
case 0x4214: return mmio_r4214(); //RDDIVL
|
||||
case 0x4215: return mmio_r4215(); //RDDIVH
|
||||
case 0x4216: return mmio_r4216(); //RDMPYL
|
||||
case 0x4217: return mmio_r4217(); //RDMPYH
|
||||
case 0x4218: return mmio_r4218(); //JOY1L
|
||||
case 0x4219: return mmio_r4219(); //JOY1H
|
||||
case 0x421a: return mmio_r421a(); //JOY2L
|
||||
case 0x421b: return mmio_r421b(); //JOY2H
|
||||
case 0x421c: return 0x00;
|
||||
case 0x421d: return 0x00;
|
||||
case 0x421e: return 0x00;
|
||||
case 0x421f: return 0x00;
|
||||
}
|
||||
|
||||
return cpu->regs.mdr;
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
//WMDATA
|
||||
@@ -398,29 +407,26 @@ void bCPU::mmio_w2183(uint8 value) {
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
|
||||
//strobing $4016.d0 affects both controller port latches.
|
||||
//$4017 bit 0 writes are ignored.
|
||||
void bCPU::mmio_w4016(uint8 value) {
|
||||
status.joypad1_strobe_value = !!(value & 1);
|
||||
if(value == 1) {
|
||||
snes->poll_input(SNES::DEV_JOYPAD1);
|
||||
status.joypad1_read_pos = 0;
|
||||
}
|
||||
}
|
||||
status.joypad_strobe_latch = bool(value & 1);
|
||||
|
||||
//JOYSER1
|
||||
void bCPU::mmio_w4017(uint8 value) {
|
||||
status.joypad2_strobe_value = !!(value & 1);
|
||||
if(value == 1) {
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
snes->poll_input(SNES::DEV_JOYPAD1);
|
||||
snes->poll_input(SNES::DEV_JOYPAD2);
|
||||
status.joypad1_read_pos = 0;
|
||||
status.joypad2_read_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//NMITIMEN
|
||||
void bCPU::mmio_w4200(uint8 value) {
|
||||
status.nmi_enabled = !!(value & 0x80);
|
||||
status.virq_enabled = !!(value & 0x20);
|
||||
status.hirq_enabled = !!(value & 0x10);
|
||||
status.auto_joypad_poll = !!(value & 0x01);
|
||||
status.nmi_enabled = bool(value & 0x80);
|
||||
status.virq_enabled = bool(value & 0x20);
|
||||
status.hirq_enabled = bool(value & 0x10);
|
||||
status.auto_joypad_poll = bool(value & 0x01);
|
||||
|
||||
if(time.nmi_read == 0) {
|
||||
if(time.nmi_line == 1 && !status.nmi_enabled == 0) {
|
||||
@@ -499,27 +505,25 @@ void bCPU::mmio_w420a(uint8 value) {
|
||||
|
||||
//DMAEN
|
||||
void bCPU::mmio_w420b(uint8 value) {
|
||||
int len;
|
||||
if(value != 0x00) {
|
||||
run_state.dma = true;
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
}
|
||||
|
||||
for(int i=0;i<8;i++) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(value & (1 << i)) {
|
||||
channel[i].active = true;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].read_index = 0;
|
||||
//DMA enable does not disable active HDMA channels
|
||||
channel[i].active = true;
|
||||
channel[i].read_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//HDMAEN
|
||||
void bCPU::mmio_w420c(uint8 value) {
|
||||
for(int i=0;i<8;i++) {
|
||||
channel[i].hdma_enabled = !!(value & (1 << i));
|
||||
channel[i].hdma_active = !!(value & (1 << i));
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].hdma_enabled = bool(value & (1 << i));
|
||||
channel[i].hdma_active = bool(value & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,10 +535,10 @@ void bCPU::mmio_w420d(uint8 value) {
|
||||
//DMAPx
|
||||
void bCPU::mmio_w43x0(uint8 value, uint8 i) {
|
||||
channel[i].dmap = value;
|
||||
channel[i].direction = !!(value & 0x80);
|
||||
channel[i].hdma_indirect = !!(value & 0x40);
|
||||
channel[i].incmode = (value & 0x10)?-1:1;
|
||||
channel[i].fixedxfer = !!(value & 0x08);
|
||||
channel[i].direction = bool(value & 0x80);
|
||||
channel[i].hdma_indirect = bool(value & 0x40);
|
||||
channel[i].incmode = (value & 0x10) ? -1 : 1;
|
||||
channel[i].fixedxfer = bool(value & 0x08);
|
||||
channel[i].xfermode = value & 7;
|
||||
}
|
||||
|
||||
@@ -593,61 +597,56 @@ void bCPU::mmio_w43xb(uint8 value, uint8 i) {
|
||||
channel[i].hdma_unknown = value;
|
||||
}
|
||||
|
||||
void bCPUMMIO::write(uint32 addr, uint8 value) {
|
||||
uint8 i;
|
||||
void bCPU::mmio_write(uint16 addr, uint8 data) {
|
||||
//APU
|
||||
if(addr >= 0x2140 && addr <= 0x217f) {
|
||||
cpu->port_write(addr & 3, value);
|
||||
port_write(addr & 3, data);
|
||||
return;
|
||||
}
|
||||
|
||||
//HDMA
|
||||
if(addr >= 0x4300 && addr <= 0x437f) {
|
||||
i = (addr >> 4) & 7;
|
||||
uint i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
case 0x0:cpu->mmio_w43x0(value, i);return;
|
||||
case 0x1:cpu->mmio_w43x1(value, i);return;
|
||||
case 0x2:cpu->mmio_w43x2(value, i);return;
|
||||
case 0x3:cpu->mmio_w43x3(value, i);return;
|
||||
case 0x4:cpu->mmio_w43x4(value, i);return;
|
||||
case 0x5:cpu->mmio_w43x5(value, i);return;
|
||||
case 0x6:cpu->mmio_w43x6(value, i);return;
|
||||
case 0x7:cpu->mmio_w43x7(value, i);return;
|
||||
case 0x8:cpu->mmio_w43x8(value, i);return;
|
||||
case 0x9:cpu->mmio_w43x9(value, i);return;
|
||||
case 0xa:cpu->mmio_w43xa(value, i);return;
|
||||
case 0xb:cpu->mmio_w43xb(value, i);return;
|
||||
case 0xc:return; //unmapped
|
||||
case 0xd:return; //unmapped
|
||||
case 0xe:return; //unmapped
|
||||
case 0xf:cpu->mmio_w43xb(value, i);return; //mirror of 43xb
|
||||
case 0x0: mmio_w43x0(data, i); return;
|
||||
case 0x1: mmio_w43x1(data, i); return;
|
||||
case 0x2: mmio_w43x2(data, i); return;
|
||||
case 0x3: mmio_w43x3(data, i); return;
|
||||
case 0x4: mmio_w43x4(data, i); return;
|
||||
case 0x5: mmio_w43x5(data, i); return;
|
||||
case 0x6: mmio_w43x6(data, i); return;
|
||||
case 0x7: mmio_w43x7(data, i); return;
|
||||
case 0x8: mmio_w43x8(data, i); return;
|
||||
case 0x9: mmio_w43x9(data, i); return;
|
||||
case 0xa: mmio_w43xa(data, i); return;
|
||||
case 0xb: mmio_w43xb(data, i); return;
|
||||
case 0xc: return; //unmapped
|
||||
case 0xd: return; //unmapped
|
||||
case 0xe: return; //unmapped
|
||||
case 0xf: mmio_w43xb(data, i); return; //mirror of 43xb
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x2180:cpu->mmio_w2180(value);return; //WMDATA
|
||||
case 0x2181:cpu->mmio_w2181(value);return; //WMADDL
|
||||
case 0x2182:cpu->mmio_w2182(value);return; //WMADDM
|
||||
case 0x2183:cpu->mmio_w2183(value);return; //WMADDH
|
||||
case 0x4016:cpu->mmio_w4016(value);return; //JOYSER0
|
||||
case 0x4017:cpu->mmio_w4017(value);return; //JOYSER1
|
||||
case 0x4200:cpu->mmio_w4200(value);return; //NMITIMEN
|
||||
case 0x4201:cpu->mmio_w4201(value);return; //WRIO
|
||||
case 0x4202:cpu->mmio_w4202(value);return; //WRMPYA
|
||||
case 0x4203:cpu->mmio_w4203(value);return; //WRMPYB
|
||||
case 0x4204:cpu->mmio_w4204(value);return; //WRDIVL
|
||||
case 0x4205:cpu->mmio_w4205(value);return; //WRDIVH
|
||||
case 0x4206:cpu->mmio_w4206(value);return; //WRDIVB
|
||||
case 0x4207:cpu->mmio_w4207(value);return; //HTIMEL
|
||||
case 0x4208:cpu->mmio_w4208(value);return; //HTIMEH
|
||||
case 0x4209:cpu->mmio_w4209(value);return; //VTIMEL
|
||||
case 0x420a:cpu->mmio_w420a(value);return; //VTIMEH
|
||||
case 0x420b:cpu->mmio_w420b(value);return; //DMAEN
|
||||
case 0x420c:cpu->mmio_w420c(value);return; //HDMAEN
|
||||
case 0x420d:cpu->mmio_w420d(value);return; //MEMSEL
|
||||
case 0x2180: mmio_w2180(data); return; //WMDATA
|
||||
case 0x2181: mmio_w2181(data); return; //WMADDL
|
||||
case 0x2182: mmio_w2182(data); return; //WMADDM
|
||||
case 0x2183: mmio_w2183(data); return; //WMADDH
|
||||
case 0x4016: mmio_w4016(data); return; //JOYSER0
|
||||
case 0x4017: return; //unmapped
|
||||
case 0x4200: mmio_w4200(data); return; //NMITIMEN
|
||||
case 0x4201: mmio_w4201(data); return; //WRIO
|
||||
case 0x4202: mmio_w4202(data); return; //WRMPYA
|
||||
case 0x4203: mmio_w4203(data); return; //WRMPYB
|
||||
case 0x4204: mmio_w4204(data); return; //WRDIVL
|
||||
case 0x4205: mmio_w4205(data); return; //WRDIVH
|
||||
case 0x4206: mmio_w4206(data); return; //WRDIVB
|
||||
case 0x4207: mmio_w4207(data); return; //HTIMEL
|
||||
case 0x4208: mmio_w4208(data); return; //HTIMEH
|
||||
case 0x4209: mmio_w4209(data); return; //VTIMEL
|
||||
case 0x420a: mmio_w420a(data); return; //VTIMEH
|
||||
case 0x420b: mmio_w420b(data); return; //DMAEN
|
||||
case 0x420c: mmio_w420c(data); return; //HDMAEN
|
||||
case 0x420d: mmio_w420d(data); return; //MEMSEL
|
||||
}
|
||||
}
|
||||
|
||||
bCPUMMIO::bCPUMMIO(bCPU *_cpu) {
|
||||
cpu = _cpu;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
cl /ML /O2 bcpugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -1,8 +0,0 @@
|
||||
@del *.exe
|
||||
@del bcpu_op_misc.cpp
|
||||
@del bcpu_op_pc.cpp
|
||||
@del bcpu_op_read.cpp
|
||||
@del bcpu_op_rmw.cpp
|
||||
@del bcpu_op_write.cpp
|
||||
@del bcpu_optable.cpp
|
||||
@del bcpu_op.h
|
||||
@@ -0,0 +1,18 @@
|
||||
#define CLASS_NAME "bCPU"
|
||||
#include "../../../lib/opgen.cpp"
|
||||
|
||||
int main() {
|
||||
fph = fopen("op.h", "wb");
|
||||
fpt = fopen("optable.cpp", "wb");
|
||||
|
||||
generate("op_read.cpp", "op_read.b");
|
||||
generate("op_rmw.cpp", "op_rmw.b");
|
||||
generate("op_write.cpp", "op_write.b");
|
||||
generate("op_pc.cpp", "op_pc.b");
|
||||
generate("op_misc.cpp", "op_misc.b");
|
||||
|
||||
fclose(fph);
|
||||
fclose(fpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
cl /O2 /wd4996 bcpugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -0,0 +1,8 @@
|
||||
@del *.exe
|
||||
@del op_misc.cpp
|
||||
@del op_pc.cpp
|
||||
@del op_read.cpp
|
||||
@del op_rmw.cpp
|
||||
@del op_write.cpp
|
||||
@del optable.cpp
|
||||
@del op.h
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "opfn.cpp"
|
||||
#include "op_read.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
|
||||
void bCPU::cpu_c2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x && (x & 0xff00) != (y & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
|
||||
switch(mode) {
|
||||
case OPMODE_ADDR:
|
||||
addr &= 0xffff;
|
||||
break;
|
||||
case OPMODE_LONG:
|
||||
addr &= 0xffffff;
|
||||
break;
|
||||
case OPMODE_DBR:
|
||||
addr = ((regs.db << 16) + addr) & 0xffffff;
|
||||
break;
|
||||
case OPMODE_PBR:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.pc.b << 16) + addr;
|
||||
break;
|
||||
case OPMODE_DP:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.d + addr) & 0xffff;
|
||||
break;
|
||||
case OPMODE_SP:
|
||||
addr &= 0xffff;
|
||||
addr = (regs.s + addr) & 0xffff;
|
||||
break;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read() {
|
||||
uint8 r;
|
||||
r = mem_read(regs.pc.d);
|
||||
regs.pc.w++;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::op_read(uint8 mode, uint32 addr) {
|
||||
addr = op_addr(mode, addr);
|
||||
return mem_read(addr);
|
||||
}
|
||||
|
||||
void bCPU::op_write(uint8 mode, uint32 addr, uint8 value) {
|
||||
addr = op_addr(mode, addr);
|
||||
mem_write(addr, value);
|
||||
}
|
||||
|
||||
uint8 bCPU::stack_read() {
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
}
|
||||
return mem_read(regs.s);
|
||||
}
|
||||
|
||||
void bCPU::stack_write(uint8 value) {
|
||||
mem_write(regs.s, value);
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::init_op_tables() {
|
||||
#include "optable.cpp"
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* External functions:
|
||||
* void last_cycle();
|
||||
* void cpu_io();
|
||||
* uint8 mem_read(uint32 addr);
|
||||
* void mem_write(uint32 addr, uint8 value);
|
||||
*/
|
||||
|
||||
void (bCPU::*optbl[256])();
|
||||
|
||||
CPUReg24 aa, rd;
|
||||
uint8 dp, sp;
|
||||
|
||||
//op_read
|
||||
inline void op_adc_b();
|
||||
inline void op_adc_w();
|
||||
inline void op_and_b();
|
||||
inline void op_and_w();
|
||||
inline void op_bit_b();
|
||||
inline void op_bit_w();
|
||||
inline void op_cmp_b();
|
||||
inline void op_cmp_w();
|
||||
inline void op_cpx_b();
|
||||
inline void op_cpx_w();
|
||||
inline void op_cpy_b();
|
||||
inline void op_cpy_w();
|
||||
inline void op_eor_b();
|
||||
inline void op_eor_w();
|
||||
inline void op_lda_b();
|
||||
inline void op_lda_w();
|
||||
inline void op_ldx_b();
|
||||
inline void op_ldx_w();
|
||||
inline void op_ldy_b();
|
||||
inline void op_ldy_w();
|
||||
inline void op_ora_b();
|
||||
inline void op_ora_w();
|
||||
inline void op_sbc_b();
|
||||
inline void op_sbc_w();
|
||||
//op_rmw
|
||||
inline void op_inc_b();
|
||||
inline void op_inc_w();
|
||||
inline void op_dec_b();
|
||||
inline void op_dec_w();
|
||||
inline void op_asl_b();
|
||||
inline void op_asl_w();
|
||||
inline void op_lsr_b();
|
||||
inline void op_lsr_w();
|
||||
inline void op_rol_b();
|
||||
inline void op_rol_w();
|
||||
inline void op_ror_b();
|
||||
inline void op_ror_w();
|
||||
inline void op_trb_b();
|
||||
inline void op_trb_w();
|
||||
inline void op_tsb_b();
|
||||
inline void op_tsb_w();
|
||||
|
||||
inline void cpu_c2();
|
||||
inline void cpu_c4(uint16 x, uint16 y);
|
||||
inline void cpu_c6(uint16 addr);
|
||||
|
||||
enum {
|
||||
OPMODE_ADDR, OPMODE_LONG,
|
||||
OPMODE_DBR, OPMODE_PBR,
|
||||
OPMODE_DP, OPMODE_SP
|
||||
};
|
||||
inline uint32 op_addr(uint8 mode, uint32 addr);
|
||||
inline uint8 op_read();
|
||||
inline uint8 op_read(uint8 mode, uint32 addr);
|
||||
inline void op_write(uint8 mode, uint32 addr, uint8 value);
|
||||
inline uint8 stack_read();
|
||||
inline void stack_write(uint8 value);
|
||||
|
||||
inline void init_op_tables();
|
||||
|
||||
#include "op.h"
|
||||
File renamed without changes.
@@ -42,13 +42,13 @@ cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
||||
3:stack_write(regs.pc.h);
|
||||
4:stack_write(regs.pc.l);
|
||||
5:stack_write(regs.p);
|
||||
6:rd.l = op_read(OPMODE_LONG, (regs.e)?$1:$3);
|
||||
7:last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e)?$2:$4);
|
||||
6:rd.l = op_read(OPMODE_LONG, (regs.e) ? $1 : $3);
|
||||
regs.pc.b = 0x00;
|
||||
regs.pc.w = rd.w;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
7:last_cycle();
|
||||
rd.h = op_read(OPMODE_LONG, (regs.e) ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
@@ -64,10 +64,16 @@ wai(0xcb) {
|
||||
run_state.wai = true;
|
||||
2:last_cycle();
|
||||
cpu_io();
|
||||
if(run_state.wai) {
|
||||
//this can be cleared within last_cycle()
|
||||
regs.pc.w--;
|
||||
}
|
||||
//no wakeup delay if last_cycle() cancelled wai
|
||||
if(run_state.wai == false)end;
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
//sleep another i/o cycle
|
||||
//note: this should alert the debugger that wai is continuing...
|
||||
if(run_state.wai == true)status.cycle_pos--;
|
||||
//wai wakeup delay (one i/o cycle)
|
||||
4:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
@@ -183,12 +189,8 @@ txs(0x9a) {
|
||||
cpu_io();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
regs.p.n = !!(regs.s.l & 0x80);
|
||||
regs.p.z = (regs.s.l == 0);
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
regs.p.n = !!(regs.s.w & 0x8000);
|
||||
regs.p.z = (regs.s.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -126,7 +126,8 @@ rti(0x40) {
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = stack_read();
|
||||
5:rd.h = stack_read();
|
||||
5:if(regs.e)last_cycle();
|
||||
rd.h = stack_read();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
@@ -1,6 +1,6 @@
|
||||
void bCPU::op_bcc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!!regs.p.c)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.c) {
|
||||
@@ -9,21 +9,21 @@ void bCPU::op_bcc() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bcs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!regs.p.c)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.c) {
|
||||
@@ -32,21 +32,21 @@ void bCPU::op_bcs() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bne() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!!regs.p.z)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.z) {
|
||||
@@ -55,21 +55,21 @@ void bCPU::op_bne() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_beq() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!regs.p.z)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.z) {
|
||||
@@ -78,21 +78,21 @@ void bCPU::op_beq() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bpl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!!regs.p.n)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.n) {
|
||||
@@ -101,21 +101,21 @@ void bCPU::op_bpl() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bmi() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!regs.p.n)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.n) {
|
||||
@@ -124,21 +124,21 @@ void bCPU::op_bmi() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bvc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!!regs.p.v)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(!regs.p.v) {
|
||||
@@ -147,21 +147,21 @@ void bCPU::op_bvc() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bvs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
if(!regs.p.v)last_cycle();
|
||||
rd.l = op_read();
|
||||
if(regs.p.v) {
|
||||
@@ -170,313 +170,314 @@ void bCPU::op_bvs() {
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bra() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
rd.l = op_read();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_brl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
rd.h = op_read();
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
rd.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
rd.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
rd.b = op_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iaddr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iaddrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iladdr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = op_read(OPMODE_ADDR, aa.w);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd.h = op_read(OPMODE_ADDR, aa.w + 1);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
rd.b = op_read(OPMODE_ADDR, aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
regs.pc.w--;
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
stack_write(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
stack_write(regs.pc.b);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
aa.b = op_read();
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
regs.pc.w--;
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
stack_write(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_iaddrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
stack_write(regs.pc.h);
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
stack_write(regs.pc.l);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
rd.l = op_read(OPMODE_PBR, aa.w + regs.x.w);
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
rd.h = op_read(OPMODE_PBR, aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rti() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
regs.p = stack_read();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd.l = stack_read();
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
if(regs.e)last_cycle();
|
||||
rd.h = stack_read();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
rd.b = stack_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rts() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = stack_read();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd.h = stack_read();
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rtl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = stack_read();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
rd.h = stack_read();
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
rd.b = stack_read();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
File renamed without changes.
File diff suppressed because it is too large.
Load diff
File renamed without changes.
File diff suppressed because it is too large.
Load diff
File renamed without changes.
@@ -1,582 +1,582 @@
|
||||
void bCPU::op_sta_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.x.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.x.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.b = op_read();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_longx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
aa.l = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_read();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.b = op_read();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp, regs.x.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, regs.x.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_dpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
aa.b = op_read(OPMODE_DP, dp + 2);
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.l = op_read(OPMODE_DP, dp + regs.x.w);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
aa.h = op_read(OPMODE_DP, dp + regs.x.w + 1);
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
dp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_read(OPMODE_DP, dp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_read(OPMODE_DP, dp + 1);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
aa.b = op_read(OPMODE_DP, dp + 2);
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_sr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_SP, sp, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_SP, sp + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_isry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1:
|
||||
case 1: {
|
||||
sp = op_read();
|
||||
break;
|
||||
case 2:
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 3:
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_read(OPMODE_SP, sp);
|
||||
break;
|
||||
case 4:
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_read(OPMODE_SP, sp + 1);
|
||||
break;
|
||||
case 5:
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_io();
|
||||
break;
|
||||
case 6:
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
break;
|
||||
case 7:
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,75 @@
|
||||
//op_read
|
||||
inline void bCPU::op_adc_b() {
|
||||
int32 r = regs.a.l + rd.l + regs.p.c;
|
||||
//bcd
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r += 6;
|
||||
if(((r >> 4) & 15) > 9)r += 6 << 4;
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||
n0 += ((rd.l) & 15) + regs.p.c;
|
||||
if(n0 > 9) {
|
||||
n0 -= 10;
|
||||
n0 &= 15;
|
||||
n1++;
|
||||
}
|
||||
n1 += ((rd.l >> 4) & 15);
|
||||
if(n1 > 9) {
|
||||
n1 -= 10;
|
||||
n1 &= 15;
|
||||
regs.p.c = 1;
|
||||
} else {
|
||||
regs.p.c = 0;
|
||||
}
|
||||
r = (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.l + rd.l + regs.p.c;
|
||||
regs.p.c = (r > 0xff);
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r > 0xff);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_adc_w() {
|
||||
int32 r = regs.a.w + rd.w + regs.p.c;
|
||||
//bcd
|
||||
int32 r;
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r += 6;
|
||||
if(((r >> 4) & 15) > 9)r += 6 << 4;
|
||||
if(((r >> 8) & 15) > 9)r += 6 << 8;
|
||||
if(((r >> 12) & 15) > 9)r += 6 << 12;
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||
uint8 n2 = (regs.a.w >> 8) & 15;
|
||||
uint8 n3 = (regs.a.w >> 12) & 15;
|
||||
n0 += ((rd.w) & 15) + regs.p.c;
|
||||
if(n0 > 9) {
|
||||
n0 -= 10;
|
||||
n0 &= 15;
|
||||
n1++;
|
||||
}
|
||||
n1 += ((rd.w >> 4) & 15);
|
||||
if(n1 > 9) {
|
||||
n1 -= 10;
|
||||
n1 &= 15;
|
||||
n2++;
|
||||
}
|
||||
n2 += ((rd.w >> 8) & 15);
|
||||
if(n2 > 9) {
|
||||
n2 -= 10;
|
||||
n2 &= 15;
|
||||
n3++;
|
||||
}
|
||||
n3 += ((rd.w >> 12) & 15);
|
||||
if(n3 > 9) {
|
||||
n3 -= 10;
|
||||
n3 &= 15;
|
||||
regs.p.c = 1;
|
||||
} else {
|
||||
regs.p.c = 0;
|
||||
}
|
||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.w + rd.w + regs.p.c;
|
||||
regs.p.c = (r > 0xffff);
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r > 0xffff);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
@@ -156,32 +200,70 @@ inline void bCPU::op_ora_w() {
|
||||
}
|
||||
|
||||
inline void bCPU::op_sbc_b() {
|
||||
int32 r = regs.a.l - rd.l - !regs.p.c;
|
||||
//bcd
|
||||
int32 r;
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r -= 6;
|
||||
if(((r >> 4) & 15) > 9)r -= 6 << 4;
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||
n0 -= ((rd.l ) & 15) + !regs.p.c;
|
||||
n1 -= ((rd.l >> 4) & 15);
|
||||
if(n0 > 9) {
|
||||
n0 += 10;
|
||||
n1--;
|
||||
}
|
||||
if(n1 > 9) {
|
||||
n1 += 10;
|
||||
regs.p.c = 0;
|
||||
} else {
|
||||
regs.p.c = 1;
|
||||
}
|
||||
r = (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.l - rd.l - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((byte)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_sbc_w() {
|
||||
int32 r = regs.a.w - rd.w - !regs.p.c;
|
||||
//bcd
|
||||
int32 r;
|
||||
if(regs.p.d) {
|
||||
if(((r ) & 15) > 9)r -= 6;
|
||||
if(((r >> 4) & 15) > 9)r -= 6 << 4;
|
||||
if(((r >> 8) & 15) > 9)r -= 6 << 8;
|
||||
if(((r >> 12) & 15) > 9)r -= 6 << 12;
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||
uint8 n2 = (regs.a.w >> 8) & 15;
|
||||
uint8 n3 = (regs.a.w >> 12) & 15;
|
||||
n0 -= ((rd.w ) & 15) + !regs.p.c;
|
||||
n1 -= ((rd.w >> 4) & 15);
|
||||
n2 -= ((rd.w >> 8) & 15);
|
||||
n3 -= ((rd.w >> 12) & 15);
|
||||
if(n0 > 9) {
|
||||
n0 += 10;
|
||||
n1--;
|
||||
}
|
||||
if(n1 > 9) {
|
||||
n1 += 10;
|
||||
n2--;
|
||||
}
|
||||
if(n2 > 9) {
|
||||
n2 += 10;
|
||||
n3--;
|
||||
}
|
||||
if(n3 > 9) {
|
||||
n3 += 10;
|
||||
regs.p.c = 0;
|
||||
} else {
|
||||
regs.p.c = 1;
|
||||
}
|
||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.w - rd.w - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((word)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,265 @@
|
||||
/* used by both DMA and HDMA
|
||||
* prevents transfer across same bus (a->a or b->b)
|
||||
*/
|
||||
void bCPU::dma_transfer_byte(bool direction, uint8 bbus, uint32 abus) {
|
||||
uint8 r;
|
||||
if(direction == 0) {
|
||||
//read from address bus a, write to address bus b
|
||||
|
||||
//DMA address bus a cannot read from or write to the following addresses:
|
||||
//$[00-3f|80-bf]:21[00-ff] <address bus b>
|
||||
//$[00-3f|80-bf]:43[00-7f] <DMA control registers>
|
||||
//$[00-3f|80-bf]:420b <DMA enable register>
|
||||
//$[00-3f|80-bf]:420c <HDMA enable register>
|
||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
||||
//these invalid reads will return open bus
|
||||
r = r_cpu->regs.mdr;
|
||||
} else {
|
||||
r = r_mem->read(abus);
|
||||
}
|
||||
|
||||
r_mem->write(0x2100 | bbus, r);
|
||||
} else {
|
||||
//read from address bus b, write to address bus a
|
||||
|
||||
//block invalid writes, see comments above
|
||||
r = (bbus == 0x80) ? r_cpu->regs.mdr : r_mem->read(0x2100 | bbus);
|
||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
|
||||
r_mem->write(abus, r);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_add_cycles(uint32 cycles) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
void bCPU::hdma_add_cycles(uint32 cycles) {
|
||||
if(run_state.dma) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
status.hdma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
uint32 bCPU::dma_addr(uint8 i) {
|
||||
uint32 r;
|
||||
r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||
|
||||
if(channel[i].fixedxfer == false) {
|
||||
channel[i].srcaddr += channel[i].incmode;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::dma_cputommio(uint8 i, uint8 index) {
|
||||
if(sdd1->dma_active() == true) {
|
||||
r_mem->write(0x2100 | ((channel[i].destaddr + index) & 0xff), sdd1->dma_read());
|
||||
} else {
|
||||
dma_transfer_byte(0, ((channel[i].destaddr + index) & 0xff), dma_addr(i));
|
||||
}
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
|
||||
dma_transfer_byte(1, ((channel[i].destaddr + index) & 0xff), dma_addr(i));
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_write(uint8 i, uint8 index) {
|
||||
if(channel[i].direction == 0) {
|
||||
dma_cputommio(i, index);
|
||||
} else {
|
||||
dma_mmiotocpu(i, index);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_run() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].active == false)continue;
|
||||
|
||||
//first byte transferred?
|
||||
if(channel[i].read_index == 0) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
channel[i].xfersize);
|
||||
}
|
||||
|
||||
switch(channel[i].xfermode) {
|
||||
case 0: dma_write(i, 0); break; //0
|
||||
case 1: dma_write(i, channel[i].read_index & 1); break; //0,1
|
||||
case 2: dma_write(i, 0); break; //0,0
|
||||
case 3: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1
|
||||
case 4: dma_write(i, channel[i].read_index & 3); break; //0,1,2,3
|
||||
case 5: dma_write(i, channel[i].read_index & 1); break; //0,1,0,1
|
||||
case 6: dma_write(i, 0); break; //0,0 [2]
|
||||
case 7: dma_write(i, (channel[i].read_index >> 1) & 1); break; //0,0,1,1 [3]
|
||||
}
|
||||
|
||||
channel[i].read_index++;
|
||||
dma_add_cycles(8);
|
||||
|
||||
if(channel[i].xfersize == 0) {
|
||||
channel[i].active = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_addr(uint8 i) {
|
||||
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_iaddr(uint8 i) {
|
||||
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
|
||||
}
|
||||
|
||||
uint16 bCPU::hdma_mmio(uint8 i) {
|
||||
uint8 l = channel[i].read_index;
|
||||
uint16 index;
|
||||
switch(channel[i].xfermode) {
|
||||
case 0: index = 0; break; //0
|
||||
case 1: index = l & 1; break; //0,1
|
||||
case 2: index = 0; break; //0,0
|
||||
case 3: index = (l >> 1) & 1; break; //0,0,1,1
|
||||
case 4: index = l & 3; break; //0,1,2,3
|
||||
case 5: index = l & 1; break; //0,1,0,1
|
||||
case 6: index = 0; break; //0,0 [2]
|
||||
case 7: index = (l >> 1) & 1; break; //0,0,1,1 [3]
|
||||
}
|
||||
|
||||
return (0x2100 | ((channel[i].destaddr + index) & 0xff));
|
||||
}
|
||||
|
||||
void bCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
|
||||
if(channel[i].hdma_line_counter == 0) {
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
return;
|
||||
}
|
||||
|
||||
channel[i].hdma_do_transfer = true;
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_run() {
|
||||
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(!channel[i].hdma_enabled || !channel[i].hdma_active)continue;
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
for(channel[i].read_index = 0; channel[i].read_index < xferlen; channel[i].read_index++) {
|
||||
if(bool(config::cpu.hdma_enable) == true) {
|
||||
dma_transfer_byte(channel[i].direction, hdma_mmio(i),
|
||||
channel[i].hdma_indirect ? hdma_iaddr(i) : hdma_addr(i));
|
||||
}
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
}
|
||||
|
||||
channel[i].hdma_line_counter--;
|
||||
channel[i].hdma_do_transfer = bool(channel[i].hdma_line_counter & 0x80);
|
||||
if((channel[i].hdma_line_counter & 0x7f) == 0) {
|
||||
hdma_update(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_enabled_channels() {
|
||||
int r = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].hdma_enabled)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_active_channels() {
|
||||
int r = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].hdma_enabled && channel[i].hdma_active)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* hdmainit_activate()
|
||||
* hdma_activate()
|
||||
*
|
||||
* Functions are called by CPU timing routine
|
||||
* when an HDMA event (init or run) occurs.
|
||||
*/
|
||||
|
||||
void bCPU::hdmainit_activate() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
|
||||
if(hdma_enabled_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_IDMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_activate() {
|
||||
if(hdma_active_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_DMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_reset() {
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
status.hdma_state = HDMASTATE_CPUSYNC;
|
||||
status.dma_cycle_count = 0;
|
||||
status.hdma_cycle_count = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].read_index = 0;
|
||||
channel[i].active = false;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].dmap = 0xff;
|
||||
channel[i].direction = 1;
|
||||
channel[i].hdma_indirect = 1;
|
||||
channel[i].incmode = -1;
|
||||
channel[i].fixedxfer = 1;
|
||||
channel[i].xfermode = 7;
|
||||
channel[i].destaddr = 0xff;
|
||||
channel[i].srcaddr = 0xffff;
|
||||
channel[i].srcbank = 0xff;
|
||||
channel[i].xfersize = 0xffff;
|
||||
//xfersize and hdma_iaddr are of union { uint16 };
|
||||
//channel[i].hdma_iaddr = 0xffff;
|
||||
channel[i].hdma_ibank = 0xff;
|
||||
channel[i].hdma_addr = 0xffff;
|
||||
channel[i].hdma_line_counter = 0xff;
|
||||
channel[i].hdma_unknown = 0xff;
|
||||
|
||||
channel[i].hdma_active = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
struct {
|
||||
uint32 read_index; //set to 0 at beginning of DMA/HDMA
|
||||
|
||||
//$420b
|
||||
bool active;
|
||||
//$420c
|
||||
bool hdma_enabled;
|
||||
//$43x0
|
||||
uint8 dmap;
|
||||
bool direction;
|
||||
bool hdma_indirect;
|
||||
int8 incmode;
|
||||
bool fixedxfer;
|
||||
uint8 xfermode;
|
||||
//$43x1
|
||||
uint8 destaddr;
|
||||
//$43x2-$43x3
|
||||
uint16 srcaddr;
|
||||
//$43x4
|
||||
uint8 srcbank;
|
||||
//$43x5-$43x6
|
||||
union {
|
||||
uint16 xfersize;
|
||||
uint16 hdma_iaddr;
|
||||
};
|
||||
//$43x7
|
||||
uint8 hdma_ibank;
|
||||
//$43x8-$43x9
|
||||
uint16 hdma_addr;
|
||||
//$43xa
|
||||
uint8 hdma_line_counter;
|
||||
//$43xb/$43xf
|
||||
uint8 hdma_unknown;
|
||||
|
||||
//hdma-specific
|
||||
bool hdma_active;
|
||||
bool hdma_do_transfer;
|
||||
|
||||
uint8 hdma_current_channel;
|
||||
uint8 hdma_current_pos;
|
||||
} channel[8];
|
||||
|
||||
inline void dma_transfer_byte(bool direction, uint8 bbus, uint32 abus);
|
||||
inline void dma_add_cycles(uint32 cycles);
|
||||
inline void hdma_add_cycles(uint32 cycles);
|
||||
inline void dma_run();
|
||||
inline void hdma_run();
|
||||
inline void hdma_update(uint8 i);
|
||||
inline uint8 hdma_enabled_channels();
|
||||
inline uint8 hdma_active_channels();
|
||||
inline void hdmainit_activate();
|
||||
inline void hdma_activate();
|
||||
inline void dma_cputommio(uint8 i, uint8 index);
|
||||
inline void dma_mmiotocpu(uint8 i, uint8 index);
|
||||
inline void dma_write(uint8 i, uint8 index);
|
||||
inline uint32 dma_addr(uint8 i);
|
||||
inline uint32 hdma_addr(uint8 i);
|
||||
inline uint32 hdma_iaddr(uint8 i);
|
||||
inline uint16 hdma_mmio(uint8 i);
|
||||
inline void dma_reset();
|
||||
@@ -0,0 +1,40 @@
|
||||
uint8 bCPU::port_read(uint8 port) {
|
||||
return apu_port[port & 3];
|
||||
}
|
||||
|
||||
void bCPU::port_write(uint8 port, uint8 value) {
|
||||
apu_port[port & 3] = value;
|
||||
}
|
||||
|
||||
/* The next 3 functions control bus timing for the CPU.
|
||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||
* mem_read / mem_write indicate memory access bus cycle,
|
||||
* they are either 6, 8, or 12 bus cycles long, depending
|
||||
* both on location and the $420d.d0 FastROM enable bit.
|
||||
*/
|
||||
|
||||
void bCPU::cpu_io() {
|
||||
status.cycle_count = 6;
|
||||
pre_exec_cycle();
|
||||
add_cycles(6);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
uint8 bCPU::mem_read(uint32 addr) {
|
||||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count - 4);
|
||||
regs.mdr = r_mem->read(addr);
|
||||
add_cycles(4);
|
||||
cycle_edge();
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void bCPU::mem_write(uint32 addr, uint8 value) {
|
||||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count);
|
||||
regs.mdr = value;
|
||||
r_mem->write(addr, value);
|
||||
cycle_edge();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
uint8 apu_port[4];
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
inline void cpu_io();
|
||||
inline uint8 mem_read(uint32 addr);
|
||||
inline void mem_write(uint32 addr, uint8 value);
|
||||
@@ -200,7 +200,7 @@ void bCPU::inc_vcounter() {
|
||||
time.v = 0;
|
||||
time.interlace_field ^= 1;
|
||||
|
||||
if(time.interlace == true && time.interlace_field == 0) {
|
||||
if(interlace() == true && interlace_field() == 0) {
|
||||
time.frame_lines = time.region_scanlines + 1;
|
||||
} else {
|
||||
time.frame_lines = time.region_scanlines;
|
||||
@@ -319,8 +319,8 @@ void bCPU::time_reset() {
|
||||
time.hc = 0;
|
||||
|
||||
//upon SNES reset, start at scanline 0 non-interlace
|
||||
time.interlace = false;
|
||||
time.interlace_field = false;
|
||||
time.interlace = 0;
|
||||
time.interlace_field = 0;
|
||||
time.overscan = false;
|
||||
time.line_cycles = 1364;
|
||||
|
||||
@@ -46,29 +46,29 @@ struct {
|
||||
int32 irq_read_trigger_pos, irq_line_trigger_pos;
|
||||
} time;
|
||||
|
||||
inline uint16 vcounter();
|
||||
inline uint16 hcounter();
|
||||
inline uint16 hcycles();
|
||||
inline bool interlace();
|
||||
inline bool interlace_field();
|
||||
inline bool overscan();
|
||||
inline uint16 region_scanlines();
|
||||
inline uint16 vcounter();
|
||||
inline uint16 hcounter();
|
||||
inline uint16 hcycles();
|
||||
inline bool interlace();
|
||||
inline bool interlace_field();
|
||||
inline bool overscan();
|
||||
inline uint16 region_scanlines();
|
||||
|
||||
inline bool nmi_trigger_pos_match(uint32 offset);
|
||||
inline bool irq_trigger_pos_match(uint32 offset);
|
||||
inline bool nmi_trigger_pos_match(uint32 offset);
|
||||
inline bool irq_trigger_pos_match(uint32 offset);
|
||||
|
||||
inline void update_nmi();
|
||||
inline void update_irq();
|
||||
inline void update_interrupts();
|
||||
inline void poll_interrupts(int cycles);
|
||||
inline void update_nmi();
|
||||
inline void update_irq();
|
||||
inline void update_interrupts();
|
||||
inline void poll_interrupts(int cycles);
|
||||
|
||||
inline void set_interlace(bool r);
|
||||
inline void set_overscan (bool r);
|
||||
inline void set_interlace(bool r);
|
||||
inline void set_overscan (bool r);
|
||||
|
||||
inline uint8 dma_counter();
|
||||
inline uint8 dma_counter();
|
||||
|
||||
inline void inc_vcounter();
|
||||
inline uint16 get_hcounter();
|
||||
inline void cycle_edge();
|
||||
inline void add_cycles(int cycles);
|
||||
inline void time_reset();
|
||||
inline void inc_vcounter();
|
||||
inline uint16 get_hcounter();
|
||||
inline void cycle_edge();
|
||||
inline void add_cycles(int cycles);
|
||||
inline void time_reset();
|
||||
@@ -3,5 +3,4 @@
|
||||
|
||||
CPU::CPU() {
|
||||
cpu_version = 1;
|
||||
mmio = &mmio_unmapped;
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
#include "cpuregs.h"
|
||||
|
||||
class CPU {
|
||||
class CPU : public MMIO {
|
||||
public:
|
||||
//CPU version number
|
||||
//* 1 and 2 are known
|
||||
@@ -12,14 +12,13 @@ uint8 cpu_version;
|
||||
virtual uint16 vcounter() = 0;
|
||||
virtual uint16 hcounter() = 0;
|
||||
virtual uint16 hcycles() = 0;
|
||||
virtual bool overscan() = 0;
|
||||
virtual bool interlace() = 0;
|
||||
virtual bool interlace_field() = 0;
|
||||
virtual bool overscan() = 0;
|
||||
virtual uint16 region_scanlines() = 0;
|
||||
virtual void set_interlace(bool r) = 0;
|
||||
virtual void set_overscan (bool r) = 0;
|
||||
|
||||
MMIO *mmio;
|
||||
CPURegs regs;
|
||||
virtual uint8 port_read (uint8 port) = 0;
|
||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||
@@ -70,4 +69,5 @@ enum {
|
||||
uint16 __relw(int16 offset);
|
||||
|
||||
CPU();
|
||||
virtual ~CPU() {}
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 281 KiB |
File renamed without changes.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
+62
-37
@@ -1,10 +1,22 @@
|
||||
#include "../../base.h"
|
||||
#include "bdsp_tables.cpp"
|
||||
|
||||
uint8 bDSP::read_8 (uint16 addr) { return (spcram[addr]); }
|
||||
uint16 bDSP::read_16 (uint16 addr) { return (spcram[(addr + 1) & 0xffff] << 8) + (spcram[addr]); }
|
||||
void bDSP::write_8 (uint16 addr, uint8 data) { spcram[addr] = data; }
|
||||
void bDSP::write_16(uint16 addr, uint16 data) { spcram[addr++] = data; spcram[addr] = data >> 8; }
|
||||
uint8 bDSP::readb(uint16 addr) {
|
||||
return spcram[addr];
|
||||
}
|
||||
|
||||
void bDSP::writeb(uint16 addr, uint8 data) {
|
||||
spcram[addr] = data;
|
||||
}
|
||||
|
||||
uint16 bDSP::readw(uint16 addr) {
|
||||
return (readb(addr)) | (readb(addr + 1) << 8);
|
||||
}
|
||||
|
||||
void bDSP::writew(uint16 addr, uint16 data) {
|
||||
writeb(addr, data);
|
||||
writeb(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
uint8 bDSP::read(uint8 addr) {
|
||||
int i, v, n;
|
||||
@@ -98,12 +110,14 @@ int i, v, n;
|
||||
break;
|
||||
case 0x04:case 0x14:case 0x24:case 0x34:
|
||||
case 0x44:case 0x54:case 0x64:case 0x74:
|
||||
//voice[v].SRCN = data;
|
||||
voice[v].SRCN = data;
|
||||
break;
|
||||
//below is anomie's code, but TRAC says writing SRCN doesn't affect anything until a
|
||||
//BRR-with-end block is encountered, where it loads the loop address from the new SRCN
|
||||
//anomie's code breaks MK2 sound completely...
|
||||
if(voice[v].SRCN != data) {
|
||||
voice[v].SRCN = data;
|
||||
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped)?2:0));
|
||||
voice[v].SRCN = data;
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped) ? 2 : 0));
|
||||
voice[v].brr_index = 0;
|
||||
}
|
||||
break;
|
||||
@@ -144,18 +158,18 @@ int i, v, n;
|
||||
case 0x3c:status.EVOLR = data;break;
|
||||
|
||||
case 0x4c:
|
||||
status.KON = data;
|
||||
// status.kon = data;
|
||||
status.KON = data;
|
||||
status.kon = data;
|
||||
status.key_flag = true;
|
||||
break;
|
||||
|
||||
case 0x5c:
|
||||
status.KOFF = data;
|
||||
status.KOFF = data;
|
||||
status.key_flag = true;
|
||||
break;
|
||||
|
||||
case 0x6c:
|
||||
status.FLG = data;
|
||||
status.FLG = data;
|
||||
status.key_flag = true;
|
||||
status.noise_rate = RateTable[data & 0x1f];
|
||||
break;
|
||||
@@ -165,15 +179,15 @@ int i, v, n;
|
||||
status.ENDX = 0;
|
||||
break;
|
||||
|
||||
case 0x0d:status.EFB = data;break;
|
||||
case 0x2d:status.PMON = data;break;
|
||||
case 0x3d:status.NON = data;break;
|
||||
case 0x4d:status.EON = data;break;
|
||||
case 0x5d:status.DIR = data;break;
|
||||
case 0x6d:status.ESA = data;break;
|
||||
case 0x0d:status.EFB = data;break;
|
||||
case 0x2d:status.PMON = data;break;
|
||||
case 0x3d:status.NON = data;break;
|
||||
case 0x4d:status.EON = data;break;
|
||||
case 0x5d:status.DIR = data;break;
|
||||
case 0x6d:status.ESA = data;break;
|
||||
|
||||
case 0x7d:
|
||||
status.EDL = data;
|
||||
status.EDL = data;
|
||||
status.echo_size = (data & 0x0f) << 11;
|
||||
break;
|
||||
}
|
||||
@@ -221,7 +235,7 @@ int v;
|
||||
status.KOFF = 0x00;
|
||||
status.FLG |= 0xe0;
|
||||
|
||||
//status.kon = 0x00;
|
||||
status.kon = 0x00;
|
||||
status.key_flag = false;
|
||||
|
||||
status.noise_ctr = 0;
|
||||
@@ -238,7 +252,7 @@ int v;
|
||||
voice[v].pitch_ctr = 0;
|
||||
|
||||
voice[v].brr_index = 0;
|
||||
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2));
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2));
|
||||
voice[v].brr_looped = false;
|
||||
voice[v].brr_data[0] = 0;
|
||||
voice[v].brr_data[1] = 0;
|
||||
@@ -288,7 +302,9 @@ int32 esamplel, esampler;
|
||||
int32 fir_samplel, fir_sampler;
|
||||
pmon = status.PMON & ~status.NON & ~1;
|
||||
|
||||
if(!(dsp_counter++ & 1) && status.key_flag) {
|
||||
//if(!(dsp_counter++ & 1) && status.key_flag) {
|
||||
//TRAC believes KON/KOFF is polled every sample. further testing is needed
|
||||
if(status.key_flag) {
|
||||
for(v=0;v<8;v++) {
|
||||
uint8 mask = 1 << v;
|
||||
if(status.soft_reset()) {
|
||||
@@ -301,10 +317,12 @@ int32 fir_samplel, fir_sampler;
|
||||
voice[v].env_state = RELEASE;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
} else if(status.KON & mask) { //status.kon
|
||||
status.KON &= ~mask; //new code
|
||||
status.ENDX &= ~mask; //new code
|
||||
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2));
|
||||
} else if(status.kon & mask) {
|
||||
//new KON code
|
||||
status.ENDX &= ~mask;
|
||||
status.kon &= ~mask;
|
||||
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2));
|
||||
voice[v].brr_index = -9;
|
||||
voice[v].brr_looped = false;
|
||||
voice[v].brr_data[0] = 0;
|
||||
@@ -316,7 +334,8 @@ int32 fir_samplel, fir_sampler;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
}
|
||||
// status.ENDX &= ~status.kon;
|
||||
//old KON code, breaks sound effects in DL / SFA2
|
||||
// status.ENDX &= ~status.kon;
|
||||
// status.kon = 0;
|
||||
status.key_flag = false;
|
||||
}
|
||||
@@ -359,13 +378,15 @@ int32 fir_samplel, fir_sampler;
|
||||
voice[v].brr_data_index &= 3;
|
||||
|
||||
if(voice[v].brr_index == 0) {
|
||||
voice[v].brr_header = read_8(voice[v].brr_ptr);
|
||||
voice[v].brr_header = readb(voice[v].brr_ptr);
|
||||
|
||||
if(voice[v].brr_header_flags() & BRR_END) {
|
||||
status.ENDX |= (1 << v);
|
||||
}
|
||||
//moving status.ENDX bit set into == BRR_END condition per DMV27
|
||||
//if(voice[v].brr_header_flags() & BRR_END) {
|
||||
// status.ENDX |= (1 << v);
|
||||
//}
|
||||
|
||||
if(voice[v].brr_header_flags() == BRR_END) {
|
||||
status.ENDX |= (1 << v);
|
||||
voice[v].env_state = SILENCE;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
@@ -373,7 +394,7 @@ int32 fir_samplel, fir_sampler;
|
||||
|
||||
#define S(x) voice[v].brr_data[(voice[v].brr_data_index + (x)) & 3]
|
||||
if(voice[v].env_state != SILENCE) {
|
||||
sample = read_8(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
|
||||
sample = readb(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
|
||||
if(voice[v].brr_index & 1) {
|
||||
sample = clip(4, sample);
|
||||
} else {
|
||||
@@ -410,7 +431,11 @@ int32 fir_samplel, fir_sampler;
|
||||
if(++voice[v].brr_index > 15) {
|
||||
voice[v].brr_index = 0;
|
||||
if(voice[v].brr_header_flags() & BRR_END) {
|
||||
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2) + 2);
|
||||
//below condition added by DMV27
|
||||
if(voice[v].brr_header_flags() & BRR_LOOP) {
|
||||
status.ENDX |= (1 << v);
|
||||
}
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + 2);
|
||||
voice[v].brr_looped = true;
|
||||
} else {
|
||||
voice[v].brr_ptr += 9;
|
||||
@@ -496,7 +521,7 @@ int32 fir_samplel, fir_sampler;
|
||||
|
||||
//gaussian interpolation / noise
|
||||
if(status.NON & (1 << v)) {
|
||||
sample = status.noise_sample;
|
||||
sample = clip(15, status.noise_sample);
|
||||
} else {
|
||||
d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1
|
||||
sample = ((GaussTable[ -1-d] * S(-3)) >> 11);
|
||||
@@ -527,8 +552,8 @@ int32 fir_samplel, fir_sampler;
|
||||
//echo (FIR) adjust
|
||||
#define F(c,x) status.fir_buffer[c][(status.fir_buffer_index+(x)) & 7]
|
||||
status.fir_buffer_index++;
|
||||
F(0,0) = read_16((status.ESA << 8) + status.echo_index);
|
||||
F(1,0) = read_16((status.ESA << 8) + status.echo_index + 2);
|
||||
F(0,0) = readw((status.ESA << 8) + status.echo_index);
|
||||
F(1,0) = readw((status.ESA << 8) + status.echo_index + 2);
|
||||
|
||||
fir_samplel = (F(0,-0) * status.FIR[7] +
|
||||
F(0,-1) * status.FIR[6] +
|
||||
@@ -557,8 +582,8 @@ int32 fir_samplel, fir_sampler;
|
||||
esamplel = clamp(16, esamplel);
|
||||
esampler = clamp(16, esampler);
|
||||
|
||||
write_16((status.ESA << 8) + status.echo_index, esamplel);
|
||||
write_16((status.ESA << 8) + status.echo_index + 2, esampler);
|
||||
writew((status.ESA << 8) + status.echo_index, esamplel);
|
||||
writew((status.ESA << 8) + status.echo_index + 2, esampler);
|
||||
}
|
||||
|
||||
status.echo_index += 4;
|
||||
|
||||
+5
-5
@@ -10,10 +10,10 @@ enum {
|
||||
BRR_LOOP = 2
|
||||
};
|
||||
|
||||
uint8 read_8 (uint16 addr);
|
||||
uint16 read_16 (uint16 addr);
|
||||
void write_8 (uint16 addr, uint8 data);
|
||||
void write_16(uint16 addr, uint16 data);
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
|
||||
public:
|
||||
static const uint16 RateTable[32];
|
||||
@@ -63,7 +63,7 @@ struct Status {
|
||||
int8 FIR[8];
|
||||
|
||||
//internal variables
|
||||
//uint8 kon;
|
||||
uint8 kon;
|
||||
bool key_flag;
|
||||
|
||||
int16 noise_ctr, noise_rate;
|
||||
|
||||
@@ -6,4 +6,7 @@ public:
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual uint32 run() = 0;
|
||||
|
||||
DSP() {}
|
||||
virtual ~DSP() {}
|
||||
};
|
||||
+23
-13
@@ -1,6 +1,3 @@
|
||||
#define BSNES_VERSION "0.014"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#ifdef POLYMORPHISM
|
||||
#define ref(x) x
|
||||
#else
|
||||
@@ -15,6 +12,8 @@
|
||||
#define r_ppu ref(deref(ppu))
|
||||
|
||||
#include "reader/reader.h"
|
||||
#include "cart/cart.h"
|
||||
#include "cheat/cheat.h"
|
||||
|
||||
#include "memory/memory.h"
|
||||
#include "memory/bmemory/bmemory.h"
|
||||
@@ -35,6 +34,9 @@
|
||||
|
||||
#include "chip/srtc/srtc.h"
|
||||
#include "chip/sdd1/sdd1.h"
|
||||
#include "chip/c4/c4.h"
|
||||
#include "chip/dsp2/dsp2.h"
|
||||
#include "chip/obc1/obc1.h"
|
||||
|
||||
extern MMIO mmio_unmapped;
|
||||
#ifdef POLYMORPHISM
|
||||
@@ -44,20 +46,25 @@ extern MMIO mmio_unmapped;
|
||||
extern DSP *deref(dsp);
|
||||
extern PPU *deref(ppu);
|
||||
#else
|
||||
extern bMemBus deref(mem);
|
||||
extern bCPU deref(cpu);
|
||||
extern bAPU deref(apu);
|
||||
extern bDSP deref(dsp);
|
||||
extern bPPU deref(ppu);
|
||||
extern MEMCORE deref(mem);
|
||||
extern CPUCORE deref(cpu);
|
||||
extern APUCORE deref(apu);
|
||||
extern DSPCORE deref(dsp);
|
||||
extern PPUCORE deref(ppu);
|
||||
#endif
|
||||
extern SNES *snes;
|
||||
|
||||
extern SRTC *srtc;
|
||||
extern SDD1 *sdd1;
|
||||
extern C4 *c4;
|
||||
extern DSP2 *dsp2;
|
||||
extern OBC1 *obc1;
|
||||
|
||||
#include "config/config.h"
|
||||
|
||||
#ifdef INTERFACE_MAIN
|
||||
Cartridge cartridge;
|
||||
Cheat cheat;
|
||||
|
||||
#include "config/config.cpp"
|
||||
#ifdef POLYMORPHISM
|
||||
@@ -67,15 +74,18 @@ extern SDD1 *sdd1;
|
||||
DSP *deref(dsp);
|
||||
PPU *deref(ppu);
|
||||
#else
|
||||
bMemBus deref(mem);
|
||||
bCPU deref(cpu);
|
||||
bAPU deref(apu);
|
||||
bDSP deref(dsp);
|
||||
bPPU deref(ppu);
|
||||
MEMCORE deref(mem);
|
||||
CPUCORE deref(cpu);
|
||||
APUCORE deref(apu);
|
||||
DSPCORE deref(dsp);
|
||||
PPUCORE deref(ppu);
|
||||
#endif
|
||||
SNES *snes;
|
||||
|
||||
SRTC *srtc;
|
||||
SDD1 *sdd1;
|
||||
C4 *c4;
|
||||
DSP2 *dsp2;
|
||||
OBC1 *obc1;
|
||||
|
||||
#endif
|
||||
+114
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libbase : version 0.03 ~byuu (08/20/05)
|
||||
libbase : version 0.07 ~byuu (04/21/06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBBASE
|
||||
@@ -9,35 +9,124 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define zerofree(__n) if(__n) { free(__n); __n = 0; }
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned long ulong;
|
||||
|
||||
typedef unsigned char bool8;
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned long uint32;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef signed short int16;
|
||||
typedef signed long int32;
|
||||
|
||||
#ifdef null
|
||||
#undef null
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#define null 0xffffffff
|
||||
|
||||
#define SafeFree(__n) if(__n) { free(__n); __n = 0; }
|
||||
#define SafeDelete(__n) if(__n) { delete(__n); __n = 0; }
|
||||
#define SafeRelease(__n) if(__n) { __n->Release(); __n = 0; }
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned long long uquad;
|
||||
|
||||
typedef unsigned char bool8;
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned long uint32;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef signed short int16;
|
||||
typedef signed long int32;
|
||||
typedef signed long long int64;
|
||||
|
||||
template<typename T> void swap(T &x, T &y) {
|
||||
T z = x;
|
||||
x = y;
|
||||
y = z;
|
||||
}
|
||||
|
||||
template<typename T, typename Targ> T bound_range(T &x, Targ min, Targ max) {
|
||||
return (x < T(min)) ? T(min) : (x > T(max)) ? T(max) : x;
|
||||
}
|
||||
|
||||
inline bool fexists(const char *fn) {
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
if(!fp)return false;
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline uint32 fsize(FILE *fp) {
|
||||
if(!fp)return 0;
|
||||
uint32 pos = ftell(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
uint32 size = ftell(fp);
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
return size;
|
||||
}
|
||||
|
||||
inline uint32 fsize(const char *fn) {
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
if(!fp)return 0;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
uint32 size = ftell(fp);
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
const uint32 crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
inline uint32 crc32_adjust(uint32 crc32, uint32 input) {
|
||||
return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff];
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,625 @@
|
||||
#include "libbase.h"
|
||||
#include "libvector.h"
|
||||
#include "libbpf.h"
|
||||
|
||||
void BPF::Handle::seek(uint32 new_pos) {
|
||||
if(pos == new_pos)return;
|
||||
pos = new_pos;
|
||||
if(mode == MODE_FILE) {
|
||||
fseek(handle, new_pos, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
void BPF::Handle::write(uint8 x) {
|
||||
if(mode == MODE_MEMORY) {
|
||||
data[pos] = x;
|
||||
} else {
|
||||
fputc(x, handle);
|
||||
}
|
||||
|
||||
if(++pos > size)size = pos;
|
||||
crc32 = crc32_adjust(crc32, x);
|
||||
}
|
||||
|
||||
uint8 BPF::Handle::read() {
|
||||
uint8 r;
|
||||
if(pos >= size) {
|
||||
return 0x00;
|
||||
} else if(mode == MODE_MEMORY) {
|
||||
r = data[pos];
|
||||
} else {
|
||||
r = fgetc(handle);
|
||||
}
|
||||
|
||||
pos++;
|
||||
crc32 = crc32_adjust(crc32, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32 BPF::Handle::calc_crc32() {
|
||||
crc32 = 0xffffffff;
|
||||
seek(0);
|
||||
for(uint32 i = 0; i < size; i++) {
|
||||
read();
|
||||
}
|
||||
seek(0);
|
||||
crc32 = ~crc32;
|
||||
return crc32;
|
||||
}
|
||||
|
||||
bool BPF::Handle::open(uint8 _access, uint32 _size, uint8 *_data) {
|
||||
close();
|
||||
|
||||
mode = MODE_MEMORY;
|
||||
access = _access;
|
||||
pos = 0;
|
||||
size = _size;
|
||||
crc32 = 0xffffffff;
|
||||
|
||||
if(access == ACCESS_READ) {
|
||||
data.resize(_size);
|
||||
data.copy(_data, _size);
|
||||
} else {
|
||||
data.resize(_size);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BPF::Handle::open(uint8 _access, const char *fn) {
|
||||
close();
|
||||
|
||||
mode = MODE_FILE;
|
||||
access = _access;
|
||||
pos = 0;
|
||||
crc32 = 0xffffffff;
|
||||
|
||||
if(access == ACCESS_READ) {
|
||||
handle = fopen(fn, "rb");
|
||||
if(!handle)return false;
|
||||
size = fsize(handle);
|
||||
} else if(access == ACCESS_WRITE) {
|
||||
handle = fopen(fn, "wb");
|
||||
if(!handle)return false;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BPF::Handle::load(const char *fn) {
|
||||
close();
|
||||
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
if(!fp)return false;
|
||||
size = fsize(fp);
|
||||
uint8 *buffer = (uint8*)malloc(size);
|
||||
memset(buffer, 0, size);
|
||||
fread(buffer, 1, size, fp);
|
||||
fclose(fp);
|
||||
return open(ACCESS_READ, size, buffer);
|
||||
}
|
||||
|
||||
bool BPF::Handle::save(const char *fn) {
|
||||
if(mode != MODE_MEMORY)return false;
|
||||
|
||||
FILE *fp = fopen(fn, "wb");
|
||||
if(!fp)return false;
|
||||
fwrite(data.handle(), 1, size, fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BPF::Handle::close() {
|
||||
if(mode == MODE_MEMORY) {
|
||||
data.release();
|
||||
} else if(mode == MODE_FILE) {
|
||||
if(handle) {
|
||||
fclose(handle);
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 *BPF::load(const char *fn, uint32 &size) {
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
if(!fp)return 0;
|
||||
size = fsize(fp);
|
||||
uint8 *buffer = (uint8*)malloc(size);
|
||||
fread(buffer, 1, size, fp);
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void BPF::save(const char *fn, uint8 *data, uint32 size) {
|
||||
FILE *fp = fopen(fn, "wb");
|
||||
if(!fp)return;
|
||||
fwrite(data, 1, size, fp);
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
}
|
||||
|
||||
void BPF::write_ptr(uint32 ptr) {
|
||||
if(ptr <= 0xef) {
|
||||
patch.write(ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr -= 0xf0;
|
||||
if(ptr <= 0xffff) {
|
||||
patch.write(0xf0);
|
||||
patch.write(ptr);
|
||||
patch.write(ptr >> 8);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr -= 0x10000;
|
||||
if(ptr <= 0xffffff) {
|
||||
patch.write(0xf1);
|
||||
patch.write(ptr);
|
||||
patch.write(ptr >> 8);
|
||||
patch.write(ptr >> 16);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr -= 0x1000000;
|
||||
patch.write(0xf2);
|
||||
patch.write(ptr);
|
||||
patch.write(ptr >> 8);
|
||||
patch.write(ptr >> 16);
|
||||
patch.write(ptr >> 24);
|
||||
}
|
||||
|
||||
uint32 BPF::read_ptr() {
|
||||
uint32 len = patch.read();
|
||||
if(len <= 0xef) {
|
||||
return len;
|
||||
}
|
||||
|
||||
len &= 0x0f;
|
||||
uint32 ptr = 0;
|
||||
for(int i = 0; i < (len + 2); i++) {
|
||||
ptr |= patch.read() << (i << 3);
|
||||
}
|
||||
|
||||
ptr += 0xf0;
|
||||
if(len >= 1)ptr += 0x10000;
|
||||
if(len >= 2)ptr += 0x1000000;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void BPF::create_patch_binary() {
|
||||
original.seek(0);
|
||||
modified.seek(0);
|
||||
|
||||
uint32 last_ptr = 0, rle_count, last_out, rep_count;
|
||||
for(uint32 i = 0; i < info.size_max;) {
|
||||
uint8 r = original.read() ^ modified.read();
|
||||
i++;
|
||||
if(r == 0x00)continue;
|
||||
|
||||
//ptr
|
||||
write_ptr((i - 1) - last_ptr);
|
||||
|
||||
//data
|
||||
patch.write(r);
|
||||
last_out = r;
|
||||
rep_count = 0;
|
||||
do {
|
||||
r = original.read() ^ modified.read();
|
||||
i++;
|
||||
patch.write(r);
|
||||
if(last_out == r) {
|
||||
if(++rep_count == 2) {
|
||||
rle_count = 0;
|
||||
do {
|
||||
r = original.read() ^ modified.read();
|
||||
i++;
|
||||
if(r != last_out || r == 0x00)break;
|
||||
rle_count++;
|
||||
} while(i < info.size_max);
|
||||
write_ptr(rle_count);
|
||||
if(i < info.size_max)patch.write(r);
|
||||
rep_count = 0;
|
||||
}
|
||||
} else {
|
||||
rep_count = 0;
|
||||
}
|
||||
|
||||
last_out = r;
|
||||
if(r == 0x00)break;
|
||||
} while(i < info.size_max);
|
||||
|
||||
last_ptr = i;
|
||||
}
|
||||
}
|
||||
|
||||
bool BPF::create_patch(uint32 format, const char *fn) {
|
||||
patch.open(ACCESS_WRITE, fn);
|
||||
|
||||
//header
|
||||
patch.write('b');
|
||||
patch.write('p');
|
||||
patch.write('f');
|
||||
patch.write(0x00);
|
||||
|
||||
//version (high-byte = major, low-byte = minor)
|
||||
patch.write(0x00);
|
||||
patch.write(0x01);
|
||||
|
||||
//bytes per pointer
|
||||
info.size_max = (original.size >= modified.size) ? original.size : modified.size;
|
||||
info.size_min = (original.size >= modified.size) ? modified.size : original.size;
|
||||
|
||||
if(info.size_max <= 0xff) {
|
||||
info.ptr_size = 1;
|
||||
} else if(info.size_max <= 0xffff) {
|
||||
info.ptr_size = 2;
|
||||
} else if(info.size_max <= 0xffffff) {
|
||||
info.ptr_size = 3;
|
||||
} else {
|
||||
info.ptr_size = 4;
|
||||
}
|
||||
patch.write(info.ptr_size);
|
||||
patch.write(info.ptr_size >> 8);
|
||||
|
||||
//format
|
||||
patch.write(format);
|
||||
patch.write(format >> 8);
|
||||
patch.write(format >> 16);
|
||||
patch.write(format >> 24);
|
||||
|
||||
//flags
|
||||
uint32 flags = 0;
|
||||
patch.write(flags);
|
||||
patch.write(flags >> 8);
|
||||
patch.write(flags >> 16);
|
||||
patch.write(flags >> 24);
|
||||
|
||||
//original size
|
||||
for(int i = 0; i < info.ptr_size; i++) {
|
||||
patch.write(original.size >> (i << 3));
|
||||
}
|
||||
|
||||
//modified size
|
||||
for(int i = 0; i < info.ptr_size; i++) {
|
||||
patch.write(modified.size >> (i << 3));
|
||||
}
|
||||
|
||||
//patch data offset (currently unused)
|
||||
uint32 pos = patch.pos + 4;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
patch.write(pos >> (i << 3));
|
||||
}
|
||||
|
||||
create_patch_binary();
|
||||
|
||||
//write crc32 of original file
|
||||
for(int i = 0; i < 4; i++) {
|
||||
patch.write(~original.crc32 >> (i << 3));
|
||||
}
|
||||
|
||||
//write crc32 of modified file
|
||||
for(int i = 0; i < 4; i++) {
|
||||
patch.write(~modified.crc32 >> (i << 3));
|
||||
}
|
||||
|
||||
uint32 patch_crc32 = patch.crc32;
|
||||
//write crc32 of patch file
|
||||
for(int i = 0; i < 4; i++) {
|
||||
patch.write(~patch_crc32 >> (i << 3));
|
||||
}
|
||||
|
||||
patch.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void BPF::apply_patch_binary() {
|
||||
//copy old data info output buffer
|
||||
output.seek(0);
|
||||
input.seek(0);
|
||||
for(uint32 z = 0; z < output.size; z++) {
|
||||
output.write(input.read());
|
||||
}
|
||||
|
||||
output.seek(0);
|
||||
input.seek(0);
|
||||
patch.seek(info.patch_start);
|
||||
//the below routine may modify output.size if the input
|
||||
//size is larger, so save the correct output size...
|
||||
uint32 start_size = output.size;
|
||||
|
||||
//subtract 12 to ignore crc32 for original, modified, and patch files
|
||||
uint32 rle_count, last_in, rep_count;
|
||||
for(; patch.pos < (patch.size - 12);) {
|
||||
//ptr
|
||||
uint32 ptr = read_ptr();
|
||||
|
||||
//data
|
||||
output.seek(output.pos + ptr);
|
||||
input.seek(input.pos + ptr);
|
||||
|
||||
last_in = 0;
|
||||
rep_count = 0;
|
||||
do {
|
||||
uint8 r = patch.read();
|
||||
output.write(r ^ input.read());
|
||||
if(r == last_in) {
|
||||
if(++rep_count == 2) {
|
||||
rle_count = read_ptr();
|
||||
while(rle_count--) {
|
||||
output.write(r ^ input.read());
|
||||
}
|
||||
rep_count = 0;
|
||||
}
|
||||
} else {
|
||||
rep_count = 0;
|
||||
}
|
||||
|
||||
last_in = r;
|
||||
if(r == 0x00)break;
|
||||
} while(patch.pos < (patch.size - 12));
|
||||
}
|
||||
|
||||
//...and restore it when finished patching
|
||||
output.size = start_size;
|
||||
}
|
||||
|
||||
bool BPF::apply_patch() {
|
||||
//verify patch is large enough to be a valid patchfile
|
||||
if(patch.size < 34)return false;
|
||||
|
||||
patch.seek(INDEX_SIG);
|
||||
//verify signature
|
||||
if(patch.read() != 'b')return false;
|
||||
if(patch.read() != 'p')return false;
|
||||
if(patch.read() != 'f')return false;
|
||||
if(patch.read() != 0x00)return false;
|
||||
|
||||
//read pointer size
|
||||
patch.seek(INDEX_PTRSIZE);
|
||||
info.ptr_size = patch.read();
|
||||
info.ptr_size |= patch.read() << 8;
|
||||
|
||||
//read flags
|
||||
uint32 flags;
|
||||
patch.seek(INDEX_FLAGS);
|
||||
flags = patch.read();
|
||||
flags |= patch.read() << 8;
|
||||
flags |= patch.read() << 16;
|
||||
flags |= patch.read() << 24;
|
||||
|
||||
uint32 sx = 0, sy = 0;
|
||||
patch.seek(INDEX_VARIABLE);
|
||||
for(int i = 0; i < info.ptr_size; i++) {
|
||||
sx |= patch.read() << (i << 3);
|
||||
}
|
||||
for(int i = 0; i < info.ptr_size; i++) {
|
||||
sy |= patch.read() << (i << 3);
|
||||
}
|
||||
|
||||
uint32 cx = 0, cy = 0, cp = 0;
|
||||
patch.seek(patch.size - 12);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
cx |= patch.read() << (i << 3);
|
||||
}
|
||||
for(int i = 0; i < 4; i++) {
|
||||
cy |= patch.read() << (i << 3);
|
||||
}
|
||||
for(int i = 0; i < 4; i++) {
|
||||
cp |= patch.read() << (i << 3);
|
||||
}
|
||||
|
||||
input.calc_crc32();
|
||||
//skip the stored patch crc32 when calculating
|
||||
patch.size -= 4;
|
||||
patch.calc_crc32();
|
||||
patch.size += 4;
|
||||
|
||||
//validate patch crc32
|
||||
if(patch.crc32 != cp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//validate input crc32 + size
|
||||
bool input_num = 0;
|
||||
if(input.crc32 == cx && input.size == sx) {
|
||||
output.open(ACCESS_WRITE, sy);
|
||||
input_num = 0;
|
||||
} else if(input.crc32 == cy && input.size == sy) {
|
||||
output.open(ACCESS_WRITE, sx);
|
||||
input_num = 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
patch.seek(INDEX_FORMAT);
|
||||
info.format = 0;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
info.format |= patch.read() << (i << 3);
|
||||
}
|
||||
|
||||
info.patch_start = 0;
|
||||
patch.seek(INDEX_VARIABLE + info.ptr_size * 2);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
info.patch_start |= patch.read() << (i << 3);
|
||||
}
|
||||
|
||||
apply_patch_binary();
|
||||
|
||||
output.calc_crc32();
|
||||
return (output.crc32 == ((input_num == 0) ? cy : cx));
|
||||
}
|
||||
|
||||
//main library interface functions
|
||||
|
||||
bool BPF::create_patch(uint32 format, const char *fn_patch, const char *fn_x, const char *fn_y) {
|
||||
uint32 size_x = fsize(fn_x);
|
||||
uint32 size_y = fsize(fn_y);
|
||||
bool lim_x = (size_x >= settings.memory_limit);
|
||||
bool lim_y = (size_y >= settings.memory_limit);
|
||||
switch(format) {
|
||||
case FORMAT_BINARY: {
|
||||
if(lim_x == false) {
|
||||
original.load(fn_x);
|
||||
} else {
|
||||
original.open(ACCESS_READ, fn_x);
|
||||
}
|
||||
if(lim_y == false) {
|
||||
modified.load(fn_y);
|
||||
} else {
|
||||
modified.open(ACCESS_READ, fn_y);
|
||||
}
|
||||
} break;
|
||||
case FORMAT_SNES: {
|
||||
if(lim_x == true || lim_y == true) {
|
||||
//files must be loaded into memory to manipulate, but
|
||||
//one or more files exceed the memory limit setting
|
||||
return false;
|
||||
}
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
//remove header, if it exists
|
||||
data = load(fn_x, size);
|
||||
if((size & 0x1fff) == 0x0200) {
|
||||
original.open(ACCESS_READ, size - 512, data + 512);
|
||||
} else {
|
||||
original.open(ACCESS_READ, size, data);
|
||||
}
|
||||
SafeFree(data);
|
||||
|
||||
//remove header, if it exists
|
||||
data = load(fn_y, size);
|
||||
if((size & 0x1fff) == 0x0200) {
|
||||
modified.open(ACCESS_READ, size - 512, data + 512);
|
||||
} else {
|
||||
modified.open(ACCESS_READ, size, data);
|
||||
}
|
||||
SafeFree(data);
|
||||
} break;
|
||||
}
|
||||
bool result = create_patch(format, fn_patch);
|
||||
original.close();
|
||||
modified.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BPF::apply_patch(const char *fn_patch, const char *fn_input) {
|
||||
uint32 size_p = fsize(fn_patch);
|
||||
uint32 size_i = fsize(fn_input);
|
||||
bool lim_p = (size_p >= settings.memory_limit);
|
||||
bool lim_i = (size_i >= settings.memory_limit);
|
||||
if(lim_p == false) {
|
||||
patch.load(fn_patch);
|
||||
} else {
|
||||
patch.open(ACCESS_READ, fn_patch);
|
||||
}
|
||||
|
||||
patch.seek(INDEX_FORMAT);
|
||||
uint32 format;
|
||||
format = patch.read();
|
||||
format |= patch.read() << 8;
|
||||
format |= patch.read() << 16;
|
||||
format |= patch.read() << 24;
|
||||
patch.seek(0);
|
||||
|
||||
switch(format) {
|
||||
case FORMAT_BINARY: {
|
||||
if(lim_i == false) {
|
||||
input.load(fn_input);
|
||||
} else {
|
||||
input.open(ACCESS_READ, fn_input);
|
||||
}
|
||||
} break;
|
||||
case FORMAT_SNES: {
|
||||
if(lim_i == true) {
|
||||
//file too large to load into memory?
|
||||
patch.close();
|
||||
return false;
|
||||
}
|
||||
uint32 size;
|
||||
uint8 *data = load(fn_input, size);
|
||||
//remove header, if it exists
|
||||
if((size & 0x1fff) == 0x0200) {
|
||||
input.open(ACCESS_READ, size - 512, data + 512);
|
||||
} else {
|
||||
input.open(ACCESS_READ, size, data);
|
||||
}
|
||||
SafeFree(data);
|
||||
} break;
|
||||
}
|
||||
bool result = apply_patch();
|
||||
patch.close();
|
||||
input.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BPF::apply_patch(uint32 s_patch, uint8 *p_patch, uint32 s_input, uint8 *p_input) {
|
||||
patch.open(ACCESS_READ, s_patch, p_patch);
|
||||
|
||||
patch.seek(INDEX_FORMAT);
|
||||
uint32 format;
|
||||
format = patch.read();
|
||||
format |= patch.read() << 8;
|
||||
format |= patch.read() << 16;
|
||||
format |= patch.read() << 24;
|
||||
patch.seek(0);
|
||||
|
||||
switch(format) {
|
||||
case FORMAT_BINARY: {
|
||||
input.open(ACCESS_READ, s_input, p_input);
|
||||
} break;
|
||||
case FORMAT_SNES: {
|
||||
//remove header, if it exists
|
||||
if((s_input & 0x1fff) == 0x0200) {
|
||||
input.open(ACCESS_READ, s_input - 512, p_input + 512);
|
||||
} else {
|
||||
input.open(ACCESS_READ, s_input, p_input);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
bool result = apply_patch();
|
||||
patch.close();
|
||||
input.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8 *BPF::get_output_handle(uint32 &size) {
|
||||
size = output.size;
|
||||
return (uint8*)output.data.handle();
|
||||
}
|
||||
|
||||
void BPF::save_output(const char *fn) {
|
||||
output.save(fn);
|
||||
}
|
||||
|
||||
void BPF::clear_settings() {
|
||||
settings.memory_limit = (16 * 1024 * 1024) + 4096;
|
||||
|
||||
settings.insert_data.enabled = false;
|
||||
settings.insert_data.mode = 0;
|
||||
settings.insert_data.handle = 0;
|
||||
settings.insert_data.data = 0;
|
||||
settings.insert_data.size = 0;
|
||||
strcpy(settings.insert_data.fn, "");
|
||||
}
|
||||
|
||||
BPF::BPF() {
|
||||
clear_settings();
|
||||
original.set_parent(this);
|
||||
modified.set_parent(this);
|
||||
output.set_parent(this);
|
||||
input.set_parent(this);
|
||||
patch.set_parent(this);
|
||||
}
|
||||
|
||||
BPF::~BPF() {
|
||||
original.close();
|
||||
modified.close();
|
||||
output.close();
|
||||
input.close();
|
||||
patch.close();
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
libbpf : version 0.01 ~byuu (12/18/05)
|
||||
*/
|
||||
|
||||
#ifndef __LIBBPF
|
||||
#define __LIBBPF
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libvector.h"
|
||||
|
||||
class BPF;
|
||||
|
||||
class BPF {
|
||||
public:
|
||||
|
||||
enum {
|
||||
//patch formats
|
||||
FORMAT_BINARY = 0x0000,
|
||||
FORMAT_SNES = 0x0001,
|
||||
};
|
||||
|
||||
enum {
|
||||
INDEX_SIG = 0x00, //4 bytes
|
||||
INDEX_VERSION = 0x04, //2 bytes
|
||||
INDEX_PTRSIZE = 0x06, //2 bytes
|
||||
INDEX_FORMAT = 0x08, //4 bytes
|
||||
INDEX_FLAGS = 0x0c, //4 bytes
|
||||
INDEX_VARIABLE = 0x10, //variable data follows
|
||||
};
|
||||
|
||||
enum { MODE_MEMORY, MODE_FILE };
|
||||
enum { ACCESS_READ, ACCESS_WRITE };
|
||||
|
||||
struct Handle {
|
||||
BPF *parent;
|
||||
uint8 mode, access;
|
||||
vector<uint8> data;
|
||||
FILE *handle;
|
||||
uint32 size, pos, crc32;
|
||||
|
||||
void seek(uint32 new_pos);
|
||||
void write(uint8 x);
|
||||
uint8 read();
|
||||
|
||||
uint32 calc_crc32();
|
||||
|
||||
bool open(uint8 _mode, uint32 size, uint8 *_data = 0);
|
||||
bool open(uint8 _mode, const char *fn);
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn);
|
||||
void close();
|
||||
|
||||
void set_parent(BPF *_bpf) { parent = _bpf; }
|
||||
|
||||
Handle() {
|
||||
mode = 0; access = 0;
|
||||
crc32 = 0; handle = 0;
|
||||
size = 0; pos = 0;
|
||||
}
|
||||
} original, modified, output, input, patch;
|
||||
|
||||
struct {
|
||||
uint32 memory_limit;
|
||||
struct {
|
||||
bool enabled;
|
||||
uint8 mode;
|
||||
char fn[4096];
|
||||
FILE *handle;
|
||||
uint8 *data;
|
||||
uint32 size;
|
||||
} insert_data;
|
||||
} settings;
|
||||
|
||||
struct {
|
||||
uint16 ptr_size;
|
||||
uint32 size_min, size_max;
|
||||
uint32 patch_start;
|
||||
uint32 format;
|
||||
} info;
|
||||
|
||||
uint8 *load(const char *fn, uint32 &size);
|
||||
void save(const char *fn, uint8 *data, uint32 size);
|
||||
|
||||
void write_ptr(uint32 ptr);
|
||||
uint32 read_ptr();
|
||||
void create_patch_binary();
|
||||
bool create_patch(uint32 format, const char *fn);
|
||||
bool create_patch(uint32 format, const char *fn_patch, const char *fn_x, const char *fn_y);
|
||||
|
||||
void apply_patch_binary();
|
||||
bool apply_patch();
|
||||
bool apply_patch(const char *fn_patch, const char *fn_input);
|
||||
bool apply_patch(uint32 s_patch, uint8 *p_patch, uint32 s_input, uint8 *p_input);
|
||||
|
||||
uint8 *get_output_handle(uint32 &size);
|
||||
void save_output(const char *fn);
|
||||
|
||||
void clear_settings();
|
||||
|
||||
BPF();
|
||||
~BPF();
|
||||
};
|
||||
|
||||
#endif
|
||||
+88
-32
@@ -13,12 +13,34 @@ uint Setting::get() {
|
||||
void Setting::set(uint _data) {
|
||||
data = _data;
|
||||
|
||||
if(type != DEC && type != HEX) {
|
||||
//data is a boolean type
|
||||
switch(type) {
|
||||
case TRUE_FALSE:
|
||||
case ENABLED_DISABLED:
|
||||
case ON_OFF:
|
||||
case YES_NO:
|
||||
data &= 1;
|
||||
break;
|
||||
case HEX8:
|
||||
data &= 0xff;
|
||||
break;
|
||||
case HEX16:
|
||||
data &= 0xffff;
|
||||
break;
|
||||
case HEX24:
|
||||
data &= 0xffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *Setting::sget() {
|
||||
return strptr(char_data);
|
||||
}
|
||||
|
||||
void Setting::sset(const char *_data) {
|
||||
strcpy(char_data, _data);
|
||||
strunquote(char_data);
|
||||
}
|
||||
|
||||
Setting::Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type) {
|
||||
int s;
|
||||
if(_parent) {
|
||||
@@ -43,55 +65,80 @@ int s;
|
||||
type = _type;
|
||||
}
|
||||
|
||||
Setting::Setting(Config *_parent, char *_name, char *_desc, char *_data) {
|
||||
int s;
|
||||
if(_parent) {
|
||||
_parent->add(this);
|
||||
}
|
||||
|
||||
s = strlen(_name);
|
||||
name = (char*)malloc(s + 1);
|
||||
strcpy(name, _name);
|
||||
|
||||
if(_desc) {
|
||||
s = strlen(_desc);
|
||||
desc = (char*)malloc(s + 1);
|
||||
strcpy(desc, _desc);
|
||||
} else {
|
||||
desc = (char*)malloc(1);
|
||||
*desc = 0;
|
||||
}
|
||||
|
||||
strcpy(char_data, _data);
|
||||
strcpy(char_def, _data);
|
||||
|
||||
type = STR;
|
||||
}
|
||||
|
||||
void Config::add(Setting *setting) {
|
||||
list[list_count++] = setting;
|
||||
}
|
||||
|
||||
uint Config::string_to_uint(uint type, char *input) {
|
||||
if(!strcmp(input, "true") ||
|
||||
!strcmp(input, "enabled") ||
|
||||
!strcmp(input, "on") ||
|
||||
!strcmp(input, "yes")
|
||||
if(strmatch(input, "true") ||
|
||||
strmatch(input, "enabled") ||
|
||||
strmatch(input, "on") ||
|
||||
strmatch(input, "yes")
|
||||
) {
|
||||
return (uint)true;
|
||||
}
|
||||
|
||||
if(!strcmp(input, "false") ||
|
||||
!strcmp(input, "disabled") ||
|
||||
!strcmp(input, "off") ||
|
||||
!strcmp(input, "no")
|
||||
if(strmatch(input, "false") ||
|
||||
strmatch(input, "disabled") ||
|
||||
strmatch(input, "off") ||
|
||||
strmatch(input, "no")
|
||||
) {
|
||||
return (uint)false;
|
||||
}
|
||||
|
||||
if(!strbegin(input, "0x")) {
|
||||
return strhex(input + 2);
|
||||
if(strbegin(input, "0x") || strbegin(input, "-0x")) {
|
||||
return sstrhex(input + 2);
|
||||
}
|
||||
|
||||
return strdec(input);
|
||||
return sstrdec(input);
|
||||
}
|
||||
|
||||
char *Config::uint_to_string(uint type, uint input) {
|
||||
static char output[512];
|
||||
switch(type) {
|
||||
case Setting::TRUE_FALSE:
|
||||
sprintf(output, "%s", (input & 1)?"true":"false");
|
||||
sprintf(output, "%s", (input & 1) ? "true" : "false");
|
||||
break;
|
||||
case Setting::ENABLED_DISABLED:
|
||||
sprintf(output, "%s", (input & 1)?"enabled":"disabled");
|
||||
sprintf(output, "%s", (input & 1) ? "enabled" : "disabled");
|
||||
break;
|
||||
case Setting::ON_OFF:
|
||||
sprintf(output, "%s", (input & 1)?"on":"off");
|
||||
sprintf(output, "%s", (input & 1) ? "on" : "off");
|
||||
break;
|
||||
case Setting::YES_NO:
|
||||
sprintf(output, "%s", (input & 1)?"yes":"no");
|
||||
break;
|
||||
case Setting::DEC:
|
||||
sprintf(output, "%d", input);
|
||||
break;
|
||||
case Setting::HEX:
|
||||
sprintf(output, "0x%x", input);
|
||||
sprintf(output, "%s", (input & 1) ? "yes" : "no");
|
||||
break;
|
||||
case Setting::DEC: sprintf(output, "%d", input); break;
|
||||
case Setting::HEX: sprintf(output, "0x%x", input); break;
|
||||
case Setting::HEX8: sprintf(output, "0x%0.2x", input & 0xff); break;
|
||||
case Setting::HEX16: sprintf(output, "0x%0.4x", input & 0xffff); break;
|
||||
case Setting::HEX24: sprintf(output, "0x%0.6x", input & 0xffffff); break;
|
||||
case Setting::HEX32: sprintf(output, "0x%0.8x", input); break;
|
||||
}
|
||||
|
||||
return output;
|
||||
@@ -119,14 +166,18 @@ char *buffer = (char*)malloc(fsize + 1);
|
||||
qreplace(data, " ", "");
|
||||
split(line, "\n", data);
|
||||
|
||||
for(int i=0;i<count(line);i++) {
|
||||
for(int i = 0; i < count(line); i++) {
|
||||
if(strlen(line[i]) == 0)continue;
|
||||
if(*strptr(line[i]) == '#')continue;
|
||||
|
||||
split(part, "=", line[i]);
|
||||
for(int l=0;l<list_count;l++) {
|
||||
if(!strcmp(list[l]->name, part[0])) {
|
||||
list[l]->set(string_to_uint(list[l]->type, strptr(part[1])));
|
||||
qsplit(part, "=", line[i]);
|
||||
for(int l = 0; l < list_count; l++) {
|
||||
if(strmatch(list[l]->name, part[0])) {
|
||||
if(list[l]->type != Setting::STR) {
|
||||
list[l]->set(string_to_uint(list[l]->type, strptr(part[1])));
|
||||
} else {
|
||||
list[l]->sset(strptr(part[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,15 +191,20 @@ FILE *fp;
|
||||
fp = fopen(fn, "wb");
|
||||
if(!fp)return false;
|
||||
|
||||
for(int i=0;i<list_count;i++) {
|
||||
for(int i = 0; i < list_count; i++) {
|
||||
strcpy(data, list[i]->desc);
|
||||
replace(data, "\r\n", "\n");
|
||||
split(line, "\n", data);
|
||||
for(int l=0;l<count(line);l++) {
|
||||
for(int l = 0; l < count(line); l++) {
|
||||
fprintf(fp, "# %s\r\n", strptr(line[l]));
|
||||
}
|
||||
fprintf(fp, "# (default = %s)\r\n", uint_to_string(list[i]->type, list[i]->def));
|
||||
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, uint_to_string(list[i]->type, list[i]->data));
|
||||
if(list[i]->type != Setting::STR) {
|
||||
fprintf(fp, "# (default = %s)\r\n", uint_to_string(list[i]->type, list[i]->def));
|
||||
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, uint_to_string(list[i]->type, list[i]->data));
|
||||
} else {
|
||||
fprintf(fp, "# (default = \"%s\")\r\n", strptr(list[i]->char_def));
|
||||
fprintf(fp, "%s = \"%s\"\r\n\r\n", list[i]->name, strptr(list[i]->char_data));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+26
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libconfig : version 0.05 ~byuu (09/13/05)
|
||||
libconfig : version 0.07 ~byuu (02/10/06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBCONFIG
|
||||
@@ -28,9 +28,13 @@ class Config;
|
||||
inline __name &operator=(const int8 _data) { set(_data); return *this; } \
|
||||
inline __name &operator=(const int16 _data) { set(_data); return *this; } \
|
||||
inline __name &operator=(const int32 _data) { set(_data); return *this; } \
|
||||
inline __name &operator=(const float _data) { set((uint)_data); return *this; } \
|
||||
inline __name &operator=(const double _data) { set((uint)_data); return *this; } \
|
||||
void toggle() { data ^= 1; set(data); } \
|
||||
__name(Config *_parent, char *_name, char *_desc = 0, uint _data = 0, uint _type = Setting::DEC) : \
|
||||
Setting(_parent, _name, _desc, _data, _type) {}
|
||||
__name(Config *_parent, char *_name, char *_desc, uint _data, uint _type) : \
|
||||
Setting(_parent, _name, _desc, _data, _type) {} \
|
||||
__name(Config *_parent, char *_name, char *_desc, char *_data) : \
|
||||
Setting(_parent, _name, _desc, _data) {}
|
||||
|
||||
class Setting {
|
||||
friend class Config;
|
||||
@@ -44,16 +48,25 @@ enum {
|
||||
ENABLED_DISABLED,
|
||||
ON_OFF,
|
||||
YES_NO,
|
||||
BOOL,
|
||||
DEC,
|
||||
HEX
|
||||
HEX,
|
||||
HEX8,
|
||||
HEX16,
|
||||
HEX24,
|
||||
HEX32,
|
||||
STR
|
||||
};
|
||||
char *name, *desc;
|
||||
virtual void toggle();
|
||||
virtual uint get();
|
||||
virtual void set(uint _data);
|
||||
substring char_data, char_def;
|
||||
virtual void toggle();
|
||||
virtual uint get();
|
||||
virtual void set(uint _data);
|
||||
|
||||
Setting(Config *_parent, char *_name, char *_desc = 0, uint _data = 0, uint _type = DEC);
|
||||
virtual char *sget();
|
||||
virtual void sset(const char *_data);
|
||||
|
||||
Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type);
|
||||
Setting(Config *_parent, char *_name, char *_desc, char *_data);
|
||||
|
||||
inline operator bool() { return (bool)get(); }
|
||||
inline operator uint() { return get(); }
|
||||
@@ -64,6 +77,8 @@ char *name, *desc;
|
||||
inline operator int8() { return get(); }
|
||||
inline operator int16() { return get(); }
|
||||
inline operator int32() { return get(); }
|
||||
inline operator float() { return (float) get(); }
|
||||
inline operator double() { return (double)get(); }
|
||||
|
||||
inline Setting &operator=(const bool _data) { set((uint)_data); return *this; }
|
||||
inline Setting &operator=(const uint _data) { set(_data); return *this; }
|
||||
@@ -74,6 +89,8 @@ char *name, *desc;
|
||||
inline Setting &operator=(const int8 _data) { set(_data); return *this; }
|
||||
inline Setting &operator=(const int16 _data) { set(_data); return *this; }
|
||||
inline Setting &operator=(const int32 _data) { set(_data); return *this; }
|
||||
inline Setting &operator=(const float _data) { set((uint)_data); return *this; }
|
||||
inline Setting &operator=(const double _data) { set((uint)_data); return *this; }
|
||||
};
|
||||
|
||||
class Config {
|
||||
|
||||
+97
-70
@@ -64,6 +64,28 @@ int strcmp(substring &dest, const char *src) { return strcmp(strptr(dest), src);
|
||||
int strcmp(const char *dest, substring &src) { return strcmp(dest, strptr(src)); }
|
||||
int strcmp(substring &dest, substring &src) { return strcmp(strptr(dest), strptr(src)); }
|
||||
|
||||
int __stricmp(const char *dest, const char *src) {
|
||||
while(*dest && *src) {
|
||||
if(chrlower(*dest) != chrlower(*src))break;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
int stricmp(substring &dest, const char *src) { return __stricmp(strptr(dest), src); }
|
||||
int stricmp(const char *dest, substring &src) { return __stricmp(dest, strptr(src)); }
|
||||
int stricmp(substring &dest, substring &src) { return __stricmp(strptr(dest), strptr(src)); }
|
||||
|
||||
bool strmatch(const char *dest, const char *src) { return !strcmp(dest, src); }
|
||||
bool strmatch(substring &dest, const char *src) { return strmatch(strptr(dest), src); }
|
||||
bool strmatch(const char *dest, substring &src) { return strmatch(dest, strptr(src)); }
|
||||
bool strmatch(substring &dest, substring &src) { return strmatch(strptr(dest), strptr(src)); }
|
||||
|
||||
bool strimatch(const char *dest, const char *src) { return !stricmp(dest, src); }
|
||||
bool strimatch(substring &dest, const char *src) { return strimatch(strptr(dest), src); }
|
||||
bool strimatch(const char *dest, substring &src) { return strimatch(dest, strptr(src)); }
|
||||
bool strimatch(substring &dest, substring &src) { return strimatch(strptr(dest), strptr(src)); }
|
||||
|
||||
void strcpy(substring &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
if(srclen > dest.size) { strresize(dest, srclen); }
|
||||
@@ -71,6 +93,18 @@ int srclen = strlen(src);
|
||||
}
|
||||
void strcpy(substring &dest, substring &src) { strcpy(dest, strptr(src)); }
|
||||
|
||||
//this differs from libc's strncpy in that it always
|
||||
//appends a null terminator to the end of a copied string
|
||||
void strncpy(substring &dest, const char *src, uint32 length) {
|
||||
int srclen = strlen(src);
|
||||
//never copy more text than is in the string
|
||||
if(srclen > length)srclen = length;
|
||||
if(srclen > dest.size) { strresize(dest, srclen); }
|
||||
strncpy(dest.s, src, srclen);
|
||||
dest.s[srclen] = 0;
|
||||
}
|
||||
void strncpy(substring &dest, substring &src, uint32 length) { strncpy(dest, strptr(src), length); }
|
||||
|
||||
void strset(substring &dest, uint pos, uint8 c) {
|
||||
char *s;
|
||||
if(pos > dest.size) { strresize(dest, pos); }
|
||||
@@ -109,18 +143,6 @@ int i, sl = strlen(dest.s);
|
||||
s[i] = 0;
|
||||
}
|
||||
|
||||
int __stricmp(const char *dest, const char *src) {
|
||||
while(*dest && *src) {
|
||||
if(chrlower(*dest) != chrlower(*src))break;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
int stricmp(substring &dest, const char *src) { return __stricmp(strptr(dest), src); }
|
||||
int stricmp(const char *dest, substring &src) { return __stricmp(dest, strptr(src)); }
|
||||
int stricmp(substring &dest, substring &src) { return __stricmp(strptr(dest), strptr(src)); }
|
||||
|
||||
void strlower(char *str) {
|
||||
while(*str) {
|
||||
*str = chrlower(*str);
|
||||
@@ -137,105 +159,110 @@ void strupper(char *str) {
|
||||
}
|
||||
void strupper(substring &str) { strupper(strptr(str)); }
|
||||
|
||||
uint strpos(const char *str, const char *key) {
|
||||
bool strpos(const char *str, const char *key, uint &pos) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return null;
|
||||
for(i=0;i<=ssl-ksl;i++) {
|
||||
if(!memcmp(str+i, key, ksl))return i;
|
||||
if(ksl > ssl)return false;
|
||||
for(i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
pos = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
uint strpos(substring &str, const char *key) { return strpos(strptr(str), key); }
|
||||
uint strpos(const char *str, substring &key) { return strpos(str, strptr(key)); }
|
||||
uint strpos(substring &str, substring &key) { return strpos(strptr(str), strptr(key)); }
|
||||
bool strpos(substring &str, const char *key, uint &pos) { return strpos(strptr(str), key, pos); }
|
||||
bool strpos(const char *str, substring &key, uint &pos) { return strpos(str, strptr(key), pos); }
|
||||
bool strpos(substring &str, substring &key, uint &pos) { return strpos(strptr(str), strptr(key), pos); }
|
||||
|
||||
uint qstrpos(const char *str, const char *key) {
|
||||
bool qstrpos(const char *str, const char *key, uint &pos) {
|
||||
int i, z, ssl = strlen(str), ksl = strlen(key);
|
||||
uint8 x;
|
||||
if(ksl > ssl)return null;
|
||||
for(i=0;i<=ssl-ksl;) {
|
||||
if(ksl > ssl)return false;
|
||||
for(i = 0; i <= ssl - ksl;) {
|
||||
x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
z = i++;
|
||||
while(str[i] != x && i < ssl)i++;
|
||||
if(i >= ssl)i = z;
|
||||
}
|
||||
if(!memcmp(str+i, key, ksl)) {
|
||||
return i;
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
pos = i;
|
||||
return true;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
uint qstrpos(substring &str, const char *key) { return qstrpos(strptr(str), key); }
|
||||
uint qstrpos(const char *str, substring &key) { return qstrpos(str, strptr(key)); }
|
||||
uint qstrpos(substring &str, substring &key) { return qstrpos(strptr(str), strptr(key)); }
|
||||
bool qstrpos(substring &str, const char *key, uint &pos) { return qstrpos(strptr(str), key, pos); }
|
||||
bool qstrpos(const char *str, substring &key, uint &pos) { return qstrpos(str, strptr(key), pos); }
|
||||
bool qstrpos(substring &str, substring &key, uint &pos) { return qstrpos(strptr(str), strptr(key), pos); }
|
||||
|
||||
void strtr(char *dest, const char *before, const char *after) {
|
||||
int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
|
||||
if((bsl != asl) || bsl == 0)return;
|
||||
for(i=0;i<sl;i++) {
|
||||
for(l=0;l<bsl;l++) {
|
||||
if(dest[i] == before[l])dest[i] = after[l];
|
||||
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
|
||||
if(bsl != asl || bsl == 0)return;
|
||||
for(int i = 0; i < sl; i++) {
|
||||
for(int l = 0; l < bsl; l++) {
|
||||
if(dest[i] == before[l]) {
|
||||
dest[i] = after[l];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void strtr(substring &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); }
|
||||
|
||||
uint strbegin(const char *str, const char *key) {
|
||||
bool strbegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return 1;
|
||||
if(!memcmp(str, key, ksl))return 0;
|
||||
return 1;
|
||||
if(ksl > ssl)return false;
|
||||
return (!memcmp(str, key, ksl));
|
||||
}
|
||||
uint strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); }
|
||||
bool strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); }
|
||||
|
||||
uint stribegin(const char *str, const char *key) {
|
||||
bool stribegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return 1;
|
||||
if(ksl > ssl)return false;
|
||||
for(i=0;i<ksl;i++) {
|
||||
if(str[i] >= 'A' && str[i] <= 'Z') {
|
||||
if(str[i] != key[i] && str[i]+0x20 != key[i])return 1;
|
||||
if(str[i] != key[i] && str[i]+0x20 != key[i])return false;
|
||||
} else if(str[i] >= 'a' && str[i] <= 'z') {
|
||||
if(str[i] != key[i] && str[i]-0x20 != key[i])return 1;
|
||||
if(str[i] != key[i] && str[i]-0x20 != key[i])return false;
|
||||
} else {
|
||||
if(str[i] != key[i])return 1;
|
||||
if(str[i] != key[i])return false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
uint stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); }
|
||||
bool stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); }
|
||||
|
||||
uint strend(const char *str, const char *key) {
|
||||
bool strend(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return 1;
|
||||
if(!memcmp(str + ssl - ksl, key, ksl))return 0;
|
||||
return 1;
|
||||
if(ksl > ssl)return false;
|
||||
return (!memcmp(str + ssl - ksl, key, ksl));
|
||||
}
|
||||
uint strend(substring &str, const char *key) { return strend(strptr(str), key); }
|
||||
bool strend(substring &str, const char *key) { return strend(strptr(str), key); }
|
||||
|
||||
uint striend(const char *str, const char *key) {
|
||||
bool striend(const char *str, const char *key) {
|
||||
int i, z, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return 1;
|
||||
if(ksl > ssl)return false;
|
||||
for(i=ssl-ksl, z=0;i<ssl;i++, z++) {
|
||||
if(str[i] >= 'A' && str[i] <= 'Z') {
|
||||
if(str[i] != key[z] && str[i]+0x20 != key[z])return 1;
|
||||
if(str[i] != key[z] && str[i]+0x20 != key[z])return false;
|
||||
} else if(str[i] >= 'a' && str[i] <= 'z') {
|
||||
if(str[i] != key[z] && str[i]-0x20 != key[z])return 1;
|
||||
if(str[i] != key[z] && str[i]-0x20 != key[z])return false;
|
||||
} else {
|
||||
if(str[i] != key[z])return 1;
|
||||
if(str[i] != key[z])return false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
uint striend(substring &str, const char *key) { return striend(strptr(str), key); }
|
||||
bool striend(substring &str, const char *key) { return striend(strptr(str), key); }
|
||||
|
||||
void strltrim(char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(!strbegin(str, key)) {
|
||||
for(i=0;i<ssl-ksl;i++)str[i] = str[i + ksl];
|
||||
if(strbegin(str, key)) {
|
||||
for(i = 0; i < (ssl - ksl); i++)str[i] = str[i + ksl];
|
||||
str[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -244,8 +271,8 @@ void strltrim(substring &str, const char *key) { strltrim(strptr(str), key); }
|
||||
void striltrim(char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(!stribegin(str, key)) {
|
||||
for(i=0;i<ssl-ksl;i++)str[i] = str[i + ksl];
|
||||
if(stribegin(str, key)) {
|
||||
for(i = 0; i < (ssl-ksl); i++)str[i] = str[i + ksl];
|
||||
str[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -254,7 +281,7 @@ void striltrim(substring &str, const char *key) { striltrim(strptr(str), key); }
|
||||
void strrtrim(char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(!strend(str, key)) {
|
||||
if(strend(str, key)) {
|
||||
str[ssl - ksl] = 0;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +290,7 @@ void strrtrim(substring &str, const char *key) { strrtrim(strptr(str), key); }
|
||||
void strirtrim(char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(!striend(str, key)) {
|
||||
if(striend(str, key)) {
|
||||
str[ssl - ksl] = 0;
|
||||
}
|
||||
}
|
||||
@@ -302,13 +329,13 @@ uint strhex(const char *str) {
|
||||
uint r = 0, m = 0;
|
||||
int i, ssl = strlen(str);
|
||||
uint8 x;
|
||||
for(i=0;i<ssl;i++) {
|
||||
for(i = 0; i < ssl; i++) {
|
||||
if(str[i] >= '0' && str[i] <= '9');
|
||||
else if(str[i] >= 'A' && str[i] <= 'F');
|
||||
else if(str[i] >= 'a' && str[i] <= 'f');
|
||||
else break;
|
||||
}
|
||||
for(--i;i>=0;i--, m+=4) {
|
||||
for(--i; i >= 0; i--, m += 4) {
|
||||
x = str[i];
|
||||
if(x >= '0' && x <= '9')x -= '0';
|
||||
else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a;
|
||||
@@ -332,11 +359,11 @@ uint strdec(const char *str) {
|
||||
uint m = 1;
|
||||
int i, r = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
for(i=0;i<ssl;i++) {
|
||||
for(i = 0; i < ssl; i++) {
|
||||
if(str[i] >= '0' && str[i] <= '9');
|
||||
else break;
|
||||
}
|
||||
for(--i;i>=0;i--, m*=10) {
|
||||
for(--i; i >= 0; i--, m *= 10) {
|
||||
x = str[i];
|
||||
if(x >= '0' && x <= '9')x -= '0';
|
||||
else return r;
|
||||
@@ -358,11 +385,11 @@ uint strbin(const char *str) {
|
||||
uint r = 0, m = 0;
|
||||
int i, ssl = strlen(str);
|
||||
uint8 x;
|
||||
for(i=0;i<ssl;i++) {
|
||||
for(i = 0; i < ssl; i++) {
|
||||
if(str[i] == '0' || str[i] == '1');
|
||||
else break;
|
||||
}
|
||||
for(--i;i>=0;i--, m++) {
|
||||
for(--i; i >= 0; i--, m++) {
|
||||
x = str[i];
|
||||
if(str[i] == '0' || str[i] == '1')x -= '0';
|
||||
else return r;
|
||||
|
||||
+40
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libstring : version 0.06a ~byuu (08/22/05)
|
||||
libstring : version 0.10 ~byuu (03/05/06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTRING
|
||||
@@ -25,8 +25,29 @@ int strcmp(substring &dest, const char *src);
|
||||
int strcmp(const char *dest, substring &src);
|
||||
int strcmp(substring &dest, substring &src);
|
||||
|
||||
//vc6/win32 and gcc/dos only support stricmp, whereas
|
||||
//gcc/unix only supports strcasecmp. this is an attempt
|
||||
//to avoid platform-specific defines...
|
||||
#define stricmp __stricmp
|
||||
int __stricmp(const char *dest, const char *src);
|
||||
int stricmp(substring &dest, const char *src);
|
||||
int stricmp(const char *dest, substring &src);
|
||||
int stricmp(substring &dest, substring &src);
|
||||
|
||||
bool strmatch(const char *dest, const char *src);
|
||||
bool strmatch(substring &dest, const char *src);
|
||||
bool strmatch(const char *dest, substring &src);
|
||||
bool strmatch(substring &dest, substring &src);
|
||||
|
||||
bool strimatch(const char *dest, const char *src);
|
||||
bool strimatch(substring &dest, const char *src);
|
||||
bool strimatch(const char *dest, substring &src);
|
||||
bool strimatch(substring &dest, substring &src);
|
||||
|
||||
void strcpy(substring &dest, const char *src);
|
||||
void strcpy(substring &dest, substring &src);
|
||||
void strncpy(substring &dest, const char *src, uint32 length);
|
||||
void strncpy(substring &dest, substring &src, uint32 length);
|
||||
|
||||
void strset(substring &dest, uint pos, uint8 c);
|
||||
|
||||
@@ -38,45 +59,36 @@ void strinsert(substring &dest, substring &src, uint pos);
|
||||
|
||||
void strremove(substring &dest, uint start, uint length = 0);
|
||||
|
||||
//vc6/win32 and gcc/dos only support stricmp, whereas
|
||||
//gcc/unix only supports strcasecmp. this is an attempt
|
||||
//to avoid platform-specific defines...
|
||||
#define stricmp __stricmp
|
||||
int __stricmp(const char *dest, const char *src);
|
||||
int stricmp(substring &dest, const char *src);
|
||||
int stricmp(const char *dest, substring &src);
|
||||
int stricmp(substring &dest, substring &src);
|
||||
|
||||
void strlower(char *str);
|
||||
void strlower(substring &str);
|
||||
|
||||
void strupper(char *str);
|
||||
void strupper(substring &str);
|
||||
|
||||
uint strpos(const char *str, const char *key);
|
||||
uint strpos(substring &str, const char *key);
|
||||
uint strpos(const char *str, substring &key);
|
||||
uint strpos(substring &str, substring &key);
|
||||
bool strpos(const char *str, const char *key, uint &pos);
|
||||
bool strpos(substring &str, const char *key, uint &pos);
|
||||
bool strpos(const char *str, substring &key, uint &pos);
|
||||
bool strpos(substring &str, substring &key, uint &pos);
|
||||
|
||||
uint qstrpos(const char *str, const char *key);
|
||||
uint qstrpos(substring &str, const char *key);
|
||||
uint qstrpos(const char *str, substring &key);
|
||||
uint qstrpos(substring &str, substring &key);
|
||||
bool qstrpos(const char *str, const char *key, uint &pos);
|
||||
bool qstrpos(substring &str, const char *key, uint &pos);
|
||||
bool qstrpos(const char *str, substring &key, uint &pos);
|
||||
bool qstrpos(substring &str, substring &key, uint &pos);
|
||||
|
||||
void strtr(char *dest, const char *before, const char *after);
|
||||
void strtr(substring &dest, const char *before, const char *after);
|
||||
|
||||
uint strbegin(const char *str, const char *key);
|
||||
uint strbegin(substring &str, const char *key);
|
||||
bool strbegin(const char *str, const char *key);
|
||||
bool strbegin(substring &str, const char *key);
|
||||
|
||||
uint stribegin(const char *str, const char *key);
|
||||
uint stribegin(substring &str, const char *key);
|
||||
bool stribegin(const char *str, const char *key);
|
||||
bool stribegin(substring &str, const char *key);
|
||||
|
||||
uint strend(const char *str, const char *key);
|
||||
uint strend(substring &str, const char *key);
|
||||
bool strend(const char *str, const char *key);
|
||||
bool strend(substring &str, const char *key);
|
||||
|
||||
uint striend(const char *str, const char *key);
|
||||
uint striend(substring &str, const char *key);
|
||||
bool striend(const char *str, const char *key);
|
||||
bool striend(substring &str, const char *key);
|
||||
|
||||
void strltrim(char *str, const char *key);
|
||||
void strltrim(substring &str, const char *key);
|
||||
@@ -125,10 +137,10 @@ void replace(substring &str, const char *key, substring &token);
|
||||
void qreplace(substring &str, const char *key, const char *token);
|
||||
void qreplace(substring &str, const char *key, substring &token);
|
||||
|
||||
void split(string &dest, const char *key, char *src);
|
||||
void split(string &dest, const char *key, const char *src);
|
||||
void split(string &dest, const char *key, substring &src);
|
||||
|
||||
void qsplit(string &dest, const char *key, char *src);
|
||||
void qsplit(string &dest, const char *key, const char *src);
|
||||
void qsplit(string &dest, const char *key, substring &src);
|
||||
|
||||
void sprintf(substring &str, const char *s, ...);
|
||||
|
||||
Loaded 100 of 327 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user