Update to v078r04 release.

byuu says:

Changelog:
- file and slot load dialogs should now have perfectly square buttons
  that are based on the platform's default button height.
- cleaned up bsnes/Accuracy SMP source code (removed old !! stuff, stage
  3 timer is now uint4, memory access switch/case cleaned up,
  sSMPTimer->Timer, etc.)
- cleaned up bsnes/Accuracy memory access functions (read/writestack ->
  read/writesp, read/writeaddr -> read/write)
- minor optimization to bsnes/Performance SMP core in cycle-mode
This commit is contained in:
Tim Allen 2011-05-05 21:40:22 +10:00
parent 7ffaeb2ac1
commit 6694a1c986
18 changed files with 269 additions and 275 deletions

View File

@ -1,7 +1,7 @@
void SMP::tick() {
timer0.tick(1);
timer1.tick(1);
timer2.tick(1);
timer0.tick();
timer1.tick();
timer2.tick();
clock += cycle_step_cpu;
dsp.clock -= 24;
@ -19,7 +19,7 @@ uint8 SMP::op_read(uint16 addr) {
tick();
#endif
if((addr & 0xfff0) == 0x00f0) return mmio_read(addr);
if((addr & 0xffc0) == 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f];
if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f];
return apuram[addr];
}
@ -31,9 +31,6 @@ void SMP::op_write(uint16 addr, uint8 data) {
apuram[addr] = data; //all writes go to RAM, even MMIO writes
}
//TODO:
//* non-cycle accurate untaken conditional branches should subtract from opcode's cycle overhead
void SMP::op_step() {
#define op_readpc() op_read(regs.pc++)
#define op_readdp(addr) op_read((regs.p.p << 8) + addr)
@ -68,6 +65,8 @@ void SMP::op_step() {
#include "core/op_rmw.cpp"
}
//TODO: untaken branches should consume less cycles
timer0.tick(cycle_count_table[opcode]);
timer1.tick(cycle_count_table[opcode]);
timer2.tick(cycle_count_table[opcode]);

View File

@ -1,25 +0,0 @@
void tick();
alwaysinline void op_io();
debugvirtual alwaysinline uint8 op_read(uint16 addr);
debugvirtual alwaysinline void op_write(uint16 addr, uint8 data);
debugvirtual alwaysinline void op_step();
static const unsigned cycle_count_table[256];
uint64 cycle_table_cpu[256];
unsigned cycle_table_dsp[256];
uint64 cycle_step_cpu;
uint8 op_adc (uint8 x, uint8 y);
uint16 op_addw(uint16 x, uint16 y);
uint8 op_and (uint8 x, uint8 y);
uint8 op_cmp (uint8 x, uint8 y);
uint16 op_cmpw(uint16 x, uint16 y);
uint8 op_eor (uint8 x, uint8 y);
uint8 op_inc (uint8 x);
uint8 op_dec (uint8 x);
uint8 op_or (uint8 x, uint8 y);
uint8 op_sbc (uint8 x, uint8 y);
uint16 op_subw(uint16 x, uint16 y);
uint8 op_asl (uint8 x);
uint8 op_lsr (uint8 x);
uint8 op_rol (uint8 x);
uint8 op_ror (uint8 x);

Binary file not shown.

View File

@ -1,4 +1,4 @@
#define CYCLE_ACCURATE
//#define CYCLE_ACCURATE
#include <snes/snes.hpp>

View File

@ -21,8 +21,7 @@ public:
SMP();
~SMP();
#include "core.hpp"
//private:
struct Flags {
bool n, v, p, b, h, i, z, c;
@ -75,12 +74,39 @@ public:
uint8 stage2_ticks;
uint8 stage3_ticks;
void tick();
void tick(unsigned clocks);
};
Timer<128> timer0;
Timer<128> timer1;
Timer< 16> timer2;
void tick();
alwaysinline void op_io();
debugvirtual alwaysinline uint8 op_read(uint16 addr);
debugvirtual alwaysinline void op_write(uint16 addr, uint8 data);
debugvirtual alwaysinline void op_step();
static const unsigned cycle_count_table[256];
uint64 cycle_table_cpu[256];
unsigned cycle_table_dsp[256];
uint64 cycle_step_cpu;
uint8 op_adc (uint8 x, uint8 y);
uint16 op_addw(uint16 x, uint16 y);
uint8 op_and (uint8 x, uint8 y);
uint8 op_cmp (uint8 x, uint8 y);
uint16 op_cmpw(uint16 x, uint16 y);
uint8 op_eor (uint8 x, uint8 y);
uint8 op_inc (uint8 x);
uint8 op_dec (uint8 x);
uint8 op_or (uint8 x, uint8 y);
uint8 op_sbc (uint8 x, uint8 y);
uint16 op_subw(uint16 x, uint16 y);
uint8 op_asl (uint8 x);
uint8 op_lsr (uint8 x);
uint8 op_rol (uint8 x);
uint8 op_ror (uint8 x);
};
#if defined(DEBUGGER)

View File

@ -1,3 +1,16 @@
template<unsigned cycle_frequency>
void SMP::Timer<cycle_frequency>::tick() {
if(++stage1_ticks < cycle_frequency) return;
stage1_ticks = 0;
if(enable == false) return;
if(++stage2_ticks != target) return;
stage2_ticks = 0;
stage3_ticks = (stage3_ticks + 1) & 15;
}
template<unsigned cycle_frequency>
void SMP::Timer<cycle_frequency>::tick(unsigned clocks) {
stage1_ticks += clocks;
@ -6,10 +19,8 @@ void SMP::Timer<cycle_frequency>::tick(unsigned clocks) {
stage1_ticks -= cycle_frequency;
if(enable == false) return;
stage2_ticks++;
if(stage2_ticks != target) return;
if(++stage2_ticks != target) return;
stage2_ticks = 0;
stage3_ticks++;
stage3_ticks &= 15;
stage3_ticks = (stage3_ticks + 1) & 15;
}

View File

@ -2,22 +2,14 @@ alwaysinline uint8_t op_readpc() {
return op_read(regs.pc++);
}
alwaysinline uint8_t op_readstack() {
alwaysinline uint8_t op_readsp() {
return op_read(0x0100 | ++regs.sp);
}
alwaysinline void op_writestack(uint8_t data) {
alwaysinline void op_writesp(uint8_t data) {
op_write(0x0100 | regs.sp--, data);
}
alwaysinline uint8_t op_readaddr(uint16_t addr) {
return op_read(addr);
}
alwaysinline void op_writeaddr(uint16_t addr, uint8_t data) {
op_write(addr, data);
}
alwaysinline uint8_t op_readdp(uint8_t addr) {
return op_read(((unsigned)regs.p.p << 8) + addr);
}

View File

@ -31,7 +31,7 @@ void SMPcore::op_daa() {
if(regs.p.h || (regs.a & 15) > 0x09) {
regs.a += 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
@ -45,7 +45,7 @@ void SMPcore::op_das() {
if(!regs.p.h || (regs.a & 15) > 0x09) {
regs.a -= 0x06;
}
regs.p.n = !!(regs.a & 0x80);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
@ -76,25 +76,25 @@ template<int op, int value> void SMPcore::op_setbit_dp() {
template<int n> void SMPcore::op_push_reg() {
op_io();
op_io();
op_writestack(regs.r[n]);
op_writesp(regs.r[n]);
}
void SMPcore::op_push_p() {
op_io();
op_io();
op_writestack(regs.p);
op_writesp(regs.p);
}
template<int n> void SMPcore::op_pop_reg() {
op_io();
op_io();
regs.r[n] = op_readstack();
regs.r[n] = op_readsp();
}
void SMPcore::op_pop_p() {
op_io();
op_io();
regs.p = op_readstack();
regs.p = op_readsp();
}
void SMPcore::op_mul_ya() {
@ -110,7 +110,7 @@ void SMPcore::op_mul_ya() {
regs.a = ya;
regs.y = ya >> 8;
//result is set based on y (high-byte) only
regs.p.n = !!(regs.y & 0x80);
regs.p.n = (regs.y & 0x80);
regs.p.z = (regs.y == 0);
}
@ -128,8 +128,8 @@ void SMPcore::op_div_ya_x() {
op_io();
ya = regs.ya;
//overflow set if quotient >= 256
regs.p.v = !!(regs.y >= regs.x);
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
regs.p.v = (regs.y >= regs.x);
regs.p.h = ((regs.y & 15) >= (regs.x & 15));
if(regs.y < (regs.x << 1)) {
//if quotient is <= 511 (will fit into 9-bit result)
regs.a = ya / regs.x;
@ -141,7 +141,7 @@ void SMPcore::op_div_ya_x() {
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
}
//result is set based on a (quotient) only
regs.p.n = !!(regs.a & 0x80);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}

View File

@ -51,7 +51,7 @@ template<int n, int i> void SMPcore::op_mov_reg_dpr() {
template<int n> void SMPcore::op_mov_reg_addr() {
sp = op_readpc() << 0;
sp |= op_readpc() << 8;
regs.r[n] = op_readaddr(sp);
regs.r[n] = op_read(sp);
regs.p.n = (regs.r[n] & 0x80);
regs.p.z = (regs.r[n] == 0);
}
@ -60,7 +60,7 @@ template<int i> void SMPcore::op_mov_a_addrr() {
sp = op_readpc() << 0;
sp |= op_readpc() << 8;
op_io();
regs.a = op_readaddr(sp + regs.r[i]);
regs.a = op_read(sp + regs.r[i]);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
@ -70,7 +70,7 @@ void SMPcore::op_mov_a_idpx() {
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
regs.a = op_readaddr(sp);
regs.a = op_read(sp);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
@ -80,7 +80,7 @@ void SMPcore::op_mov_a_idpy() {
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
regs.a = op_readaddr(sp + regs.y);
regs.a = op_read(sp + regs.y);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
@ -128,8 +128,8 @@ template<int n, int i> void SMPcore::op_mov_dpr_reg() {
template<int n> void SMPcore::op_mov_addr_reg() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
op_readaddr(dp);
op_writeaddr(dp, regs.r[n]);
op_read(dp);
op_write(dp, regs.r[n]);
}
template<int i> void SMPcore::op_mov_addrr_a() {
@ -137,8 +137,8 @@ template<int i> void SMPcore::op_mov_addrr_a() {
dp |= op_readpc() << 8;
op_io();
dp += regs.r[i];
op_readaddr(dp);
op_writeaddr(dp, regs.a);
op_read(dp);
op_write(dp, regs.a);
}
void SMPcore::op_mov_idpx_a() {
@ -147,8 +147,8 @@ void SMPcore::op_mov_idpx_a() {
sp += regs.x;
dp = op_readdp(sp + 0) << 0;
dp |= op_readdp(sp + 1) << 8;
op_readaddr(dp);
op_writeaddr(dp, regs.a);
op_read(dp);
op_write(dp, regs.a);
}
void SMPcore::op_mov_idpy_a() {
@ -157,8 +157,8 @@ void SMPcore::op_mov_idpy_a() {
dp |= op_readdp(sp + 1) << 8;
op_io();
dp += regs.y;
op_readaddr(dp);
op_writeaddr(dp, regs.a);
op_read(dp);
op_write(dp, regs.a);
}
void SMPcore::op_movw_ya_dp() {
@ -182,7 +182,7 @@ void SMPcore::op_mov1_c_bit() {
sp |= op_readpc() << 8;
bit = sp >> 13;
sp &= 0x1fff;
rd = op_readaddr(sp);
rd = op_read(sp);
regs.p.c = (rd & (1 << bit));
}
@ -191,10 +191,10 @@ void SMPcore::op_mov1_bit_c() {
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd = op_read(dp);
(regs.p.c) ? rd |= (1 << bit) : rd &= ~(1 << bit);
op_io();
op_writeaddr(dp, rd);
op_write(dp, rd);
}
#endif

View File

@ -82,8 +82,8 @@ void SMPcore::op_jmp_iaddrx() {
dp |= op_readpc() << 8;
op_io();
dp += regs.x;
rd = op_readaddr(dp + 0) << 0;
rd |= op_readaddr(dp + 1) << 8;
rd = op_read(dp + 0) << 0;
rd |= op_read(dp + 1) << 8;
regs.pc = rd;
}
@ -93,8 +93,8 @@ void SMPcore::op_call() {
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
regs.pc = rd;
}
@ -102,48 +102,48 @@ void SMPcore::op_pcall() {
rd = op_readpc();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
regs.pc = 0xff00 | rd;
}
template<int n> void SMPcore::op_tcall() {
dp = 0xffde - (n << 1);
rd = op_readaddr(dp + 0) << 0;
rd |= op_readaddr(dp + 1) << 8;
rd = op_read(dp + 0) << 0;
rd |= op_read(dp + 1) << 8;
op_io();
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
regs.pc = rd;
}
void SMPcore::op_brk() {
rd = op_readaddr(0xffde) << 0;
rd |= op_readaddr(0xffdf) << 8;
rd = op_read(0xffde) << 0;
rd |= op_read(0xffdf) << 8;
op_io();
op_io();
op_writestack(regs.pc >> 8);
op_writestack(regs.pc >> 0);
op_writestack(regs.p);
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
op_writesp(regs.p);
regs.pc = rd;
regs.p.b = 1;
regs.p.i = 0;
}
void SMPcore::op_ret() {
rd = op_readstack() << 0;
rd |= op_readstack() << 8;
rd = op_readsp() << 0;
rd |= op_readsp() << 8;
op_io();
op_io();
regs.pc = rd;
}
void SMPcore::op_reti() {
regs.p = op_readstack();
rd = op_readstack() << 0;
rd |= op_readstack() << 8;
regs.p = op_readsp();
rd = op_readsp() << 0;
rd |= op_readsp() << 8;
op_io();
op_io();
regs.pc = rd;

View File

@ -32,7 +32,7 @@ template<uint8 (SMPcore::*op)(uint8, uint8), int n>
void SMPcore::op_read_reg_addr() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_read(dp);
regs.r[n] = (this->*op)(regs.r[n], rd);
}
@ -41,7 +41,7 @@ void SMPcore::op_read_a_addrr() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
op_io();
rd = op_readaddr(dp + regs.r[i]);
rd = op_read(dp + regs.r[i]);
regs.a = (this->*op)(regs.a, rd);
}
@ -51,7 +51,7 @@ void SMPcore::op_read_a_idpx() {
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp);
rd = op_read(sp);
regs.a = (this->*op)(regs.a, rd);
}
@ -61,7 +61,7 @@ void SMPcore::op_read_a_idpy() {
op_io();
sp = op_readdp(dp + 0) << 0;
sp |= op_readdp(dp + 1) << 8;
rd = op_readaddr(sp + regs.y);
rd = op_read(sp + regs.y);
regs.a = (this->*op)(regs.a, rd);
}
@ -117,7 +117,7 @@ template<int op> void SMPcore::op_and1_bit() {
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd = op_read(dp);
regs.p.c = regs.p.c & ((bool)(rd & (1 << bit)) ^ op);
}
@ -126,7 +126,7 @@ void SMPcore::op_eor1_bit() {
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd = op_read(dp);
op_io();
regs.p.c = regs.p.c ^ (bool)(rd & (1 << bit));
}
@ -136,9 +136,9 @@ void SMPcore::op_not1_bit() {
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd = op_read(dp);
rd ^= 1 << bit;
op_writeaddr(dp, rd);
op_write(dp, rd);
}
template<int op> void SMPcore::op_or1_bit() {
@ -146,7 +146,7 @@ template<int op> void SMPcore::op_or1_bit() {
dp |= op_readpc() << 8;
bit = dp >> 13;
dp &= 0x1fff;
rd = op_readaddr(dp);
rd = op_read(dp);
op_io();
regs.p.c = regs.p.c | ((bool)(rd & (1 << bit)) ^ op);
}

View File

@ -27,20 +27,20 @@ template<uint8 (SMPcore::*op)(uint8)>
void SMPcore::op_adjust_addr() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_read(dp);
rd = (this->*op)(rd);
op_writeaddr(dp, rd);
op_write(dp, rd);
}
template<int op>
void SMPcore::op_adjust_addr_a() {
dp = op_readpc() << 0;
dp |= op_readpc() << 8;
rd = op_readaddr(dp);
rd = op_read(dp);
regs.p.n = ((regs.a - rd) & 0x80);
regs.p.z = ((regs.a - rd) == 0);
op_readaddr(dp);
op_writeaddr(dp, (op ? rd | regs.a : rd & ~regs.a));
op_read(dp);
op_write(dp, (op ? rd | regs.a : rd & ~regs.a));
}
template<int adjust>

View File

@ -20,74 +20,67 @@ void SMP::port_write(uint2 port, uint8 data) {
}
alwaysinline uint8 SMP::op_busread(uint16 addr) {
uint8 r;
if((addr & 0xfff0) == 0x00f0) { //00f0-00ff
if((addr & 0xfff0) != 0x00f0) return ram_read(addr);
unsigned result;
switch(addr) {
case 0xf0: { //TEST -- write-only register
r = 0x00;
} break;
case 0xf0: //TEST -- write-only register
return 0x00;
case 0xf1: { //CONTROL -- write-only register
r = 0x00;
} break;
case 0xf1: //CONTROL -- write-only register
return 0x00;
case 0xf2: { //DSPADDR
r = status.dsp_addr;
} break;
case 0xf2: //DSPADDR
return status.dsp_addr;
case 0xf3: { //DSPDATA
case 0xf3: //DSPDATA
//0x80-0xff are read-only mirrors of 0x00-0x7f
r = dsp.read(status.dsp_addr & 0x7f);
} break;
return dsp.read(status.dsp_addr & 0x7f);
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
case 0xf7: //CPUIO3
synchronize_cpu();
r = cpu.port_read(addr);
} break;
return cpu.port_read(addr);
case 0xf8: { //RAM0
r = status.ram00f8;
} break;
case 0xf8: //RAM0
return status.ram00f8;
case 0xf9: { //RAM1
r = status.ram00f9;
} break;
case 0xf9: //RAM1
return status.ram00f9;
case 0xfa: //T0TARGET
case 0xfb: //T1TARGET
case 0xfc: { //T2TARGET -- write-only registers
r = 0x00;
} break;
case 0xfc: //T2TARGET -- write-only registers
return 0x00;
case 0xfd: { //T0OUT -- 4-bit counter value
r = timer0.stage3_ticks & 15;
case 0xfd: //T0OUT -- 4-bit counter value
result = timer0.stage3_ticks & 15;
timer0.stage3_ticks = 0;
} break;
return result;
case 0xfe: { //T1OUT -- 4-bit counter value
r = timer1.stage3_ticks & 15;
case 0xfe: //T1OUT -- 4-bit counter value
result = timer1.stage3_ticks & 15;
timer1.stage3_ticks = 0;
} break;
return result;
case 0xff: { //T2OUT -- 4-bit counter value
r = timer2.stage3_ticks & 15;
case 0xff: //T2OUT -- 4-bit counter value
result = timer2.stage3_ticks & 15;
timer2.stage3_ticks = 0;
} break;
}
} else {
r = ram_read(addr);
return result;
}
return r;
return 0x00; //never used, avoids compiler warning
}
alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
if((addr & 0xfff0) == 0x00f0) { //$00f0-00ff
ram_write(addr, data); //all writes, even to MMIO registers, appear on bus
if((addr & 0xfff0) != 0x00f0) return;
switch(addr) {
case 0xf0: { //TEST
case 0xf0: //TEST
if(regs.p.p) break; //writes only valid when P flag is clear
status.clock_speed = (data >> 6) & 3;
@ -99,12 +92,12 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
status.timer_step = (1 << status.clock_speed) + (2 << status.timer_speed);
timer0.sync_stage1();
timer1.sync_stage1();
timer2.sync_stage1();
} break;
timer0.synchronize_stage1();
timer1.synchronize_stage1();
timer2.synchronize_stage1();
break;
case 0xf1: { //CONTROL
case 0xf1: //CONTROL
status.iplrom_enable = data & 0x80;
if(data & 0x30) {
@ -139,56 +132,50 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
timer0.stage3_ticks = 0;
}
timer0.enable = data & 0x01;
} break;
break;
case 0xf2: { //DSPADDR
case 0xf2: //DSPADDR
status.dsp_addr = data;
} break;
break;
case 0xf3: { //DSPDATA
//0x80-0xff are read-only mirrors of 0x00-0x7f
if(!(status.dsp_addr & 0x80)) {
case 0xf3: //DSPDATA
if(status.dsp_addr & 0x80) break; //0x80-0xff are read-only mirrors of 0x00-0x7f
dsp.write(status.dsp_addr & 0x7f, data);
}
} break;
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: { //CPUIO3
case 0xf7: //CPUIO3
synchronize_cpu();
port_write(addr, data);
} break;
break;
case 0xf8: { //RAM0
case 0xf8: //RAM0
status.ram00f8 = data;
} break;
break;
case 0xf9: { //RAM1
case 0xf9: //RAM1
status.ram00f9 = data;
} break;
break;
case 0xfa: { //T0TARGET
case 0xfa: //T0TARGET
timer0.target = data;
} break;
break;
case 0xfb: { //T1TARGET
case 0xfb: //T1TARGET
timer1.target = data;
} break;
break;
case 0xfc: { //T2TARGET
case 0xfc: //T2TARGET
timer2.target = data;
} break;
break;
case 0xfd: //T0OUT
case 0xfe: //T1OUT
case 0xff: { //T2OUT -- read-only registers
} break;
case 0xff: //T2OUT -- read-only registers
break;
}
}
//all writes, even to MMIO registers, appear on bus
ram_write(addr, data);
}
void SMP::op_io() {

View File

@ -25,7 +25,7 @@ void SMP::cycle_edge() {
}
template<unsigned timer_frequency>
void SMP::sSMPTimer<timer_frequency>::tick() {
void SMP::Timer<timer_frequency>::tick() {
//stage 0 increment
stage0_ticks += smp.status.timer_step;
if(stage0_ticks < timer_frequency) return;
@ -33,11 +33,11 @@ void SMP::sSMPTimer<timer_frequency>::tick() {
//stage 1 increment
stage1_ticks ^= 1;
sync_stage1();
synchronize_stage1();
}
template<unsigned frequency>
void SMP::sSMPTimer<frequency>::sync_stage1() {
template<unsigned timer_frequency>
void SMP::Timer<timer_frequency>::synchronize_stage1() {
bool new_line = stage1_ticks;
if(smp.status.timers_enable == false) new_line = false;
if(smp.status.timers_disable == true) new_line = false;
@ -48,13 +48,11 @@ void SMP::sSMPTimer<frequency>::sync_stage1() {
//stage 2 increment
if(enable == false) return;
stage2_ticks++;
if(stage2_ticks != target) return;
if(++stage2_ticks != target) return;
//stage 3 increment
stage2_ticks = 0;
stage3_ticks++;
stage3_ticks &= 15;
}
#endif

View File

@ -1,21 +1,21 @@
template<unsigned timer_frequency>
class sSMPTimer {
class Timer {
public:
uint8 stage0_ticks;
uint8 stage1_ticks;
uint8 stage2_ticks;
uint8 stage3_ticks;
uint4 stage3_ticks;
bool current_line;
bool enable;
uint8 target;
void tick();
void sync_stage1();
void synchronize_stage1();
};
sSMPTimer<192> timer0;
sSMPTimer<192> timer1;
sSMPTimer< 24> timer2;
Timer<192> timer0;
Timer<192> timer1;
Timer< 24> timer2;
alwaysinline void add_clocks(unsigned clocks);
alwaysinline void cycle_edge();

View File

@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "078.03";
static const char Version[] = "078.04";
static const unsigned SerializerVersion = 20;
}
}

View File

@ -6,10 +6,12 @@ void FileBrowser::create() {
browseButton.setText("...");
upButton.setText("..");
const unsigned sq = browseButton.minimumGeometry().height;
layout.setMargin(5);
pathLayout.append(pathBox, ~0, 0, 5);
pathLayout.append(browseButton, 25, 25, 5);
pathLayout.append(upButton, 25, 25 );
pathLayout.append(browseButton, sq, sq, 5);
pathLayout.append(upButton, sq, sq );
layout.append(pathLayout, 5);
layout.append(contentsBox, ~0, ~0 );
append(layout);

View File

@ -10,14 +10,16 @@ void SingleSlotLoader::create() {
slotBrowse.setText("...");
okButton.setText("Ok");
const unsigned sq = baseBrowse.minimumGeometry().height;
layout.setMargin(5);
baseLayout.append(baseLabel, 40, 0, 5);
baseLayout.append(basePath, ~0, 0, 5);
baseLayout.append(baseBrowse, 25, 25 );
baseLayout.append(baseBrowse, sq, sq );
layout.append(baseLayout, 5);
slotLayout.append(slotLabel, 40, 0, 5);
slotLayout.append(slotPath, ~0, 0, 5);
slotLayout.append(slotBrowse, 25, 25 );
slotLayout.append(slotBrowse, sq, sq );
layout.append(slotLayout, 5);
controlLayout.append(spacer, ~0, 0 );
controlLayout.append(okButton, 80, 0 );
@ -103,18 +105,20 @@ void DoubleSlotLoader::create() {
slotBBrowse.setText("...");
okButton.setText("Ok");
const unsigned sq = baseBrowse.minimumGeometry().height;
layout.setMargin(5);
baseLayout.append(baseLabel, 40, 0, 5);
baseLayout.append(basePath, ~0, 0, 5);
baseLayout.append(baseBrowse, 25, 25 );
baseLayout.append(baseBrowse, sq, sq );
layout.append(baseLayout, 5);
slotALayout.append(slotALabel, 40, 0, 5);
slotALayout.append(slotAPath, ~0, 0, 5);
slotALayout.append(slotABrowse, 25, 25 );
slotALayout.append(slotABrowse, sq, sq );
layout.append(slotALayout, 5);
slotBLayout.append(slotBLabel, 40, 0, 5);
slotBLayout.append(slotBPath, ~0, 0, 5);
slotBLayout.append(slotBBrowse, 25, 25 );
slotBLayout.append(slotBBrowse, sq, sq );
layout.append(slotBLayout, 5);
controlLayout.append(spacer, ~0, 0 );
controlLayout.append(okButton, 80, 0 );