From 09b326ae86388746d471f39dedda1f5fb429c8cd Mon Sep 17 00:00:00 2001 From: byuu Date: Sun, 12 Jun 2005 08:15:22 +0000 Subject: [PATCH] Update to bsnes v007 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have done quite a bit, so I´ll try my best to recap most of the fixes since the last release... - HDMA was not running during DMA transfers - Emulator did not recognize any filetype other than .smc - Added configuration file support and imported my vector/string/config libraries into bsnes - Added option to use system RAM instead of video RAM for display, this can greatly increase speed on certain video cards - Increased speed by ~15% by adding 256x224 renderer (still very buggy when the SNES mixes video modes mid-frame) - mvn/mvp opcodes were not setting the DB register - Fixed joypad input in many games (Super Mario: All Stars, Dragon Quest III, etc.) - Major speedup with frakeskip option - Fixed default aspect ratio when emulator is first started There´s probably a lot more, but that´s all I remember offhand... this release should be a lot closer to the quality of v0.005a, but still needs a bit more polishing. --- bsnes.cfg | 21 + bsnes_g2.exe | Bin 229376 -> 270336 bytes demo_1.smc | Bin 0 -> 131584 bytes demo_1.srm | Bin 0 -> 131072 bytes demo_2.smc | Bin 0 -> 131584 bytes demo_2.srm | Bin 0 -> 131072 bytes src/base.h | 18 +- src/clock/bclock/bclock.cpp | 48 +- src/clock/bclock/bclock.h | 4 +- src/clock/clock.h | 1 - src/cpu/bcpu/bcpu.cpp | 44 +- src/cpu/bcpu/bcpu.h | 262 ++-------- src/cpu/bcpu/bcpu_exec.cpp | 793 +++++++++++++++++++----------- src/cpu/bcpu/bcpu_mmio.cpp | 36 +- src/cpu/bcpu/bcpu_op_adc.cpp | 34 +- src/cpu/bcpu/bcpu_op_and.cpp | 34 +- src/cpu/bcpu/bcpu_op_cmp.cpp | 34 +- src/cpu/bcpu/bcpu_op_eor.cpp | 34 +- src/cpu/bcpu/bcpu_op_incdec.cpp | 28 -- src/cpu/bcpu/bcpu_op_lda.cpp | 34 +- src/cpu/bcpu/bcpu_op_misc.cpp | 132 ++--- src/cpu/bcpu/bcpu_op_ora.cpp | 34 +- src/cpu/bcpu/bcpu_op_pc.cpp | 9 +- src/cpu/bcpu/bcpu_op_sbc.cpp | 34 +- src/cpu/bcpu/bcpu_op_shift.cpp | 40 -- src/cpu/bcpu/bcpu_op_sta.cpp | 28 -- src/cpu/bcpu/bcpu_op_stack.cpp | 23 +- src/lib/libbase.h | 30 ++ src/lib/libconfig.cpp | 304 ++++++++++++ src/lib/libconfig.h | 51 ++ src/lib/libstring.cpp | 338 +++++++++++++ src/lib/libstring.h | 276 +++++++++++ src/lib/libstring_math.cpp | 177 +++++++ src/lib/libstring_replace.cpp | 82 +++ src/lib/libstring_split.cpp | 41 ++ src/lib/libstring_sprintf.cpp | 69 +++ src/lib/libvector.h | 71 +++ src/memory/bmemory/bmemory.cpp | 9 + src/memory/bmemory/bmemory.h | 3 + src/memory/memory.h | 3 + src/ppu/bppu/bppu.cpp | 19 +- src/ppu/bppu/bppu_mmio.cpp | 15 +- src/ppu/bppu/bppu_render.cpp | 2 +- src/ppu/bppu/bppu_render.h | 4 +- src/ppu/bppu/bppu_render_main.cpp | 33 +- src/ppu/ppu.cpp | 18 +- src/ppu/ppu.h | 18 +- src/reader/reader.cpp | 14 +- src/snes/snes.cpp | 6 +- src/snes/snes.h | 1 + src/win/Makefile | 9 + src/win/bsnes.cpp | 37 +- src/win/bsnes.h | 7 + src/win/config.cpp | 15 + src/win/lib.cpp | 38 -- src/win/timer.cpp | 43 ++ src/win/ui.cpp | 5 +- src/win/ui.h | 9 +- src/win/ui_main.cpp | 27 +- src/win/ui_render.cpp | 239 ++++++--- src/win/winmain.cpp | 15 +- src/win/winmain.h | 5 + 62 files changed, 2571 insertions(+), 1187 deletions(-) create mode 100644 bsnes.cfg create mode 100644 demo_1.smc create mode 100644 demo_1.srm create mode 100644 demo_2.smc create mode 100644 demo_2.srm create mode 100644 src/lib/libbase.h create mode 100644 src/lib/libconfig.cpp create mode 100644 src/lib/libconfig.h create mode 100644 src/lib/libstring.cpp create mode 100644 src/lib/libstring.h create mode 100644 src/lib/libstring_math.cpp create mode 100644 src/lib/libstring_replace.cpp create mode 100644 src/lib/libstring_split.cpp create mode 100644 src/lib/libstring_sprintf.cpp create mode 100644 src/lib/libvector.h create mode 100644 src/win/config.cpp create mode 100644 src/win/timer.cpp diff --git a/bsnes.cfg b/bsnes.cfg new file mode 100644 index 00000000..f9249f54 --- /dev/null +++ b/bsnes.cfg @@ -0,0 +1,21 @@ +#[bsnes v0.007 configuration file] + +#[video mode] +# 0: 256x224w +# 1: 512x448w +# 2: 960x720w +video.mode = 1 + +#[video memory type] +# true: video ram (VRAM) +# false: system ram (SRAM) +# +# VRAM results in the image being stretched in hardware, +# which is generally much faster, and automatically adds +# bilinear filtering (if the card supports it). +# +# However, some video cards end up taking a major speed +# loss when this option is enabled. It is also the only +# way to guarantee that the output image will not be +# filtered. +video.use_vram = true diff --git a/bsnes_g2.exe b/bsnes_g2.exe index 02e0cd2644ae99431216858ed8eb239ab5d167ee..2b27685d9ea8df226e75c437340638e25e58a38b 100644 GIT binary patch literal 270336 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%0AH*R(<)@?agOK^i|hL(`lx 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%0DoH>ZDg5$7wti%6F;?gy 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

>S60SRfDjG7#jOz8c#^~!( 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 diff --git a/demo_1.smc b/demo_1.smc new file mode 100644 index 0000000000000000000000000000000000000000..b2716e5b774793d00dc2a2889e3e9c17b6636e97 GIT binary patch literal 131584 zcmeIuyA8rH5C-6b20B)-*?^UhTu?wz?2;l2WRNV$!x9Z6pnQLEx<_?igb*M=fB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7)-ABaob#s~^YZBBFh`!A>o)N{ z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5*BpTN1^N=@}XURp`5)RxBK zdfM)H5u1qDH@*9v`XQ#i6#@hZ5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N v0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAQ15e{iQ0D literal 0 HcmV?d00001 diff --git a/demo_1.srm b/demo_1.srm new file mode 100644 index 0000000000000000000000000000000000000000..e2c8fe92d8237d3c9169891e23a1b7d6ae8e0dcb GIT binary patch literal 131072 zcmeIuF#!Mo0K%a4Pwin1h(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* W1`HT5V8DO@0|pEjFkrxdfe#D-9smIV literal 0 HcmV?d00001 diff --git a/demo_2.smc b/demo_2.smc new file mode 100644 index 0000000000000000000000000000000000000000..fb32878fdd85105f3801e46fc570937f88b72167 GIT binary patch literal 131584 zcmeIuxedZV5CzbI1TtFKr32Ft5|RS~4tX6CxPdKXo8+)WLJ7$42ctQnc@aW@009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5LmWAi<~nj}WmhA&RJ+`c z^^m9MvUPkYwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* W1`HT5V8DO@0|pEjFkrxdfe#D-9smIV literal 0 HcmV?d00001 diff --git a/src/base.h b/src/base.h index 0e35f1c8..0be99a9b 100644 --- a/src/base.h +++ b/src/base.h @@ -1,20 +1,4 @@ -//platform-independant includes -#include -#include -#include - -//typecasts -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long ulong; - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned long uint32; - -typedef signed char int8; -typedef signed short int16; -typedef signed long int32; +#include "lib/libbase.h" //structs typedef struct { diff --git a/src/clock/bclock/bclock.cpp b/src/clock/bclock/bclock.cpp index b46ccf8f..4c38f5d9 100644 --- a/src/clock/bclock/bclock.cpp +++ b/src/clock/bclock/bclock.cpp @@ -71,9 +71,7 @@ void bClock::inc_vcounter() { cc1.frame_lines = 262; } } - cc1.render_frame = true; - cpu->frame(); - if(frameskip.notify_ppu == true)ppu->frame(); + signal_frame = true; } if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) { @@ -83,13 +81,7 @@ void bClock::inc_vcounter() { } cc1.dram_refreshed = false; - - cpu->scanline(); - if(frameskip.notify_ppu == true)ppu->scanline(); - -//if(status.vcounter == visible_scanlines()) { -// cc1.render_frame = true; -//} + signal_scanline = true; } /* @@ -121,12 +113,6 @@ uint32 new_cycles, cycles; inc_vcounter(); } } - cc1.last_pos = cc1.pos; - - if(cc1.pos > cc1.frequency) { - cc1.pos -= cc1.frequency; - cc1.last_pos -= cc1.frequency; - } if(status.interlace == false && status.interlace_field == 1 && status.vcounter == 240) { status.hcounter = status.hcycles >> 2; @@ -134,6 +120,12 @@ uint32 new_cycles, cycles; //1288 = 322 * 4, 1306 = 326 * 4 + 2 status.hcounter = (status.hcycles - ((status.hcycles > 1288) << 1) - ((status.hcycles > 1306) << 1)) >> 2; } + + cc1.last_pos = cc1.pos; + if(cc1.pos > cc1.frequency) { + cc1.pos -= cc1.frequency; + cc1.last_pos -= cc1.frequency; + } } void bClock::set_frameskip(uint8 fs) { @@ -141,21 +133,11 @@ void bClock::set_frameskip(uint8 fs) { frameskip.new_count = fs; } -bool bClock::update_frame() { - if(cc1.render_frame == true) { - cc1.render_frame = false; - return true; - } - return false; -} - void bClock::power() { reset(); } void bClock::reset() { - cc1.render_frame = false; - //upon SNES reset, start at scanline 0 non-interlace cc1.frame_cycles = 262 * 1364; cc1.frame_lines = 262; @@ -178,6 +160,8 @@ void bClock::reset() { cc2.pos = 0; + signal_scanline = false; + signal_frame = false; sync(); } @@ -185,6 +169,18 @@ void bClock::run() { cpu->run(); if(frameskip.notify_ppu == true)ppu->run(); sync(); + + if(signal_frame == true) { + signal_frame = false; + cpu->frame(); + if(frameskip.notify_ppu == true)ppu->frame(); + } + + if(signal_scanline == true) { + signal_scanline = false; + cpu->scanline(); + if(frameskip.notify_ppu == true)ppu->scanline(); + } } void bClock::add_cc1_cycles(uint32 cycles) { diff --git a/src/clock/bclock/bclock.h b/src/clock/bclock/bclock.h index befb6448..89b32d2b 100644 --- a/src/clock/bclock/bclock.h +++ b/src/clock/bclock/bclock.h @@ -4,6 +4,7 @@ struct { bool changed, notify_ppu; uint8 count, new_count, pos; }frameskip; +bool signal_scanline, signal_frame; void frameskip_update_status(); void inc_vcounter(); void dram_refresh_test(); @@ -16,8 +17,6 @@ public: uint16 line_cycles; bool dram_refreshed; //whether or not dram has been refreshed on this line uint16 dram_refresh_pos; - - bool render_frame; }cc1; struct { uint32 frequency; @@ -25,7 +24,6 @@ public: }cc2; void set_frameskip(uint8 fs); - bool update_frame(); void add_cc1_cycles(uint32 cycles); void add_cc2_cycles(uint32 cycles); diff --git a/src/clock/clock.h b/src/clock/clock.h index 551a1eb1..4795c330 100644 --- a/src/clock/clock.h +++ b/src/clock/clock.h @@ -22,7 +22,6 @@ public: virtual uint16 visible_scanlines(); virtual void set_frameskip(uint8 fs); - virtual bool update_frame() = 0; virtual void add_cc1_cycles(uint32 cycles) = 0; virtual void add_cc2_cycles(uint32 cycles) = 0; diff --git a/src/cpu/bcpu/bcpu.cpp b/src/cpu/bcpu/bcpu.cpp index bc9d9c0d..9552a471 100644 --- a/src/cpu/bcpu/bcpu.cpp +++ b/src/cpu/bcpu/bcpu.cpp @@ -58,17 +58,26 @@ void bCPU::irq(uint16 addr) { void bCPU::run() { uint16 v, h, hc, vs; + v = clock->vcounter(); + h = clock->hcounter(); + hc = clock->hcycles(); + vs = clock->visible_scanlines(); + +//HDMA test + if(v < vs && h >= 278) { + if(status.hdma_triggered == false) { + status.hdma_triggered = true; + dma->hdma_run(); + return; + } + } + switch(cpustate) { case CPUSTATE_RUN: case CPUSTATE_WAI: - v = clock->vcounter(); - h = clock->hcounter(); - hc = clock->hcycles(); - vs = clock->visible_scanlines(); - //NMI test if(v >= (vs + 1) && status.nmi_triggered == false) { - if((v == (vs + 1) && hc >= 12) || (v >= (vs + 1))) { + if((v == (vs + 1) && hc >= 12) || (v > (vs + 1))) { status.nmi_triggered = true; status.nmi_pin = 0; if(status.nmi_enabled == true) { @@ -104,12 +113,6 @@ uint16 v, h, hc, vs; } } - //HDMA test - if(v < vs && h >= 278 && dma->hdma_triggered == false) { - dma->hdma_run(); - dma->hdma_triggered = true; - } - exec_opcode(); break; case CPUSTATE_DMA: @@ -123,16 +126,25 @@ uint16 v, h, hc, vs; void bCPU::scanline() { uint16 v = clock->vcounter(); + status.hdma_triggered = false; + if(v == 225 && status.auto_joypad_poll == true) { snes->poll_input(); +//When the SNES auto-polls the joypads, it writes 1, then 0 to +//$4016, then reads from each 16 times to get the joypad state +//information. As a result, the joypad read positions are set +//to 16 after such a poll. Position 16 is the controller +//connected status bit. + status.joypad1_read_pos = 16; } if(status.virq_enabled == false) { status.irq_pin = 1; } - dma->hdma_triggered = false; } void bCPU::frame() { + status.hdma_triggered = false; + status.nmi_triggered = false; status.r4210_read = false; @@ -165,6 +177,10 @@ void bCPU::reset() { dma->reset(); mmio_reset(); + optbl = optbl_e; + + status.hdma_triggered = false; + status.nmi_triggered = false; status.nmi_pin = 1; status.r4210_read = false; @@ -290,6 +306,8 @@ void bCPU::stack_write(uint8 value) { bCPU::bCPU() { dma = new bDMA(this); mmio = new bCPUMMIO(this); + + init_op_tables(); } bCPU::~bCPU() { diff --git a/src/cpu/bcpu/bcpu.h b/src/cpu/bcpu/bcpu.h index bb66f18b..8bbcb791 100644 --- a/src/cpu/bcpu/bcpu.h +++ b/src/cpu/bcpu/bcpu.h @@ -30,8 +30,6 @@ struct { uint32 hdma_address, hdma_iaddress; bool hdma_completed; }channel[8]; -bool hdma_triggered; - void hdma_write(uint8 i, uint8 l, uint8 x); void hdma_run(); void hdma_initialize(); @@ -58,6 +56,10 @@ bCPU *cpu; }; class bCPU : public CPU { +private: +typedef void (bCPU::*op)(); +op *optbl, optbl_e[256], optbl_MX[256], optbl_Mx[256], optbl_mX[256], optbl_mx[256]; + public: enum { CPUSTATE_RUN = 0, CPUSTATE_DMA, CPUSTATE_WAI, CPUSTATE_STP }; uint8 cpustate; @@ -72,6 +74,8 @@ CPUReg24 aa, rd; uint8 dp, sp; struct { + bool hdma_triggered; + bool nmi_triggered; bool nmi_pin; bool r4210_read; @@ -175,406 +179,285 @@ struct { void cpu_c6(uint16 a); void cpu_io(); +//opcode functions + void init_op_tables(); + //op_adc - void flags_adc_b(); - void flags_adc_w(); + inline void flags_adc_b(); + inline void flags_adc_w(); void op_adc_constb(); void op_adc_constw(); - void op_adc_const(); void op_adc_addrb(); void op_adc_addrw(); - void op_adc_addr(); void op_adc_addrxb(); void op_adc_addrxw(); - void op_adc_addrx(); void op_adc_dpb(); void op_adc_dpw(); - void op_adc_dp(); void op_adc_idpb(); void op_adc_idpw(); - void op_adc_idp(); void op_adc_ildpb(); void op_adc_ildpw(); - void op_adc_ildp(); void op_adc_longb(); void op_adc_longw(); - void op_adc_long(); void op_adc_longxb(); void op_adc_longxw(); - void op_adc_longx(); void op_adc_addryb(); void op_adc_addryw(); - void op_adc_addry(); void op_adc_dpxb(); void op_adc_dpxw(); - void op_adc_dpx(); void op_adc_idpxb(); void op_adc_idpxw(); - void op_adc_idpx(); void op_adc_idpyb(); void op_adc_idpyw(); - void op_adc_idpy(); void op_adc_ildpyb(); void op_adc_ildpyw(); - void op_adc_ildpy(); void op_adc_srb(); void op_adc_srw(); - void op_adc_sr(); void op_adc_isryb(); void op_adc_isryw(); - void op_adc_isry(); //op_and - void flags_and_b(); - void flags_and_w(); + inline void flags_and_b(); + inline void flags_and_w(); void op_and_constb(); void op_and_constw(); - void op_and_const(); void op_and_addrb(); void op_and_addrw(); - void op_and_addr(); void op_and_addrxb(); void op_and_addrxw(); - void op_and_addrx(); void op_and_dpb(); void op_and_dpw(); - void op_and_dp(); void op_and_idpb(); void op_and_idpw(); - void op_and_idp(); void op_and_ildpb(); void op_and_ildpw(); - void op_and_ildp(); void op_and_longb(); void op_and_longw(); - void op_and_long(); void op_and_longxb(); void op_and_longxw(); - void op_and_longx(); void op_and_addryb(); void op_and_addryw(); - void op_and_addry(); void op_and_dpxb(); void op_and_dpxw(); - void op_and_dpx(); void op_and_idpxb(); void op_and_idpxw(); - void op_and_idpx(); void op_and_idpyb(); void op_and_idpyw(); - void op_and_idpy(); void op_and_ildpyb(); void op_and_ildpyw(); - void op_and_ildpy(); void op_and_srb(); void op_and_srw(); - void op_and_sr(); void op_and_isryb(); void op_and_isryw(); - void op_and_isry(); //op_cmp - void flags_cmp_b(); - void flags_cmp_w(); + inline void flags_cmp_b(); + inline void flags_cmp_w(); void op_cmp_constb(); void op_cmp_constw(); - void op_cmp_const(); void op_cmp_addrb(); void op_cmp_addrw(); - void op_cmp_addr(); void op_cmp_addrxb(); void op_cmp_addrxw(); - void op_cmp_addrx(); void op_cmp_dpb(); void op_cmp_dpw(); - void op_cmp_dp(); void op_cmp_idpb(); void op_cmp_idpw(); - void op_cmp_idp(); void op_cmp_ildpb(); void op_cmp_ildpw(); - void op_cmp_ildp(); void op_cmp_longb(); void op_cmp_longw(); - void op_cmp_long(); void op_cmp_longxb(); void op_cmp_longxw(); - void op_cmp_longx(); void op_cmp_addryb(); void op_cmp_addryw(); - void op_cmp_addry(); void op_cmp_dpxb(); void op_cmp_dpxw(); - void op_cmp_dpx(); void op_cmp_idpxb(); void op_cmp_idpxw(); - void op_cmp_idpx(); void op_cmp_idpyb(); void op_cmp_idpyw(); - void op_cmp_idpy(); void op_cmp_ildpyb(); void op_cmp_ildpyw(); - void op_cmp_ildpy(); void op_cmp_srb(); void op_cmp_srw(); - void op_cmp_sr(); void op_cmp_isryb(); void op_cmp_isryw(); - void op_cmp_isry(); //op_eor - void flags_eor_b(); - void flags_eor_w(); + inline void flags_eor_b(); + inline void flags_eor_w(); void op_eor_constb(); void op_eor_constw(); - void op_eor_const(); void op_eor_addrb(); void op_eor_addrw(); - void op_eor_addr(); void op_eor_addrxb(); void op_eor_addrxw(); - void op_eor_addrx(); void op_eor_dpb(); void op_eor_dpw(); - void op_eor_dp(); void op_eor_idpb(); void op_eor_idpw(); - void op_eor_idp(); void op_eor_ildpb(); void op_eor_ildpw(); - void op_eor_ildp(); void op_eor_longb(); void op_eor_longw(); - void op_eor_long(); void op_eor_longxb(); void op_eor_longxw(); - void op_eor_longx(); void op_eor_addryb(); void op_eor_addryw(); - void op_eor_addry(); void op_eor_dpxb(); void op_eor_dpxw(); - void op_eor_dpx(); void op_eor_idpxb(); void op_eor_idpxw(); - void op_eor_idpx(); void op_eor_idpyb(); void op_eor_idpyw(); - void op_eor_idpy(); void op_eor_ildpyb(); void op_eor_ildpyw(); - void op_eor_ildpy(); void op_eor_srb(); void op_eor_srw(); - void op_eor_sr(); void op_eor_isryb(); void op_eor_isryw(); - void op_eor_isry(); //op_incdec void op_incb(); void op_incw(); - void op_inc(); void op_inc_addrb(); void op_inc_addrw(); - void op_inc_addr(); void op_inc_addrxb(); void op_inc_addrxw(); - void op_inc_addrx(); void op_inc_dpb(); void op_inc_dpw(); - void op_inc_dp(); void op_inc_dpxb(); void op_inc_dpxw(); - void op_inc_dpx(); void op_inxb(); void op_inxw(); - void op_inx(); void op_inyb(); void op_inyw(); - void op_iny(); void op_decb(); void op_decw(); - void op_dec(); void op_dec_addrb(); void op_dec_addrw(); - void op_dec_addr(); void op_dec_addrxb(); void op_dec_addrxw(); - void op_dec_addrx(); void op_dec_dpb(); void op_dec_dpw(); - void op_dec_dp(); void op_dec_dpxb(); void op_dec_dpxw(); - void op_dec_dpx(); void op_dexb(); void op_dexw(); - void op_dex(); void op_deyb(); void op_deyw(); - void op_dey(); //op_lda - void flags_lda_b(); - void flags_lda_w(); + inline void flags_lda_b(); + inline void flags_lda_w(); void op_lda_constb(); void op_lda_constw(); - void op_lda_const(); void op_lda_addrb(); void op_lda_addrw(); - void op_lda_addr(); void op_lda_addrxb(); void op_lda_addrxw(); - void op_lda_addrx(); void op_lda_dpb(); void op_lda_dpw(); - void op_lda_dp(); void op_lda_idpb(); void op_lda_idpw(); - void op_lda_idp(); void op_lda_ildpb(); void op_lda_ildpw(); - void op_lda_ildp(); void op_lda_longb(); void op_lda_longw(); - void op_lda_long(); void op_lda_longxb(); void op_lda_longxw(); - void op_lda_longx(); void op_lda_addryb(); void op_lda_addryw(); - void op_lda_addry(); void op_lda_dpxb(); void op_lda_dpxw(); - void op_lda_dpx(); void op_lda_idpxb(); void op_lda_idpxw(); - void op_lda_idpx(); void op_lda_idpyb(); void op_lda_idpyw(); - void op_lda_idpy(); void op_lda_ildpyb(); void op_lda_ildpyw(); - void op_lda_ildpy(); void op_lda_srb(); void op_lda_srw(); - void op_lda_sr(); void op_lda_isryb(); void op_lda_isryw(); - void op_lda_isry(); //op_misc - void flags_bit_b(); - void flags_bit_w(); + inline void flags_bit_b(); + inline void flags_bit_w(); void op_bit_constb(); void op_bit_constw(); - void op_bit_const(); void op_bit_addrb(); void op_bit_addrw(); - void op_bit_addr(); void op_bit_addrxb(); void op_bit_addrxw(); - void op_bit_addrx(); void op_bit_dpb(); void op_bit_dpw(); - void op_bit_dp(); void op_bit_dpxb(); void op_bit_dpxw(); - void op_bit_dpx(); - void flags_cpx_b(); - void flags_cpx_w(); + inline void flags_cpx_b(); + inline void flags_cpx_w(); void op_cpx_constb(); void op_cpx_constw(); - void op_cpx_const(); void op_cpx_addrb(); void op_cpx_addrw(); - void op_cpx_addr(); void op_cpx_dpb(); void op_cpx_dpw(); - void op_cpx_dp(); - void flags_cpy_b(); - void flags_cpy_w(); + inline void flags_cpy_b(); + inline void flags_cpy_w(); void op_cpy_constb(); void op_cpy_constw(); - void op_cpy_const(); void op_cpy_addrb(); void op_cpy_addrw(); - void op_cpy_addr(); void op_cpy_dpb(); void op_cpy_dpw(); - void op_cpy_dp(); - void flags_ldx_b(); - void flags_ldx_w(); + inline void flags_ldx_b(); + inline void flags_ldx_w(); void op_ldx_constb(); void op_ldx_constw(); - void op_ldx_const(); void op_ldx_addrb(); void op_ldx_addrw(); - void op_ldx_addr(); void op_ldx_addryb(); void op_ldx_addryw(); - void op_ldx_addry(); void op_ldx_dpb(); void op_ldx_dpw(); - void op_ldx_dp(); void op_ldx_dpyb(); void op_ldx_dpyw(); - void op_ldx_dpy(); - void flags_ldy_b(); - void flags_ldy_w(); + inline void flags_ldy_b(); + inline void flags_ldy_w(); void op_ldy_constb(); void op_ldy_constw(); - void op_ldy_const(); void op_ldy_addrb(); void op_ldy_addrw(); - void op_ldy_addr(); void op_ldy_addrxb(); void op_ldy_addrxw(); - void op_ldy_addrx(); void op_ldy_dpb(); void op_ldy_dpw(); - void op_ldy_dp(); void op_ldy_dpxb(); void op_ldy_dpxw(); - void op_ldy_dpx(); void op_stx_addrb(); void op_stx_addrw(); - void op_stx_addr(); void op_stx_dpb(); void op_stx_dpw(); - void op_stx_dp(); void op_stx_dpyb(); void op_stx_dpyw(); - void op_stx_dpy(); void op_sty_addrb(); void op_sty_addrw(); - void op_sty_addr(); void op_sty_dpb(); void op_sty_dpw(); - void op_sty_dp(); void op_sty_dpxb(); void op_sty_dpxw(); - void op_sty_dpx(); void op_stz_addrb(); void op_stz_addrw(); - void op_stz_addr(); void op_stz_addrxb(); void op_stz_addrxw(); - void op_stz_addrx(); void op_stz_dpb(); void op_stz_dpw(); - void op_stz_dp(); void op_stz_dpxb(); void op_stz_dpxw(); - void op_stz_dpx(); void op_xba(); void op_trb_addrb(); void op_trb_addrw(); - void op_trb_addr(); void op_trb_dpb(); void op_trb_dpw(); - void op_trb_dp(); void op_tsb_addrb(); void op_tsb_addrw(); - void op_tsb_addr(); void op_tsb_dpb(); void op_tsb_dpw(); - void op_tsb_dp(); void op_mvn(); void op_mvp(); void op_brk(); @@ -595,80 +478,57 @@ struct { void op_sep(); void op_taxb(); void op_taxw(); - void op_tax(); void op_tayb(); void op_tayw(); - void op_tay(); void op_tcd(); void op_tcs(); void op_tdc(); void op_tsc(); void op_tsxb(); void op_tsxw(); - void op_tsx(); void op_txab(); void op_txaw(); - void op_txa(); void op_txsb(); void op_txsw(); - void op_txs(); void op_txyb(); void op_txyw(); - void op_txy(); void op_tyab(); void op_tyaw(); - void op_tya(); void op_tyxb(); void op_tyxw(); - void op_tyx(); //op_ora - void flags_ora_b(); - void flags_ora_w(); + inline void flags_ora_b(); + inline void flags_ora_w(); void op_ora_constb(); void op_ora_constw(); - void op_ora_const(); void op_ora_addrb(); void op_ora_addrw(); - void op_ora_addr(); void op_ora_addrxb(); void op_ora_addrxw(); - void op_ora_addrx(); void op_ora_dpb(); void op_ora_dpw(); - void op_ora_dp(); void op_ora_idpb(); void op_ora_idpw(); - void op_ora_idp(); void op_ora_ildpb(); void op_ora_ildpw(); - void op_ora_ildp(); void op_ora_longb(); void op_ora_longw(); - void op_ora_long(); void op_ora_longxb(); void op_ora_longxw(); - void op_ora_longx(); void op_ora_addryb(); void op_ora_addryw(); - void op_ora_addry(); void op_ora_dpxb(); void op_ora_dpxw(); - void op_ora_dpx(); void op_ora_idpxb(); void op_ora_idpxw(); - void op_ora_idpx(); void op_ora_idpyb(); void op_ora_idpyw(); - void op_ora_idpy(); void op_ora_ildpyb(); void op_ora_ildpyw(); - void op_ora_ildpy(); void op_ora_srb(); void op_ora_srw(); - void op_ora_sr(); void op_ora_isryb(); void op_ora_isryw(); - void op_ora_isry(); //op_pc void op_jmp_addr(); void op_jmp_long(); @@ -680,7 +540,6 @@ struct { void op_jsr_iaddrx(); void op_rtie(); void op_rtin(); - void op_rti(); void op_rts(); void op_rtl(); void op_bra(); @@ -694,183 +553,128 @@ struct { void op_bvc(); void op_bvs(); //op_sbc - void flags_sbc_b(); - void flags_sbc_w(); + inline void flags_sbc_b(); + inline void flags_sbc_w(); void op_sbc_constb(); void op_sbc_constw(); - void op_sbc_const(); void op_sbc_addrb(); void op_sbc_addrw(); - void op_sbc_addr(); void op_sbc_addrxb(); void op_sbc_addrxw(); - void op_sbc_addrx(); void op_sbc_dpb(); void op_sbc_dpw(); - void op_sbc_dp(); void op_sbc_idpb(); void op_sbc_idpw(); - void op_sbc_idp(); void op_sbc_ildpb(); void op_sbc_ildpw(); - void op_sbc_ildp(); void op_sbc_longb(); void op_sbc_longw(); - void op_sbc_long(); void op_sbc_longxb(); void op_sbc_longxw(); - void op_sbc_longx(); void op_sbc_addryb(); void op_sbc_addryw(); - void op_sbc_addry(); void op_sbc_dpxb(); void op_sbc_dpxw(); - void op_sbc_dpx(); void op_sbc_idpxb(); void op_sbc_idpxw(); - void op_sbc_idpx(); void op_sbc_idpyb(); void op_sbc_idpyw(); - void op_sbc_idpy(); void op_sbc_ildpyb(); void op_sbc_ildpyw(); - void op_sbc_ildpy(); void op_sbc_srb(); void op_sbc_srw(); - void op_sbc_sr(); void op_sbc_isryb(); void op_sbc_isryw(); - void op_sbc_isry(); //op_shift void op_aslb(); void op_aslw(); - void op_asl(); void op_asl_addrb(); void op_asl_addrw(); - void op_asl_addr(); void op_asl_addrxb(); void op_asl_addrxw(); - void op_asl_addrx(); void op_asl_dpb(); void op_asl_dpw(); - void op_asl_dp(); void op_asl_dpxb(); void op_asl_dpxw(); - void op_asl_dpx(); void op_lsrb(); void op_lsrw(); - void op_lsr(); void op_lsr_addrb(); void op_lsr_addrw(); - void op_lsr_addr(); void op_lsr_addrxb(); void op_lsr_addrxw(); - void op_lsr_addrx(); void op_lsr_dpb(); void op_lsr_dpw(); - void op_lsr_dp(); void op_lsr_dpxb(); void op_lsr_dpxw(); - void op_lsr_dpx(); void op_rolb(); void op_rolw(); - void op_rol(); void op_rol_addrb(); void op_rol_addrw(); - void op_rol_addr(); void op_rol_addrxb(); void op_rol_addrxw(); - void op_rol_addrx(); void op_rol_dpb(); void op_rol_dpw(); - void op_rol_dp(); void op_rol_dpxb(); void op_rol_dpxw(); - void op_rol_dpx(); void op_rorb(); void op_rorw(); - void op_ror(); void op_ror_addrb(); void op_ror_addrw(); - void op_ror_addr(); void op_ror_addrxb(); void op_ror_addrxw(); - void op_ror_addrx(); void op_ror_dpb(); void op_ror_dpw(); - void op_ror_dp(); void op_ror_dpxb(); void op_ror_dpxw(); - void op_ror_dpx(); //op_sta void op_sta_addrb(); void op_sta_addrw(); - void op_sta_addr(); void op_sta_addrxb(); void op_sta_addrxw(); - void op_sta_addrx(); void op_sta_dpb(); void op_sta_dpw(); - void op_sta_dp(); void op_sta_idpb(); void op_sta_idpw(); - void op_sta_idp(); void op_sta_ildpb(); void op_sta_ildpw(); - void op_sta_ildp(); void op_sta_longb(); void op_sta_longw(); - void op_sta_long(); void op_sta_longxb(); void op_sta_longxw(); - void op_sta_longx(); void op_sta_addryb(); void op_sta_addryw(); - void op_sta_addry(); void op_sta_dpxb(); void op_sta_dpxw(); - void op_sta_dpx(); void op_sta_idpxb(); void op_sta_idpxw(); - void op_sta_idpx(); void op_sta_idpyb(); void op_sta_idpyw(); - void op_sta_idpy(); void op_sta_ildpyb(); void op_sta_ildpyw(); - void op_sta_ildpy(); void op_sta_srb(); void op_sta_srw(); - void op_sta_sr(); void op_sta_isryb(); void op_sta_isryw(); - void op_sta_isry(); //op_stack void op_phab(); void op_phaw(); - void op_pha(); void op_phb(); void op_phd(); void op_phk(); void op_php(); void op_phxb(); void op_phxw(); - void op_phx(); void op_phyb(); void op_phyw(); - void op_phy(); void op_plab(); void op_plaw(); - void op_pla(); void op_plb(); void op_pld(); void op_plp(); void op_plxb(); void op_plxw(); - void op_plx(); void op_plyb(); void op_plyw(); - void op_ply(); void op_pea(); void op_pei(); void op_per(); diff --git a/src/cpu/bcpu/bcpu_exec.cpp b/src/cpu/bcpu/bcpu_exec.cpp index 5b147ef5..b809ce03 100644 --- a/src/cpu/bcpu/bcpu_exec.cpp +++ b/src/cpu/bcpu/bcpu_exec.cpp @@ -1,280 +1,519 @@ void bCPU::exec_opcode() { -byte op; - op = op_read(); - switch(op) { -/* 0x */ - case 0x00:op_brk(); break; - case 0x01:op_ora_idpx(); break; - case 0x02:op_cop(); break; - case 0x03:op_ora_sr(); break; - case 0x04:op_tsb_dp(); break; - case 0x05:op_ora_dp(); break; - case 0x06:op_asl_dp(); break; - case 0x07:op_ora_ildp(); break; - case 0x08:op_php(); break; - case 0x09:op_ora_const();break; - case 0x0a:op_asl(); break; - case 0x0b:op_phd(); break; - case 0x0c:op_tsb_addr(); break; - case 0x0d:op_ora_addr(); break; - case 0x0e:op_asl_addr(); break; - case 0x0f:op_ora_long(); break; -/* 1x */ - case 0x10:op_bpl(); break; - case 0x11:op_ora_idpy(); break; - case 0x12:op_ora_idp(); break; - case 0x13:op_ora_isry(); break; - case 0x14:op_trb_dp(); break; - case 0x15:op_ora_dpx(); break; - case 0x16:op_asl_dpx(); break; - case 0x17:op_ora_ildpy();break; - case 0x18:op_clc(); break; - case 0x19:op_ora_addry();break; - case 0x1a:op_inc(); break; - case 0x1b:op_tcs(); break; - case 0x1c:op_trb_addr(); break; - case 0x1d:op_ora_addrx();break; - case 0x1e:op_asl_addrx();break; - case 0x1f:op_ora_longx();break; -/* 2x */ - case 0x20:op_jsr_addr(); break; - case 0x21:op_and_idpx(); break; - case 0x22:op_jsr_long(); break; - case 0x23:op_and_sr(); break; - case 0x24:op_bit_dp(); break; - case 0x25:op_and_dp(); break; - case 0x26:op_rol_dp(); break; - case 0x27:op_and_ildp(); break; - case 0x28:op_plp(); break; - case 0x29:op_and_const();break; - case 0x2a:op_rol(); break; - case 0x2b:op_pld(); break; - case 0x2c:op_bit_addr(); break; - case 0x2d:op_and_addr(); break; - case 0x2e:op_rol_addr(); break; - case 0x2f:op_and_long(); break; -/* 3x */ - case 0x30:op_bmi(); break; - case 0x31:op_and_idpy(); break; - case 0x32:op_and_idp(); break; - case 0x33:op_and_isry(); break; - case 0x34:op_bit_dpx(); break; - case 0x35:op_and_dpx(); break; - case 0x36:op_rol_dpx(); break; - case 0x37:op_and_ildpy();break; - case 0x38:op_sec(); break; - case 0x39:op_and_addry();break; - case 0x3a:op_dec(); break; - case 0x3b:op_tsc(); break; - case 0x3c:op_bit_addrx();break; - case 0x3d:op_and_addrx();break; - case 0x3e:op_rol_addrx();break; - case 0x3f:op_and_longx();break; -/* 4x */ - case 0x40:op_rti(); break; - case 0x41:op_eor_idpx(); break; - case 0x42:op_wdm(); break; - case 0x43:op_eor_sr(); break; - case 0x44:op_mvp(); break; - case 0x45:op_eor_dp(); break; - case 0x46:op_lsr_dp(); break; - case 0x47:op_eor_ildp(); break; - case 0x48:op_pha(); break; - case 0x49:op_eor_const();break; - case 0x4a:op_lsr(); break; - case 0x4b:op_phk(); break; - case 0x4c:op_jmp_addr(); break; - case 0x4d:op_eor_addr(); break; - case 0x4e:op_lsr_addr(); break; - case 0x4f:op_eor_long(); break; -/* 5x */ - case 0x50:op_bvc(); break; - case 0x51:op_eor_idpy(); break; - case 0x52:op_eor_idp(); break; - case 0x53:op_eor_isry(); break; - case 0x54:op_mvn(); break; - case 0x55:op_eor_dpx(); break; - case 0x56:op_lsr_dpx(); break; - case 0x57:op_eor_ildpy();break; - case 0x58:op_cli(); break; - case 0x59:op_eor_addry();break; - case 0x5a:op_phy(); break; - case 0x5b:op_tcd(); break; - case 0x5c:op_jmp_long(); break; - case 0x5d:op_eor_addrx();break; - case 0x5e:op_lsr_addrx();break; - case 0x5f:op_eor_longx();break; -/* 6x */ - case 0x60:op_rts(); break; - case 0x61:op_adc_idpx(); break; - case 0x62:op_per(); break; - case 0x63:op_adc_sr(); break; - case 0x64:op_stz_dp(); break; - case 0x65:op_adc_dp(); break; - case 0x66:op_ror_dp(); break; - case 0x67:op_adc_ildp(); break; - case 0x68:op_pla(); break; - case 0x69:op_adc_const();break; - case 0x6a:op_ror(); break; - case 0x6b:op_rtl(); break; - case 0x6c:op_jmp_iaddr();break; - case 0x6d:op_adc_addr(); break; - case 0x6e:op_ror_addr(); break; - case 0x6f:op_adc_long(); break; -/* 7x */ - case 0x70:op_bvs(); break; - case 0x71:op_adc_idpy(); break; - case 0x72:op_adc_idp(); break; - case 0x73:op_adc_isry(); break; - case 0x74:op_stz_dpx(); break; - case 0x75:op_adc_dpx(); break; - case 0x76:op_ror_dpx(); break; - case 0x77:op_adc_ildpy(); break; - case 0x78:op_sei(); break; - case 0x79:op_adc_addry(); break; - case 0x7a:op_ply(); break; - case 0x7b:op_tdc(); break; - case 0x7c:op_jmp_iaddrx();break; - case 0x7d:op_adc_addrx(); break; - case 0x7e:op_ror_addrx(); break; - case 0x7f:op_adc_longx(); break; -/* 8x */ - case 0x80:op_bra(); break; - case 0x81:op_sta_idpx(); break; - case 0x82:op_brl(); break; - case 0x83:op_sta_sr(); break; - case 0x84:op_sty_dp(); break; - case 0x85:op_sta_dp(); break; - case 0x86:op_stx_dp(); break; - case 0x87:op_sta_ildp(); break; - case 0x88:op_dey(); break; - case 0x89:op_bit_const();break; - case 0x8a:op_txa(); break; - case 0x8b:op_phb(); break; - case 0x8c:op_sty_addr(); break; - case 0x8d:op_sta_addr(); break; - case 0x8e:op_stx_addr(); break; - case 0x8f:op_sta_long(); break; -/* 9x */ - case 0x90:op_bcc(); break; - case 0x91:op_sta_idpy(); break; - case 0x92:op_sta_idp(); break; - case 0x93:op_sta_isry(); break; - case 0x94:op_sty_dpx(); break; - case 0x95:op_sta_dpx(); break; - case 0x96:op_stx_dpy(); break; - case 0x97:op_sta_ildpy();break; - case 0x98:op_tya(); break; - case 0x99:op_sta_addry();break; - case 0x9a:op_txs(); break; - case 0x9b:op_txy(); break; - case 0x9c:op_stz_addr(); break; - case 0x9d:op_sta_addrx();break; - case 0x9e:op_stz_addrx();break; - case 0x9f:op_sta_longx();break; -/* ax */ - case 0xa0:op_ldy_const();break; - case 0xa1:op_lda_idpx(); break; - case 0xa2:op_ldx_const();break; - case 0xa3:op_lda_sr(); break; - case 0xa4:op_ldy_dp(); break; - case 0xa5:op_lda_dp(); break; - case 0xa6:op_ldx_dp(); break; - case 0xa7:op_lda_ildp(); break; - case 0xa8:op_tay(); break; - case 0xa9:op_lda_const();break; - case 0xaa:op_tax(); break; - case 0xab:op_plb(); break; - case 0xac:op_ldy_addr(); break; - case 0xad:op_lda_addr(); break; - case 0xae:op_ldx_addr(); break; - case 0xaf:op_lda_long(); break; -/* bx */ - case 0xb0:op_bcs(); break; - case 0xb1:op_lda_idpy(); break; - case 0xb2:op_lda_idp(); break; - case 0xb3:op_lda_isry(); break; - case 0xb4:op_ldy_dpx(); break; - case 0xb5:op_lda_dpx(); break; - case 0xb6:op_ldx_dpy(); break; - case 0xb7:op_lda_ildpy();break; - case 0xb8:op_clv(); break; - case 0xb9:op_lda_addry();break; - case 0xba:op_tsx(); break; - case 0xbb:op_tyx(); break; - case 0xbc:op_ldy_addrx();break; - case 0xbd:op_lda_addrx();break; - case 0xbe:op_ldx_addry();break; - case 0xbf:op_lda_longx();break; -/* cx */ - case 0xc0:op_cpy_const();break; - case 0xc1:op_cmp_idpx(); break; - case 0xc2:op_rep(); break; - case 0xc3:op_cmp_sr(); break; - case 0xc4:op_cpy_dp(); break; - case 0xc5:op_cmp_dp(); break; - case 0xc6:op_dec_dp(); break; - case 0xc7:op_cmp_ildp(); break; - case 0xc8:op_iny(); break; - case 0xc9:op_cmp_const();break; - case 0xca:op_dex(); break; - case 0xcb:op_wai(); break; - case 0xcc:op_cpy_addr(); break; - case 0xcd:op_cmp_addr(); break; - case 0xce:op_dec_addr(); break; - case 0xcf:op_cmp_long(); break; -/* dx */ - case 0xd0:op_bne(); break; - case 0xd1:op_cmp_idpy(); break; - case 0xd2:op_cmp_idp(); break; - case 0xd3:op_cmp_isry(); break; - case 0xd4:op_pei(); break; - case 0xd5:op_cmp_dpx(); break; - case 0xd6:op_dec_dpx(); break; - case 0xd7:op_cmp_ildpy(); break; - case 0xd8:op_cld(); break; - case 0xd9:op_cmp_addry(); break; - case 0xda:op_phx(); break; - case 0xdb:op_stp(); break; - case 0xdc:op_jmp_iladdr();break; - case 0xdd:op_cmp_addrx(); break; - case 0xde:op_dec_addrx(); break; - case 0xdf:op_cmp_longx(); break; -/* ex */ - case 0xe0:op_cpx_const();break; - case 0xe1:op_sbc_idpx(); break; - case 0xe2:op_sep(); break; - case 0xe3:op_sbc_sr(); break; - case 0xe4:op_cpx_dp(); break; - case 0xe5:op_sbc_dp(); break; - case 0xe6:op_inc_dp(); break; - case 0xe7:op_sbc_ildp(); break; - case 0xe8:op_inx(); break; - case 0xe9:op_sbc_const();break; - case 0xea:op_nop(); break; - case 0xeb:op_xba(); break; - case 0xec:op_cpx_addr(); break; - case 0xed:op_sbc_addr(); break; - case 0xee:op_inc_addr(); break; - case 0xef:op_sbc_long(); break; -/* fx */ - case 0xf0:op_beq(); break; - case 0xf1:op_sbc_idpy(); break; - case 0xf2:op_sbc_idp(); break; - case 0xf3:op_sbc_isry(); break; - case 0xf4:op_pea(); break; - case 0xf5:op_sbc_dpx(); break; - case 0xf6:op_inc_dpx(); break; - case 0xf7:op_sbc_ildpy(); break; - case 0xf8:op_sed(); break; - case 0xf9:op_sbc_addry(); break; - case 0xfa:op_plx(); break; - case 0xfb:op_xce(); break; - case 0xfc:op_jsr_iaddrx();break; - case 0xfd:op_sbc_addrx(); break; - case 0xfe:op_inc_addrx(); break; - case 0xff:op_sbc_longx(); break; - } - + (this->*optbl[op_read()])(); snes->notify(SNES::CPU_EXEC_OPCODE); } + +void bCPU::init_op_tables() { + optbl = optbl_e; + +/* 0x */ + optbl[0x00] = op_brk; + optbl[0x01] = op_ora_idpxb; + optbl[0x02] = op_cop; + optbl[0x03] = op_ora_srb; + optbl[0x04] = op_tsb_dpb; + optbl[0x05] = op_ora_dpb; + optbl[0x06] = op_asl_dpb; + optbl[0x07] = op_ora_ildpb; + optbl[0x08] = op_php; + optbl[0x09] = op_ora_constb; + optbl[0x0a] = op_aslb; + optbl[0x0b] = op_phd; + optbl[0x0c] = op_tsb_addrb; + optbl[0x0d] = op_ora_addrb; + optbl[0x0e] = op_asl_addrb; + optbl[0x0f] = op_ora_longb; +/* 1x */ + optbl[0x10] = op_bpl; + optbl[0x11] = op_ora_idpyb; + optbl[0x12] = op_ora_idpb; + optbl[0x13] = op_ora_isryb; + optbl[0x14] = op_trb_dpb; + optbl[0x15] = op_ora_dpxb; + optbl[0x16] = op_asl_dpxb; + optbl[0x17] = op_ora_ildpyb; + optbl[0x18] = op_clc; + optbl[0x19] = op_ora_addryb; + optbl[0x1a] = op_incb; + optbl[0x1b] = op_tcs; + optbl[0x1c] = op_trb_addrb; + optbl[0x1d] = op_ora_addrxb; + optbl[0x1e] = op_asl_addrxb; + optbl[0x1f] = op_ora_longxb; +/* 2x */ + optbl[0x20] = op_jsr_addr; + optbl[0x21] = op_and_idpxb; + optbl[0x22] = op_jsr_long; + optbl[0x23] = op_and_srb; + optbl[0x24] = op_bit_dpb; + optbl[0x25] = op_and_dpb; + optbl[0x26] = op_rol_dpb; + optbl[0x27] = op_and_ildpb; + optbl[0x28] = op_plp; + optbl[0x29] = op_and_constb; + optbl[0x2a] = op_rolb; + optbl[0x2b] = op_pld; + optbl[0x2c] = op_bit_addrb; + optbl[0x2d] = op_and_addrb; + optbl[0x2e] = op_rol_addrb; + optbl[0x2f] = op_and_longb; +/* 3x */ + optbl[0x30] = op_bmi; + optbl[0x31] = op_and_idpyb; + optbl[0x32] = op_and_idpb; + optbl[0x33] = op_and_isryb; + optbl[0x34] = op_bit_dpxb; + optbl[0x35] = op_and_dpxb; + optbl[0x36] = op_rol_dpxb; + optbl[0x37] = op_and_ildpyb; + optbl[0x38] = op_sec; + optbl[0x39] = op_and_addryb; + optbl[0x3a] = op_decb; + optbl[0x3b] = op_tsc; + optbl[0x3c] = op_bit_addrxb; + optbl[0x3d] = op_and_addrxb; + optbl[0x3e] = op_rol_addrxb; + optbl[0x3f] = op_and_longxb; +/* 4x */ + optbl[0x40] = op_rtie; + optbl[0x41] = op_eor_idpxb; + optbl[0x42] = op_wdm; + optbl[0x43] = op_eor_srb; + optbl[0x44] = op_mvp; + optbl[0x45] = op_eor_dpb; + optbl[0x46] = op_lsr_dpb; + optbl[0x47] = op_eor_ildpb; + optbl[0x48] = op_phab; + optbl[0x49] = op_eor_constb; + optbl[0x4a] = op_lsrb; + optbl[0x4b] = op_phk; + optbl[0x4c] = op_jmp_addr; + optbl[0x4d] = op_eor_addrb; + optbl[0x4e] = op_lsr_addrb; + optbl[0x4f] = op_eor_longb; +/* 5x */ + optbl[0x50] = op_bvc; + optbl[0x51] = op_eor_idpyb; + optbl[0x52] = op_eor_idpb; + optbl[0x53] = op_eor_isryb; + optbl[0x54] = op_mvn; + optbl[0x55] = op_eor_dpxb; + optbl[0x56] = op_lsr_dpxb; + optbl[0x57] = op_eor_ildpyb; + optbl[0x58] = op_cli; + optbl[0x59] = op_eor_addryb; + optbl[0x5a] = op_phyb; + optbl[0x5b] = op_tcd; + optbl[0x5c] = op_jmp_long; + optbl[0x5d] = op_eor_addrxb; + optbl[0x5e] = op_lsr_addrxb; + optbl[0x5f] = op_eor_longxb; +/* 6x */ + optbl[0x60] = op_rts; + optbl[0x61] = op_adc_idpxb; + optbl[0x62] = op_per; + optbl[0x63] = op_adc_srb; + optbl[0x64] = op_stz_dpb; + optbl[0x65] = op_adc_dpb; + optbl[0x66] = op_ror_dpb; + optbl[0x67] = op_adc_ildpb; + optbl[0x68] = op_plab; + optbl[0x69] = op_adc_constb; + optbl[0x6a] = op_rorb; + optbl[0x6b] = op_rtl; + optbl[0x6c] = op_jmp_iaddr; + optbl[0x6d] = op_adc_addrb; + optbl[0x6e] = op_ror_addrb; + optbl[0x6f] = op_adc_longb; +/* 7x */ + optbl[0x70] = op_bvs; + optbl[0x71] = op_adc_idpyb; + optbl[0x72] = op_adc_idpb; + optbl[0x73] = op_adc_isryb; + optbl[0x74] = op_stz_dpxb; + optbl[0x75] = op_adc_dpxb; + optbl[0x76] = op_ror_dpxb; + optbl[0x77] = op_adc_ildpyb; + optbl[0x78] = op_sei; + optbl[0x79] = op_adc_addryb; + optbl[0x7a] = op_plyb; + optbl[0x7b] = op_tdc; + optbl[0x7c] = op_jmp_iaddrx; + optbl[0x7d] = op_adc_addrxb; + optbl[0x7e] = op_ror_addrxb; + optbl[0x7f] = op_adc_longxb; +/* 8x */ + optbl[0x80] = op_bra; + optbl[0x81] = op_sta_idpxb; + optbl[0x82] = op_brl; + optbl[0x83] = op_sta_srb; + optbl[0x84] = op_sty_dpb; + optbl[0x85] = op_sta_dpb; + optbl[0x86] = op_stx_dpb; + optbl[0x87] = op_sta_ildpb; + optbl[0x88] = op_deyb; + optbl[0x89] = op_bit_constb; + optbl[0x8a] = op_txab; + optbl[0x8b] = op_phb; + optbl[0x8c] = op_sty_addrb; + optbl[0x8d] = op_sta_addrb; + optbl[0x8e] = op_stx_addrb; + optbl[0x8f] = op_sta_longb; +/* 9x */ + optbl[0x90] = op_bcc; + optbl[0x91] = op_sta_idpyb; + optbl[0x92] = op_sta_idpb; + optbl[0x93] = op_sta_isryb; + optbl[0x94] = op_sty_dpxb; + optbl[0x95] = op_sta_dpxb; + optbl[0x96] = op_stx_dpyb; + optbl[0x97] = op_sta_ildpyb; + optbl[0x98] = op_tyab; + optbl[0x99] = op_sta_addryb; + optbl[0x9a] = op_txsb; + optbl[0x9b] = op_txyb; + optbl[0x9c] = op_stz_addrb; + optbl[0x9d] = op_sta_addrxb; + optbl[0x9e] = op_stz_addrxb; + optbl[0x9f] = op_sta_longxb; +/* ax */ + optbl[0xa0] = op_ldy_constb; + optbl[0xa1] = op_lda_idpxb; + optbl[0xa2] = op_ldx_constb; + optbl[0xa3] = op_lda_srb; + optbl[0xa4] = op_ldy_dpb; + optbl[0xa5] = op_lda_dpb; + optbl[0xa6] = op_ldx_dpb; + optbl[0xa7] = op_lda_ildpb; + optbl[0xa8] = op_tayb; + optbl[0xa9] = op_lda_constb; + optbl[0xaa] = op_taxb; + optbl[0xab] = op_plb; + optbl[0xac] = op_ldy_addrb; + optbl[0xad] = op_lda_addrb; + optbl[0xae] = op_ldx_addrb; + optbl[0xaf] = op_lda_longb; +/* bx */ + optbl[0xb0] = op_bcs; + optbl[0xb1] = op_lda_idpyb; + optbl[0xb2] = op_lda_idpb; + optbl[0xb3] = op_lda_isryb; + optbl[0xb4] = op_ldy_dpxb; + optbl[0xb5] = op_lda_dpxb; + optbl[0xb6] = op_ldx_dpyb; + optbl[0xb7] = op_lda_ildpyb; + optbl[0xb8] = op_clv; + optbl[0xb9] = op_lda_addryb; + optbl[0xba] = op_tsxb; + optbl[0xbb] = op_tyxb; + optbl[0xbc] = op_ldy_addrxb; + optbl[0xbd] = op_lda_addrxb; + optbl[0xbe] = op_ldx_addryb; + optbl[0xbf] = op_lda_longxb; +/* cx */ + optbl[0xc0] = op_cpy_constb; + optbl[0xc1] = op_cmp_idpxb; + optbl[0xc2] = op_rep; + optbl[0xc3] = op_cmp_srb; + optbl[0xc4] = op_cpy_dpb; + optbl[0xc5] = op_cmp_dpb; + optbl[0xc6] = op_dec_dpb; + optbl[0xc7] = op_cmp_ildpb; + optbl[0xc8] = op_inyb; + optbl[0xc9] = op_cmp_constb; + optbl[0xca] = op_dexb; + optbl[0xcb] = op_wai; + optbl[0xcc] = op_cpy_addrb; + optbl[0xcd] = op_cmp_addrb; + optbl[0xce] = op_dec_addrb; + optbl[0xcf] = op_cmp_longb; +/* dx */ + optbl[0xd0] = op_bne; + optbl[0xd1] = op_cmp_idpyb; + optbl[0xd2] = op_cmp_idpb; + optbl[0xd3] = op_cmp_isryb; + optbl[0xd4] = op_pei; + optbl[0xd5] = op_cmp_dpxb; + optbl[0xd6] = op_dec_dpxb; + optbl[0xd7] = op_cmp_ildpyb; + optbl[0xd8] = op_cld; + optbl[0xd9] = op_cmp_addryb; + optbl[0xda] = op_phxb; + optbl[0xdb] = op_stp; + optbl[0xdc] = op_jmp_iladdr; + optbl[0xdd] = op_cmp_addrxb; + optbl[0xde] = op_dec_addrxb; + optbl[0xdf] = op_cmp_longxb; +/* ex */ + optbl[0xe0] = op_cpx_constb; + optbl[0xe1] = op_sbc_idpxb; + optbl[0xe2] = op_sep; + optbl[0xe3] = op_sbc_srb; + optbl[0xe4] = op_cpx_dpb; + optbl[0xe5] = op_sbc_dpb; + optbl[0xe6] = op_inc_dpb; + optbl[0xe7] = op_sbc_ildpb; + optbl[0xe8] = op_inxb; + optbl[0xe9] = op_sbc_constb; + optbl[0xea] = op_nop; + optbl[0xeb] = op_xba; + optbl[0xec] = op_cpx_addrb; + optbl[0xed] = op_sbc_addrb; + optbl[0xee] = op_inc_addrb; + optbl[0xef] = op_sbc_longb; +/* fx */ + optbl[0xf0] = op_beq; + optbl[0xf1] = op_sbc_idpyb; + optbl[0xf2] = op_sbc_idpb; + optbl[0xf3] = op_sbc_isryb; + optbl[0xf4] = op_pea; + optbl[0xf5] = op_sbc_dpxb; + optbl[0xf6] = op_inc_dpxb; + optbl[0xf7] = op_sbc_ildpyb; + optbl[0xf8] = op_sed; + optbl[0xf9] = op_sbc_addryb; + optbl[0xfa] = op_plxb; + optbl[0xfb] = op_xce; + optbl[0xfc] = op_jsr_iaddrx; + optbl[0xfd] = op_sbc_addrxb; + optbl[0xfe] = op_inc_addrxb; + optbl[0xff] = op_sbc_longxb; + + memcpy(optbl_MX, optbl_e, sizeof(optbl_e)); + memcpy(optbl_Mx, optbl_e, sizeof(optbl_e)); + memcpy(optbl_mX, optbl_e, sizeof(optbl_e)); + memcpy(optbl_mx, optbl_e, sizeof(optbl_e)); + +/* adc */ + optbl_mX[0x69] = optbl_mx[0x69] = op_adc_constw; + optbl_mX[0x6d] = optbl_mx[0x6d] = op_adc_addrw; + optbl_mX[0x7d] = optbl_mx[0x7d] = op_adc_addrxw; + optbl_mX[0x65] = optbl_mx[0x65] = op_adc_dpw; + optbl_mX[0x72] = optbl_mx[0x72] = op_adc_idpw; + optbl_mX[0x67] = optbl_mx[0x67] = op_adc_ildpw; + optbl_mX[0x6f] = optbl_mx[0x6f] = op_adc_longw; + optbl_mX[0x7f] = optbl_mx[0x7f] = op_adc_longxw; + optbl_mX[0x79] = optbl_mx[0x79] = op_adc_addryw; + optbl_mX[0x75] = optbl_mx[0x75] = op_adc_dpxw; + optbl_mX[0x61] = optbl_mx[0x61] = op_adc_idpxw; + optbl_mX[0x71] = optbl_mx[0x71] = op_adc_idpyw; + optbl_mX[0x77] = optbl_mx[0x77] = op_adc_ildpyw; + optbl_mX[0x63] = optbl_mx[0x63] = op_adc_srw; + optbl_mX[0x73] = optbl_mx[0x73] = op_adc_isryw; + +/* and */ + optbl_mX[0x29] = optbl_mx[0x29] = op_and_constw; + optbl_mX[0x2d] = optbl_mx[0x2d] = op_and_addrw; + optbl_mX[0x3d] = optbl_mx[0x3d] = op_and_addrxw; + optbl_mX[0x25] = optbl_mx[0x25] = op_and_dpw; + optbl_mX[0x32] = optbl_mx[0x32] = op_and_idpw; + optbl_mX[0x27] = optbl_mx[0x27] = op_and_ildpw; + optbl_mX[0x2f] = optbl_mx[0x2f] = op_and_longw; + optbl_mX[0x3f] = optbl_mx[0x3f] = op_and_longxw; + optbl_mX[0x39] = optbl_mx[0x39] = op_and_addryw; + optbl_mX[0x35] = optbl_mx[0x35] = op_and_dpxw; + optbl_mX[0x21] = optbl_mx[0x21] = op_and_idpxw; + optbl_mX[0x31] = optbl_mx[0x31] = op_and_idpyw; + optbl_mX[0x37] = optbl_mx[0x37] = op_and_ildpyw; + optbl_mX[0x23] = optbl_mx[0x23] = op_and_srw; + optbl_mX[0x33] = optbl_mx[0x33] = op_and_isryw; + +/* cmp */ + optbl_mX[0xc9] = optbl_mx[0xc9] = op_cmp_constw; + optbl_mX[0xcd] = optbl_mx[0xcd] = op_cmp_addrw; + optbl_mX[0xdd] = optbl_mx[0xdd] = op_cmp_addrxw; + optbl_mX[0xc5] = optbl_mx[0xc5] = op_cmp_dpw; + optbl_mX[0xd2] = optbl_mx[0xd2] = op_cmp_idpw; + optbl_mX[0xc7] = optbl_mx[0xc7] = op_cmp_ildpw; + optbl_mX[0xcf] = optbl_mx[0xcf] = op_cmp_longw; + optbl_mX[0xdf] = optbl_mx[0xdf] = op_cmp_longxw; + optbl_mX[0xd9] = optbl_mx[0xd9] = op_cmp_addryw; + optbl_mX[0xd5] = optbl_mx[0xd5] = op_cmp_dpxw; + optbl_mX[0xc1] = optbl_mx[0xc1] = op_cmp_idpxw; + optbl_mX[0xd1] = optbl_mx[0xd1] = op_cmp_idpyw; + optbl_mX[0xd7] = optbl_mx[0xd7] = op_cmp_ildpyw; + optbl_mX[0xc3] = optbl_mx[0xc3] = op_cmp_srw; + optbl_mX[0xd3] = optbl_mx[0xd3] = op_cmp_isryw; + +/* eor */ + optbl_mX[0x49] = optbl_mx[0x49] = op_eor_constw; + optbl_mX[0x4d] = optbl_mx[0x4d] = op_eor_addrw; + optbl_mX[0x5d] = optbl_mx[0x5d] = op_eor_addrxw; + optbl_mX[0x45] = optbl_mx[0x45] = op_eor_dpw; + optbl_mX[0x52] = optbl_mx[0x52] = op_eor_idpw; + optbl_mX[0x47] = optbl_mx[0x47] = op_eor_ildpw; + optbl_mX[0x4f] = optbl_mx[0x4f] = op_eor_longw; + optbl_mX[0x5f] = optbl_mx[0x5f] = op_eor_longxw; + optbl_mX[0x59] = optbl_mx[0x59] = op_eor_addryw; + optbl_mX[0x55] = optbl_mx[0x55] = op_eor_dpxw; + optbl_mX[0x41] = optbl_mx[0x41] = op_eor_idpxw; + optbl_mX[0x51] = optbl_mx[0x51] = op_eor_idpyw; + optbl_mX[0x57] = optbl_mx[0x57] = op_eor_ildpyw; + optbl_mX[0x43] = optbl_mx[0x43] = op_eor_srw; + optbl_mX[0x53] = optbl_mx[0x53] = op_eor_isryw; + +/* lda */ + optbl_mX[0xa9] = optbl_mx[0xa9] = op_lda_constw; + optbl_mX[0xad] = optbl_mx[0xad] = op_lda_addrw; + optbl_mX[0xbd] = optbl_mx[0xbd] = op_lda_addrxw; + optbl_mX[0xa5] = optbl_mx[0xa5] = op_lda_dpw; + optbl_mX[0xb2] = optbl_mx[0xb2] = op_lda_idpw; + optbl_mX[0xa7] = optbl_mx[0xa7] = op_lda_ildpw; + optbl_mX[0xaf] = optbl_mx[0xaf] = op_lda_longw; + optbl_mX[0xbf] = optbl_mx[0xbf] = op_lda_longxw; + optbl_mX[0xb9] = optbl_mx[0xb9] = op_lda_addryw; + optbl_mX[0xb5] = optbl_mx[0xb5] = op_lda_dpxw; + optbl_mX[0xa1] = optbl_mx[0xa1] = op_lda_idpxw; + optbl_mX[0xb1] = optbl_mx[0xb1] = op_lda_idpyw; + optbl_mX[0xb7] = optbl_mx[0xb7] = op_lda_ildpyw; + optbl_mX[0xa3] = optbl_mx[0xa3] = op_lda_srw; + optbl_mX[0xb3] = optbl_mx[0xb3] = op_lda_isryw; + +/* ora */ + optbl_mX[0x09] = optbl_mx[0x09] = op_ora_constw; + optbl_mX[0x0d] = optbl_mx[0x0d] = op_ora_addrw; + optbl_mX[0x1d] = optbl_mx[0x1d] = op_ora_addrxw; + optbl_mX[0x05] = optbl_mx[0x05] = op_ora_dpw; + optbl_mX[0x12] = optbl_mx[0x12] = op_ora_idpw; + optbl_mX[0x07] = optbl_mx[0x07] = op_ora_ildpw; + optbl_mX[0x0f] = optbl_mx[0x0f] = op_ora_longw; + optbl_mX[0x1f] = optbl_mx[0x1f] = op_ora_longxw; + optbl_mX[0x19] = optbl_mx[0x19] = op_ora_addryw; + optbl_mX[0x15] = optbl_mx[0x15] = op_ora_dpxw; + optbl_mX[0x01] = optbl_mx[0x01] = op_ora_idpxw; + optbl_mX[0x11] = optbl_mx[0x11] = op_ora_idpyw; + optbl_mX[0x17] = optbl_mx[0x17] = op_ora_ildpyw; + optbl_mX[0x03] = optbl_mx[0x03] = op_ora_srw; + optbl_mX[0x13] = optbl_mx[0x13] = op_ora_isryw; + +/* sbc */ + optbl_mX[0xe9] = optbl_mx[0xe9] = op_sbc_constw; + optbl_mX[0xed] = optbl_mx[0xed] = op_sbc_addrw; + optbl_mX[0xfd] = optbl_mx[0xfd] = op_sbc_addrxw; + optbl_mX[0xe5] = optbl_mx[0xe5] = op_sbc_dpw; + optbl_mX[0xf2] = optbl_mx[0xf2] = op_sbc_idpw; + optbl_mX[0xe7] = optbl_mx[0xe7] = op_sbc_ildpw; + optbl_mX[0xef] = optbl_mx[0xef] = op_sbc_longw; + optbl_mX[0xff] = optbl_mx[0xff] = op_sbc_longxw; + optbl_mX[0xf9] = optbl_mx[0xf9] = op_sbc_addryw; + optbl_mX[0xf5] = optbl_mx[0xf5] = op_sbc_dpxw; + optbl_mX[0xe1] = optbl_mx[0xe1] = op_sbc_idpxw; + optbl_mX[0xf1] = optbl_mx[0xf1] = op_sbc_idpyw; + optbl_mX[0xf7] = optbl_mx[0xf7] = op_sbc_ildpyw; + optbl_mX[0xe3] = optbl_mx[0xe3] = op_sbc_srw; + optbl_mX[0xf3] = optbl_mx[0xf3] = op_sbc_isryw; + +/* sta */ + optbl_mX[0x8d] = optbl_mx[0x8d] = op_sta_addrw; + optbl_mX[0x9d] = optbl_mx[0x9d] = op_sta_addrxw; + optbl_mX[0x85] = optbl_mx[0x85] = op_sta_dpw; + optbl_mX[0x92] = optbl_mx[0x92] = op_sta_idpw; + optbl_mX[0x87] = optbl_mx[0x87] = op_sta_ildpw; + optbl_mX[0x8f] = optbl_mx[0x8f] = op_sta_longw; + optbl_mX[0x9f] = optbl_mx[0x9f] = op_sta_longxw; + optbl_mX[0x99] = optbl_mx[0x99] = op_sta_addryw; + optbl_mX[0x95] = optbl_mx[0x95] = op_sta_dpxw; + optbl_mX[0x81] = optbl_mx[0x81] = op_sta_idpxw; + optbl_mX[0x91] = optbl_mx[0x91] = op_sta_idpyw; + optbl_mX[0x97] = optbl_mx[0x97] = op_sta_ildpyw; + optbl_mX[0x83] = optbl_mx[0x83] = op_sta_srw; + optbl_mX[0x93] = optbl_mx[0x93] = op_sta_isryw; + +/* incdec */ + optbl_mX[0x1a] = optbl_mx[0x1a] = op_incw; + optbl_mX[0xee] = optbl_mx[0xee] = op_inc_addrw; + optbl_mX[0xfe] = optbl_mx[0xfe] = op_inc_addrxw; + optbl_mX[0xe6] = optbl_mx[0xe6] = op_inc_dpw; + optbl_mX[0xf6] = optbl_mx[0xf6] = op_inc_dpxw; + optbl_mX[0x3a] = optbl_mx[0x3a] = op_decw; + optbl_mX[0xce] = optbl_mx[0xce] = op_dec_addrw; + optbl_mX[0xde] = optbl_mx[0xde] = op_dec_addrxw; + optbl_mX[0xc6] = optbl_mx[0xc6] = op_dec_dpw; + optbl_mX[0xd6] = optbl_mx[0xd6] = op_dec_dpxw; + + optbl_Mx[0xe8] = optbl_mx[0xe8] = op_inxw; + optbl_Mx[0xc8] = optbl_mx[0xc8] = op_inyw; + optbl_Mx[0xca] = optbl_mx[0xca] = op_dexw; + optbl_Mx[0x88] = optbl_mx[0x88] = op_deyw; + +/* misc */ + optbl_mX[0x89] = optbl_mx[0x89] = op_bit_constw; + optbl_mX[0x2c] = optbl_mx[0x2c] = op_bit_addrw; + optbl_mX[0x3c] = optbl_mx[0x3c] = op_bit_addrxw; + optbl_mX[0x24] = optbl_mx[0x24] = op_bit_dpw; + optbl_mX[0x34] = optbl_mx[0x34] = op_bit_dpxw; + optbl_mX[0x9c] = optbl_mx[0x9c] = op_stz_addrw; + optbl_mX[0x9e] = optbl_mx[0x9e] = op_stz_addrxw; + optbl_mX[0x64] = optbl_mx[0x64] = op_stz_dpw; + optbl_mX[0x74] = optbl_mx[0x74] = op_stz_dpxw; + optbl_mX[0x1c] = optbl_mx[0x1c] = op_trb_addrw; + optbl_mX[0x14] = optbl_mx[0x14] = op_trb_dpw; + optbl_mX[0x0c] = optbl_mx[0x0c] = op_tsb_addrw; + optbl_mX[0x04] = optbl_mx[0x04] = op_tsb_dpw; + optbl_mX[0x8a] = optbl_mx[0x8a] = op_txaw; + optbl_mX[0x98] = optbl_mx[0x98] = op_tyaw; + + optbl_Mx[0xe0] = optbl_mx[0xe0] = op_cpx_constw; + optbl_Mx[0xec] = optbl_mx[0xec] = op_cpx_addrw; + optbl_Mx[0xe4] = optbl_mx[0xe4] = op_cpx_dpw; + optbl_Mx[0xc0] = optbl_mx[0xc0] = op_cpy_constw; + optbl_Mx[0xcc] = optbl_mx[0xcc] = op_cpy_addrw; + optbl_Mx[0xc4] = optbl_mx[0xc4] = op_cpy_dpw; + optbl_Mx[0xa2] = optbl_mx[0xa2] = op_ldx_constw; + optbl_Mx[0xae] = optbl_mx[0xae] = op_ldx_addrw; + optbl_Mx[0xbe] = optbl_mx[0xbe] = op_ldx_addryw; + optbl_Mx[0xa6] = optbl_mx[0xa6] = op_ldx_dpw; + optbl_Mx[0xb6] = optbl_mx[0xb6] = op_ldx_dpyw; + optbl_Mx[0xa0] = optbl_mx[0xa0] = op_ldy_constw; + optbl_Mx[0xac] = optbl_mx[0xac] = op_ldy_addrw; + optbl_Mx[0xbc] = optbl_mx[0xbc] = op_ldy_addrxw; + optbl_Mx[0xa4] = optbl_mx[0xa4] = op_ldy_dpw; + optbl_Mx[0xb4] = optbl_mx[0xb4] = op_ldy_dpxw; + optbl_Mx[0x8e] = optbl_mx[0x8e] = op_stx_addrw; + optbl_Mx[0x86] = optbl_mx[0x86] = op_stx_dpw; + optbl_Mx[0x96] = optbl_mx[0x96] = op_stx_dpyw; + optbl_Mx[0x8c] = optbl_mx[0x8c] = op_sty_addrw; + optbl_Mx[0x84] = optbl_mx[0x84] = op_sty_dpw; + optbl_Mx[0x94] = optbl_mx[0x94] = op_sty_dpxw; + optbl_Mx[0xaa] = optbl_mx[0xaa] = op_taxw; + optbl_Mx[0xa8] = optbl_mx[0xa8] = op_tayw; + optbl_Mx[0xba] = optbl_mx[0xba] = op_tsxw; + optbl_Mx[0x9a] = optbl_mx[0x9a] = op_txsw; + optbl_Mx[0x9b] = optbl_mx[0x9b] = op_txyw; + optbl_Mx[0xbb] = optbl_mx[0xbb] = op_tyxw; + +/* pc */ + optbl_MX[0x40] = optbl_Mx[0x40] = op_rtin; + optbl_mX[0x40] = optbl_mx[0x40] = op_rtin; + +/* shift */ + optbl_mX[0x0a] = optbl_mx[0x0a] = op_aslw; + optbl_mX[0x0e] = optbl_mx[0x0e] = op_asl_addrw; + optbl_mX[0x1e] = optbl_mx[0x1e] = op_asl_addrxw; + optbl_mX[0x06] = optbl_mx[0x06] = op_asl_dpw; + optbl_mX[0x16] = optbl_mx[0x16] = op_asl_dpxw; + optbl_mX[0x4a] = optbl_mx[0x4a] = op_lsrw; + optbl_mX[0x4e] = optbl_mx[0x4e] = op_lsr_addrw; + optbl_mX[0x5e] = optbl_mx[0x5e] = op_lsr_addrxw; + optbl_mX[0x46] = optbl_mx[0x46] = op_lsr_dpw; + optbl_mX[0x56] = optbl_mx[0x56] = op_lsr_dpxw; + optbl_mX[0x2a] = optbl_mx[0x2a] = op_rolw; + optbl_mX[0x2e] = optbl_mx[0x2e] = op_rol_addrw; + optbl_mX[0x3e] = optbl_mx[0x3e] = op_rol_addrxw; + optbl_mX[0x26] = optbl_mx[0x26] = op_rol_dpw; + optbl_mX[0x36] = optbl_mx[0x36] = op_rol_dpxw; + optbl_mX[0x6a] = optbl_mx[0x6a] = op_rorw; + optbl_mX[0x6e] = optbl_mx[0x6e] = op_ror_addrw; + optbl_mX[0x7e] = optbl_mx[0x7e] = op_ror_addrxw; + optbl_mX[0x66] = optbl_mx[0x66] = op_ror_dpw; + optbl_mX[0x76] = optbl_mx[0x76] = op_ror_dpxw; + +/* stack */ + optbl_mX[0x48] = optbl_mx[0x48] = op_phaw; + optbl_mX[0x68] = optbl_mx[0x68] = op_plaw; + + optbl_Mx[0xda] = optbl_mx[0xda] = op_phxw; + optbl_Mx[0x5a] = optbl_mx[0x5a] = op_phyw; + optbl_Mx[0xfa] = optbl_mx[0xfa] = op_plxw; + optbl_Mx[0x7a] = optbl_mx[0x7a] = op_plyw; +} diff --git a/src/cpu/bcpu/bcpu_mmio.cpp b/src/cpu/bcpu/bcpu_mmio.cpp index 6d4df3f3..c782ff6d 100644 --- a/src/cpu/bcpu/bcpu_mmio.cpp +++ b/src/cpu/bcpu/bcpu_mmio.cpp @@ -177,7 +177,7 @@ uint8 bCPU::mmio_r4218() { uint8 r = 0x00; uint16 v = clock->vcounter(); if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled - if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input +//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_A) << 7; r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_X) << 6; r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_L) << 5; @@ -190,7 +190,7 @@ uint8 bCPU::mmio_r4219() { uint8 r = 0x00; uint16 v = clock->vcounter(); if(status.auto_joypad_poll == false)return 0x00; //can't read joypad if auto polling not enabled - if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input +//if(v >= 225 && v <= 227)return 0x00; //can't read joypad while SNES is polling input r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_B) << 7; r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_Y) << 6; r |= (uint8)snes->get_input_status(SNES::DEV_JOYPAD1, SNES::JOYPAD_SELECT) << 5; @@ -250,9 +250,11 @@ void bCPU::mmio_w2183(uint8 value) { //JOYSER0 void bCPU::mmio_w4016(uint8 value) { - status.joypad1_strobe_value = value; - if(value == 1)snes->poll_input(); - if(value == 0)status.joypad1_read_pos = 0; + status.joypad1_strobe_value = (value & 1); + if(value == 1) { + snes->poll_input(); + status.joypad1_read_pos = 0; + } } //NMITIMEN @@ -320,22 +322,24 @@ void bCPU::mmio_w420a(uint8 value) { //DMAEN void bCPU::mmio_w420b(uint8 value) { + if(value != 0x00) { + clock->add_cc1_cycles(18); + } + for(int i=0;i<8;i++) { - dma->channel[i].active = !!(value & (1 << i)); - if(dma->channel[i].active == true) { + if(value & (1 << i)) { + dma->channel[i].active = true; dma->channel[i].hdma_active = false; + clock->add_cc1_cycles(8); + cpustate = CPUSTATE_DMA; } } - cpustate = CPUSTATE_DMA; } //HDMAEN void bCPU::mmio_w420c(uint8 value) { for(int i=0;i<8;i++) { dma->channel[i].hdma_active = !!(value & (1 << i)); - if(dma->channel[i].hdma_active == true) { - dma->channel[i].active = false; - } } } @@ -610,9 +614,10 @@ uint8 x, active_channels = 0; if(channel[i].hdma_indirect == false) { channel[i].hdma_iaddress = channel[i].hdma_address; } else { - channel[i].hdma_iaddress = mem_bus->read(channel[i].hdma_address++); - channel[i].hdma_iaddress |= mem_bus->read(channel[i].hdma_address++) << 8; + channel[i].hdma_iaddress = mem_bus->read(channel[i].hdma_address); + channel[i].hdma_iaddress |= mem_bus->read(channel[i].hdma_address + 1) << 8; channel[i].hdma_iaddress |= channel[i].hdma_indirect_bank << 16; + channel[i].hdma_address += 2; clock->add_cc1_cycles(16); } } @@ -648,7 +653,7 @@ uint8 x, active_channels = 0; void bDMA::hdma_initialize() { uint8 active_channels = 0; for(int i=0;i<8;i++) { - if(!channel[i].hdma_active) { + if(channel[i].hdma_active == false) { channel[i].hdma_completed = true; continue; } @@ -687,9 +692,8 @@ void bDMA::reset() { channel[i].hdma_line_counter = 0; channel[i].hdma_address = 0; channel[i].hdma_iaddress = 0; - channel[i].hdma_completed = false; + channel[i].hdma_completed = true; } - hdma_triggered = false; } bDMA::bDMA(bCPU *_cpu) { diff --git a/src/cpu/bcpu/bcpu_op_adc.cpp b/src/cpu/bcpu/bcpu_op_adc.cpp index 2bfe4ab6..fdf6e152 100644 --- a/src/cpu/bcpu/bcpu_op_adc.cpp +++ b/src/cpu/bcpu/bcpu_op_adc.cpp @@ -1,4 +1,4 @@ -void bCPU::flags_adc_b() { +inline void bCPU::flags_adc_b() { int32 r = regs.a.l + rd.l + regs.p.c; //bcd if(regs.p.d) { @@ -12,7 +12,7 @@ int32 r = regs.a.l + rd.l + regs.p.c; regs.a.l = r; } -void bCPU::flags_adc_w() { +inline void bCPU::flags_adc_w() { int32 r = regs.a.w + rd.w + regs.p.c; //bcd if(regs.p.d) { @@ -47,8 +47,6 @@ void bCPU::op_adc_constw() { flags_adc_w(); } -void bCPU::op_adc_const() { (regs.p.m)?op_adc_constb():op_adc_constw(); } - /********************** *** 0x6d: adc addr *** ********************** @@ -74,8 +72,6 @@ void bCPU::op_adc_addrw() { flags_adc_w(); } -void bCPU::op_adc_addr() { (regs.p.m)?op_adc_addrb():op_adc_addrw(); } - /************************ *** 0x7d: adc addr,x *** ************************ @@ -104,8 +100,6 @@ void bCPU::op_adc_addrxw() { flags_adc_w(); } -void bCPU::op_adc_addrx() { (regs.p.m)?op_adc_addrxb():op_adc_addrxw(); } - /******************** *** 0x65: adc dp *** ******************** @@ -131,8 +125,6 @@ void bCPU::op_adc_dpw() { flags_adc_w(); } -void bCPU::op_adc_dp() { (regs.p.m)?op_adc_dpb():op_adc_dpw(); } - /********************** *** 0x72: adc (dp) *** ********************** @@ -164,8 +156,6 @@ void bCPU::op_adc_idpw() { flags_adc_w(); } -void bCPU::op_adc_idp() { (regs.p.m)?op_adc_idpb():op_adc_idpw(); } - /********************** *** 0x67: adc [dp] *** ********************** @@ -200,8 +190,6 @@ void bCPU::op_adc_ildpw() { flags_adc_w(); } -void bCPU::op_adc_ildp() { (regs.p.m)?op_adc_ildpb():op_adc_ildpw(); } - /********************** *** 0x6f: adc long *** ********************** @@ -230,8 +218,6 @@ void bCPU::op_adc_longw() { flags_adc_w(); } -void bCPU::op_adc_long() { (regs.p.m)?op_adc_longb():op_adc_longw(); } - /************************ *** 0x7f: adc long,x *** ************************ @@ -260,8 +246,6 @@ void bCPU::op_adc_longxw() { flags_adc_w(); } -void bCPU::op_adc_longx() { (regs.p.m)?op_adc_longxb():op_adc_longxw(); } - /************************ *** 0x79: adc addr,y *** ************************ @@ -290,8 +274,6 @@ void bCPU::op_adc_addryw() { flags_adc_w(); } -void bCPU::op_adc_addry() { (regs.p.m)?op_adc_addryb():op_adc_addryw(); } - /********************** *** 0x75: adc dp,x *** ********************** @@ -320,8 +302,6 @@ void bCPU::op_adc_dpxw() { flags_adc_w(); } -void bCPU::op_adc_dpx() { (regs.p.m)?op_adc_dpxb():op_adc_dpxw(); } - /************************ *** 0x61: adc (dp,x) *** ************************ @@ -356,8 +336,6 @@ void bCPU::op_adc_idpxw() { flags_adc_w(); } -void bCPU::op_adc_idpx() { (regs.p.m)?op_adc_idpxb():op_adc_idpxw(); } - /************************ *** 0x71: adc (dp),y *** ************************ @@ -392,8 +370,6 @@ void bCPU::op_adc_idpyw() { flags_adc_w(); } -void bCPU::op_adc_idpy() { (regs.p.m)?op_adc_idpyb():op_adc_idpyw(); } - /************************ *** 0x77: adc [dp],y *** ************************ @@ -428,8 +404,6 @@ void bCPU::op_adc_ildpyw() { flags_adc_w(); } -void bCPU::op_adc_ildpy() { (regs.p.m)?op_adc_ildpyb():op_adc_ildpyw(); } - /********************** *** 0x63: adc sr,s *** ********************** @@ -455,8 +429,6 @@ void bCPU::op_adc_srw() { flags_adc_w(); } -void bCPU::op_adc_sr() { (regs.p.m)?op_adc_srb():op_adc_srw(); } - /************************** *** 0x73: adc (sr,s),y *** ************************** @@ -490,5 +462,3 @@ void bCPU::op_adc_isryw() { rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_adc_w(); } - -void bCPU::op_adc_isry() { (regs.p.m)?op_adc_isryb():op_adc_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_and.cpp b/src/cpu/bcpu/bcpu_op_and.cpp index c6d0f3b3..4960ae05 100644 --- a/src/cpu/bcpu/bcpu_op_and.cpp +++ b/src/cpu/bcpu/bcpu_op_and.cpp @@ -1,9 +1,9 @@ -void bCPU::flags_and_b() { +inline void bCPU::flags_and_b() { regs.p.n = !!(regs.a.l & 0x80); regs.p.z = (regs.a.l == 0); } -void bCPU::flags_and_w() { +inline void bCPU::flags_and_w() { regs.p.n = !!(regs.a.w & 0x8000); regs.p.z = (regs.a.w == 0); } @@ -27,8 +27,6 @@ void bCPU::op_and_constw() { flags_and_w(); } -void bCPU::op_and_const() { (regs.p.m)?op_and_constb():op_and_constw(); } - /********************** *** 0x2d: and addr *** ********************** @@ -54,8 +52,6 @@ void bCPU::op_and_addrw() { flags_and_w(); } -void bCPU::op_and_addr() { (regs.p.m)?op_and_addrb():op_and_addrw(); } - /************************ *** 0x3d: and addr,x *** ************************ @@ -84,8 +80,6 @@ void bCPU::op_and_addrxw() { flags_and_w(); } -void bCPU::op_and_addrx() { (regs.p.m)?op_and_addrxb():op_and_addrxw(); } - /******************** *** 0x25: and dp *** ******************** @@ -111,8 +105,6 @@ void bCPU::op_and_dpw() { flags_and_w(); } -void bCPU::op_and_dp() { (regs.p.m)?op_and_dpb():op_and_dpw(); } - /********************** *** 0x32: and (dp) *** ********************** @@ -144,8 +136,6 @@ void bCPU::op_and_idpw() { flags_and_w(); } -void bCPU::op_and_idp() { (regs.p.m)?op_and_idpb():op_and_idpw(); } - /********************** *** 0x27: and [dp] *** ********************** @@ -180,8 +170,6 @@ void bCPU::op_and_ildpw() { flags_and_w(); } -void bCPU::op_and_ildp() { (regs.p.m)?op_and_ildpb():op_and_ildpw(); } - /********************** *** 0x2f: and long *** ********************** @@ -210,8 +198,6 @@ void bCPU::op_and_longw() { flags_and_w(); } -void bCPU::op_and_long() { (regs.p.m)?op_and_longb():op_and_longw(); } - /************************ *** 0x3f: and long,x *** ************************ @@ -240,8 +226,6 @@ void bCPU::op_and_longxw() { flags_and_w(); } -void bCPU::op_and_longx() { (regs.p.m)?op_and_longxb():op_and_longxw(); } - /************************ *** 0x39: and addr,y *** ************************ @@ -270,8 +254,6 @@ void bCPU::op_and_addryw() { flags_and_w(); } -void bCPU::op_and_addry() { (regs.p.m)?op_and_addryb():op_and_addryw(); } - /********************** *** 0x35: and dp,x *** ********************** @@ -300,8 +282,6 @@ void bCPU::op_and_dpxw() { flags_and_w(); } -void bCPU::op_and_dpx() { (regs.p.m)?op_and_dpxb():op_and_dpxw(); } - /************************ *** 0x21: and (dp,x) *** ************************ @@ -336,8 +316,6 @@ void bCPU::op_and_idpxw() { flags_and_w(); } -void bCPU::op_and_idpx() { (regs.p.m)?op_and_idpxb():op_and_idpxw(); } - /************************ *** 0x31: and (dp),y *** ************************ @@ -372,8 +350,6 @@ void bCPU::op_and_idpyw() { flags_and_w(); } -void bCPU::op_and_idpy() { (regs.p.m)?op_and_idpyb():op_and_idpyw(); } - /************************ *** 0x37: and [dp],y *** ************************ @@ -408,8 +384,6 @@ void bCPU::op_and_ildpyw() { flags_and_w(); } -void bCPU::op_and_ildpy() { (regs.p.m)?op_and_ildpyb():op_and_ildpyw(); } - /********************** *** 0x23: and sr,s *** ********************** @@ -435,8 +409,6 @@ void bCPU::op_and_srw() { flags_and_w(); } -void bCPU::op_and_sr() { (regs.p.m)?op_and_srb():op_and_srw(); } - /************************** *** 0x33: and (sr,s),y *** ************************** @@ -470,5 +442,3 @@ void bCPU::op_and_isryw() { regs.a.h &= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_and_w(); } - -void bCPU::op_and_isry() { (regs.p.m)?op_and_isryb():op_and_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_cmp.cpp b/src/cpu/bcpu/bcpu_op_cmp.cpp index af58527a..fd370f3c 100644 --- a/src/cpu/bcpu/bcpu_op_cmp.cpp +++ b/src/cpu/bcpu/bcpu_op_cmp.cpp @@ -1,11 +1,11 @@ -void bCPU::flags_cmp_b() { +inline void bCPU::flags_cmp_b() { int32 r = regs.a.l - rd.l; regs.p.n = !!(r & 0x80); regs.p.z = ((uint8)r == 0); regs.p.c = (r >= 0); } -void bCPU::flags_cmp_w() { +inline void bCPU::flags_cmp_w() { int32 r = regs.a.w - rd.w; regs.p.n = !!(r & 0x8000); regs.p.z = ((uint16)r == 0); @@ -31,8 +31,6 @@ void bCPU::op_cmp_constw() { flags_cmp_w(); } -void bCPU::op_cmp_const() { (regs.p.m)?op_cmp_constb():op_cmp_constw(); } - /********************** *** 0xcd: cmp addr *** ********************** @@ -58,8 +56,6 @@ void bCPU::op_cmp_addrw() { flags_cmp_w(); } -void bCPU::op_cmp_addr() { (regs.p.m)?op_cmp_addrb():op_cmp_addrw(); } - /************************ *** 0xdd: cmp addr,x *** ************************ @@ -88,8 +84,6 @@ void bCPU::op_cmp_addrxw() { flags_cmp_w(); } -void bCPU::op_cmp_addrx() { (regs.p.m)?op_cmp_addrxb():op_cmp_addrxw(); } - /******************** *** 0xc5: cmp dp *** ******************** @@ -115,8 +109,6 @@ void bCPU::op_cmp_dpw() { flags_cmp_w(); } -void bCPU::op_cmp_dp() { (regs.p.m)?op_cmp_dpb():op_cmp_dpw(); } - /********************** *** 0xd2: cmp (dp) *** ********************** @@ -148,8 +140,6 @@ void bCPU::op_cmp_idpw() { flags_cmp_w(); } -void bCPU::op_cmp_idp() { (regs.p.m)?op_cmp_idpb():op_cmp_idpw(); } - /********************** *** 0xc7: cmp [dp] *** ********************** @@ -184,8 +174,6 @@ void bCPU::op_cmp_ildpw() { flags_cmp_w(); } -void bCPU::op_cmp_ildp() { (regs.p.m)?op_cmp_ildpb():op_cmp_ildpw(); } - /********************** *** 0xcf: cmp long *** ********************** @@ -214,8 +202,6 @@ void bCPU::op_cmp_longw() { flags_cmp_w(); } -void bCPU::op_cmp_long() { (regs.p.m)?op_cmp_longb():op_cmp_longw(); } - /************************ *** 0xdf: cmp long,x *** ************************ @@ -244,8 +230,6 @@ void bCPU::op_cmp_longxw() { flags_cmp_w(); } -void bCPU::op_cmp_longx() { (regs.p.m)?op_cmp_longxb():op_cmp_longxw(); } - /************************ *** 0xd9: cmp addr,y *** ************************ @@ -274,8 +258,6 @@ void bCPU::op_cmp_addryw() { flags_cmp_w(); } -void bCPU::op_cmp_addry() { (regs.p.m)?op_cmp_addryb():op_cmp_addryw(); } - /********************** *** 0xd5: cmp dp,x *** ********************** @@ -304,8 +286,6 @@ void bCPU::op_cmp_dpxw() { flags_cmp_w(); } -void bCPU::op_cmp_dpx() { (regs.p.m)?op_cmp_dpxb():op_cmp_dpxw(); } - /************************ *** 0xc1: cmp (dp,x) *** ************************ @@ -340,8 +320,6 @@ void bCPU::op_cmp_idpxw() { flags_cmp_w(); } -void bCPU::op_cmp_idpx() { (regs.p.m)?op_cmp_idpxb():op_cmp_idpxw(); } - /************************ *** 0xd1: cmp (dp),y *** ************************ @@ -376,8 +354,6 @@ void bCPU::op_cmp_idpyw() { flags_cmp_w(); } -void bCPU::op_cmp_idpy() { (regs.p.m)?op_cmp_idpyb():op_cmp_idpyw(); } - /************************ *** 0xd7: cmp [dp],y *** ************************ @@ -412,8 +388,6 @@ void bCPU::op_cmp_ildpyw() { flags_cmp_w(); } -void bCPU::op_cmp_ildpy() { (regs.p.m)?op_cmp_ildpyb():op_cmp_ildpyw(); } - /********************** *** 0xc3: cmp sr,s *** ********************** @@ -439,8 +413,6 @@ void bCPU::op_cmp_srw() { flags_cmp_w(); } -void bCPU::op_cmp_sr() { (regs.p.m)?op_cmp_srb():op_cmp_srw(); } - /************************** *** 0xd3: cmp (sr,s),y *** ************************** @@ -474,5 +446,3 @@ void bCPU::op_cmp_isryw() { rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_cmp_w(); } - -void bCPU::op_cmp_isry() { (regs.p.m)?op_cmp_isryb():op_cmp_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_eor.cpp b/src/cpu/bcpu/bcpu_op_eor.cpp index 0f444c14..98508be7 100644 --- a/src/cpu/bcpu/bcpu_op_eor.cpp +++ b/src/cpu/bcpu/bcpu_op_eor.cpp @@ -1,9 +1,9 @@ -void bCPU::flags_eor_b() { +inline void bCPU::flags_eor_b() { regs.p.n = !!(regs.a.l & 0x80); regs.p.z = (regs.a.l == 0); } -void bCPU::flags_eor_w() { +inline void bCPU::flags_eor_w() { regs.p.n = !!(regs.a.w & 0x8000); regs.p.z = (regs.a.w == 0); } @@ -27,8 +27,6 @@ void bCPU::op_eor_constw() { flags_eor_w(); } -void bCPU::op_eor_const() { (regs.p.m)?op_eor_constb():op_eor_constw(); } - /********************** *** 0x4d: eor addr *** ********************** @@ -54,8 +52,6 @@ void bCPU::op_eor_addrw() { flags_eor_w(); } -void bCPU::op_eor_addr() { (regs.p.m)?op_eor_addrb():op_eor_addrw(); } - /************************ *** 0x5d: eor addr,x *** ************************ @@ -84,8 +80,6 @@ void bCPU::op_eor_addrxw() { flags_eor_w(); } -void bCPU::op_eor_addrx() { (regs.p.m)?op_eor_addrxb():op_eor_addrxw(); } - /******************** *** 0x45: eor dp *** ******************** @@ -111,8 +105,6 @@ void bCPU::op_eor_dpw() { flags_eor_w(); } -void bCPU::op_eor_dp() { (regs.p.m)?op_eor_dpb():op_eor_dpw(); } - /********************** *** 0x52: eor (dp) *** ********************** @@ -144,8 +136,6 @@ void bCPU::op_eor_idpw() { flags_eor_w(); } -void bCPU::op_eor_idp() { (regs.p.m)?op_eor_idpb():op_eor_idpw(); } - /********************** *** 0x47: eor [dp] *** ********************** @@ -180,8 +170,6 @@ void bCPU::op_eor_ildpw() { flags_eor_w(); } -void bCPU::op_eor_ildp() { (regs.p.m)?op_eor_ildpb():op_eor_ildpw(); } - /********************** *** 0x4f: eor long *** ********************** @@ -210,8 +198,6 @@ void bCPU::op_eor_longw() { flags_eor_w(); } -void bCPU::op_eor_long() { (regs.p.m)?op_eor_longb():op_eor_longw(); } - /************************ *** 0x5f: eor long,x *** ************************ @@ -240,8 +226,6 @@ void bCPU::op_eor_longxw() { flags_eor_w(); } -void bCPU::op_eor_longx() { (regs.p.m)?op_eor_longxb():op_eor_longxw(); } - /************************ *** 0x59: eor addr,y *** ************************ @@ -270,8 +254,6 @@ void bCPU::op_eor_addryw() { flags_eor_w(); } -void bCPU::op_eor_addry() { (regs.p.m)?op_eor_addryb():op_eor_addryw(); } - /********************** *** 0x55: eor dp,x *** ********************** @@ -300,8 +282,6 @@ void bCPU::op_eor_dpxw() { flags_eor_w(); } -void bCPU::op_eor_dpx() { (regs.p.m)?op_eor_dpxb():op_eor_dpxw(); } - /************************ *** 0x41: eor (dp,x) *** ************************ @@ -336,8 +316,6 @@ void bCPU::op_eor_idpxw() { flags_eor_w(); } -void bCPU::op_eor_idpx() { (regs.p.m)?op_eor_idpxb():op_eor_idpxw(); } - /************************ *** 0x51: eor (dp),y *** ************************ @@ -372,8 +350,6 @@ void bCPU::op_eor_idpyw() { flags_eor_w(); } -void bCPU::op_eor_idpy() { (regs.p.m)?op_eor_idpyb():op_eor_idpyw(); } - /************************ *** 0x57: eor [dp],y *** ************************ @@ -408,8 +384,6 @@ void bCPU::op_eor_ildpyw() { flags_eor_w(); } -void bCPU::op_eor_ildpy() { (regs.p.m)?op_eor_ildpyb():op_eor_ildpyw(); } - /********************** *** 0x43: eor sr,s *** ********************** @@ -435,8 +409,6 @@ void bCPU::op_eor_srw() { flags_eor_w(); } -void bCPU::op_eor_sr() { (regs.p.m)?op_eor_srb():op_eor_srw(); } - /************************** *** 0x53: eor (sr,s),y *** ************************** @@ -470,5 +442,3 @@ void bCPU::op_eor_isryw() { regs.a.h ^= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_eor_w(); } - -void bCPU::op_eor_isry() { (regs.p.m)?op_eor_isryb():op_eor_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_incdec.cpp b/src/cpu/bcpu/bcpu_op_incdec.cpp index fe34ae2a..64a28e0c 100644 --- a/src/cpu/bcpu/bcpu_op_incdec.cpp +++ b/src/cpu/bcpu/bcpu_op_incdec.cpp @@ -19,8 +19,6 @@ void bCPU::op_incw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_inc() { (regs.p.m)?op_incb():op_incw(); } - /********************** *** 0xee: inc addr *** ********************** @@ -58,8 +56,6 @@ void bCPU::op_inc_addrw() { regs.p.z = (rd.w == 0); } -void bCPU::op_inc_addr() { (regs.p.m)?op_inc_addrb():op_inc_addrw(); } - /************************ *** 0xfe: inc addr,x *** ************************ @@ -100,8 +96,6 @@ void bCPU::op_inc_addrxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_inc_addrx() { (regs.p.m)?op_inc_addrxb():op_inc_addrxw(); } - /******************** *** 0xe6: inc dp *** ******************** @@ -139,8 +133,6 @@ void bCPU::op_inc_dpw() { regs.p.z = (rd.w == 0); } -void bCPU::op_inc_dp() { (regs.p.m)?op_inc_dpb():op_inc_dpw(); } - /********************** *** 0xf6: inc dp,x *** ********************** @@ -181,8 +173,6 @@ void bCPU::op_inc_dpxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_inc_dpx() { (regs.p.m)?op_inc_dpxb():op_inc_dpxw(); } - /***************** *** 0xe8: inx *** ***************** @@ -204,8 +194,6 @@ void bCPU::op_inxw() { regs.p.z = (regs.x.w == 0); } -void bCPU::op_inx() { (regs.p.x)?op_inxb():op_inxw(); } - /***************** *** 0xc8: iny *** ***************** @@ -227,8 +215,6 @@ void bCPU::op_inyw() { regs.p.z = (regs.y.w == 0); } -void bCPU::op_iny() { (regs.p.x)?op_inyb():op_inyw(); } - /***************** *** 0x3a: dec *** ***************** @@ -250,8 +236,6 @@ void bCPU::op_decw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_dec() { (regs.p.m)?op_decb():op_decw(); } - /********************** *** 0xce: dec addr *** ********************** @@ -289,8 +273,6 @@ void bCPU::op_dec_addrw() { regs.p.z = (rd.w == 0); } -void bCPU::op_dec_addr() { (regs.p.m)?op_dec_addrb():op_dec_addrw(); } - /************************ *** 0xde: dec addr,x *** ************************ @@ -331,8 +313,6 @@ void bCPU::op_dec_addrxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_dec_addrx() { (regs.p.m)?op_dec_addrxb():op_dec_addrxw(); } - /******************** *** 0xc6: dec dp *** ******************** @@ -370,8 +350,6 @@ void bCPU::op_dec_dpw() { regs.p.z = (rd.w == 0); } -void bCPU::op_dec_dp() { (regs.p.m)?op_dec_dpb():op_dec_dpw(); } - /********************** *** 0xd6: dec dp,x *** ********************** @@ -412,8 +390,6 @@ void bCPU::op_dec_dpxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_dec_dpx() { (regs.p.m)?op_dec_dpxb():op_dec_dpxw(); } - /***************** *** 0xca: dex *** ***************** @@ -435,8 +411,6 @@ void bCPU::op_dexw() { regs.p.z = (regs.x.w == 0); } -void bCPU::op_dex() { (regs.p.x)?op_dexb():op_dexw(); } - /***************** *** 0x88: dey *** ***************** @@ -457,5 +431,3 @@ void bCPU::op_deyw() { regs.p.n = !!(regs.y.w & 0x8000); regs.p.z = (regs.y.w == 0); } - -void bCPU::op_dey() { (regs.p.x)?op_deyb():op_deyw(); } diff --git a/src/cpu/bcpu/bcpu_op_lda.cpp b/src/cpu/bcpu/bcpu_op_lda.cpp index 568a0cc8..09acc1a6 100644 --- a/src/cpu/bcpu/bcpu_op_lda.cpp +++ b/src/cpu/bcpu/bcpu_op_lda.cpp @@ -1,9 +1,9 @@ -void bCPU::flags_lda_b() { +inline void bCPU::flags_lda_b() { regs.p.n = !!(regs.a.l & 0x80); regs.p.z = (regs.a.l == 0); } -void bCPU::flags_lda_w() { +inline void bCPU::flags_lda_w() { regs.p.n = !!(regs.a.w & 0x8000); regs.p.z = (regs.a.w == 0); } @@ -27,8 +27,6 @@ void bCPU::op_lda_constw() { flags_lda_w(); } -void bCPU::op_lda_const() { (regs.p.m)?op_lda_constb():op_lda_constw(); } - /********************** *** 0xad: lda addr *** ********************** @@ -54,8 +52,6 @@ void bCPU::op_lda_addrw() { flags_lda_w(); } -void bCPU::op_lda_addr() { (regs.p.m)?op_lda_addrb():op_lda_addrw(); } - /************************ *** 0xbd: lda addr,x *** ************************ @@ -84,8 +80,6 @@ void bCPU::op_lda_addrxw() { flags_lda_w(); } -void bCPU::op_lda_addrx() { (regs.p.m)?op_lda_addrxb():op_lda_addrxw(); } - /******************** *** 0xa5: lda dp *** ******************** @@ -111,8 +105,6 @@ void bCPU::op_lda_dpw() { flags_lda_w(); } -void bCPU::op_lda_dp() { (regs.p.m)?op_lda_dpb():op_lda_dpw(); } - /********************** *** 0xb2: lda (dp) *** ********************** @@ -144,8 +136,6 @@ void bCPU::op_lda_idpw() { flags_lda_w(); } -void bCPU::op_lda_idp() { (regs.p.m)?op_lda_idpb():op_lda_idpw(); } - /********************** *** 0xa7: lda [dp] *** ********************** @@ -180,8 +170,6 @@ void bCPU::op_lda_ildpw() { flags_lda_w(); } -void bCPU::op_lda_ildp() { (regs.p.m)?op_lda_ildpb():op_lda_ildpw(); } - /********************** *** 0xaf: lda long *** ********************** @@ -210,8 +198,6 @@ void bCPU::op_lda_longw() { flags_lda_w(); } -void bCPU::op_lda_long() { (regs.p.m)?op_lda_longb():op_lda_longw(); } - /************************ *** 0xbf: lda long,x *** ************************ @@ -240,8 +226,6 @@ void bCPU::op_lda_longxw() { flags_lda_w(); } -void bCPU::op_lda_longx() { (regs.p.m)?op_lda_longxb():op_lda_longxw(); } - /************************ *** 0xb9: lda addr,y *** ************************ @@ -270,8 +254,6 @@ void bCPU::op_lda_addryw() { flags_lda_w(); } -void bCPU::op_lda_addry() { (regs.p.m)?op_lda_addryb():op_lda_addryw(); } - /********************** *** 0xb5: lda dp,x *** ********************** @@ -300,8 +282,6 @@ void bCPU::op_lda_dpxw() { flags_lda_w(); } -void bCPU::op_lda_dpx() { (regs.p.m)?op_lda_dpxb():op_lda_dpxw(); } - /************************ *** 0xa1: lda (dp,x) *** ************************ @@ -336,8 +316,6 @@ void bCPU::op_lda_idpxw() { flags_lda_w(); } -void bCPU::op_lda_idpx() { (regs.p.m)?op_lda_idpxb():op_lda_idpxw(); } - /************************ *** 0xb1: lda (dp),y *** ************************ @@ -372,8 +350,6 @@ void bCPU::op_lda_idpyw() { flags_lda_w(); } -void bCPU::op_lda_idpy() { (regs.p.m)?op_lda_idpyb():op_lda_idpyw(); } - /************************ *** 0xb7: lda [dp],y *** ************************ @@ -408,8 +384,6 @@ void bCPU::op_lda_ildpyw() { flags_lda_w(); } -void bCPU::op_lda_ildpy() { (regs.p.m)?op_lda_ildpyb():op_lda_ildpyw(); } - /********************** *** 0xa3: lda sr,s *** ********************** @@ -435,8 +409,6 @@ void bCPU::op_lda_srw() { flags_lda_w(); } -void bCPU::op_lda_sr() { (regs.p.m)?op_lda_srb():op_lda_srw(); } - /************************** *** 0xb3: lda (sr,s),y *** ************************** @@ -470,5 +442,3 @@ void bCPU::op_lda_isryw() { regs.a.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_lda_w(); } - -void bCPU::op_lda_isry() { (regs.p.m)?op_lda_isryb():op_lda_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_misc.cpp b/src/cpu/bcpu/bcpu_op_misc.cpp index fab75e4c..f09ded99 100644 --- a/src/cpu/bcpu/bcpu_op_misc.cpp +++ b/src/cpu/bcpu/bcpu_op_misc.cpp @@ -1,10 +1,10 @@ -void bCPU::flags_bit_b() { +inline void bCPU::flags_bit_b() { regs.p.n = !!(rd.l & 0x80); regs.p.v = !!(rd.l & 0x40); regs.p.z = ((rd.l & regs.a.l) == 0); } -void bCPU::flags_bit_w() { +inline void bCPU::flags_bit_w() { regs.p.n = !!(rd.w & 0x8000); regs.p.v = !!(rd.w & 0x4000); regs.p.z = ((rd.w & regs.a.w) == 0); @@ -20,17 +20,15 @@ cycles: */ void bCPU::op_bit_constb() { rd.l = op_read(); //2 - flags_bit_b(); + regs.p.z = ((rd.l & regs.a.l) == 0); } void bCPU::op_bit_constw() { rd.l = op_read(); //2 rd.h = op_read(); //2a - flags_bit_w(); + regs.p.z = ((rd.w & regs.a.w) == 0); } -void bCPU::op_bit_const() { (regs.p.m)?op_bit_constb():op_bit_constw(); } - /********************** *** 0x2c: bit addr *** ********************** @@ -56,8 +54,6 @@ void bCPU::op_bit_addrw() { flags_bit_w(); } -void bCPU::op_bit_addr() { (regs.p.m)?op_bit_addrb():op_bit_addrw(); } - /************************ *** 0x3c: bit addr,x *** ************************ @@ -86,8 +82,6 @@ void bCPU::op_bit_addrxw() { flags_bit_w(); } -void bCPU::op_bit_addrx() { (regs.p.m)?op_bit_addrxb():op_bit_addrxw(); } - /******************** *** 0x24: bit dp *** ******************** @@ -113,8 +107,6 @@ void bCPU::op_bit_dpw() { flags_bit_w(); } -void bCPU::op_bit_dp() { (regs.p.m)?op_bit_dpb():op_bit_dpw(); } - /********************** *** 0x34: bit dp,x *** ********************** @@ -143,16 +135,14 @@ void bCPU::op_bit_dpxw() { flags_bit_w(); } -void bCPU::op_bit_dpx() { (regs.p.m)?op_bit_dpxb():op_bit_dpxw(); } - -void bCPU::flags_cpx_b() { +inline void bCPU::flags_cpx_b() { int32 r = regs.x.l - rd.l; regs.p.n = !!(r & 0x80); regs.p.z = ((uint8)r == 0); regs.p.c = (r >= 0); } -void bCPU::flags_cpx_w() { +inline void bCPU::flags_cpx_w() { int32 r = regs.x.w - rd.w; regs.p.n = !!(r & 0x8000); regs.p.z = ((uint16)r == 0); @@ -178,8 +168,6 @@ void bCPU::op_cpx_constw() { flags_cpx_w(); } -void bCPU::op_cpx_const() { (regs.p.x)?op_cpx_constb():op_cpx_constw(); } - /********************** *** 0xec: cpx addr *** ********************** @@ -205,8 +193,6 @@ void bCPU::op_cpx_addrw() { flags_cpx_w(); } -void bCPU::op_cpx_addr() { (regs.p.x)?op_cpx_addrb():op_cpx_addrw(); } - /******************** *** 0xe4: cpx dp *** ******************** @@ -232,16 +218,14 @@ void bCPU::op_cpx_dpw() { flags_cpx_w(); } -void bCPU::op_cpx_dp() { (regs.p.x)?op_cpx_dpb():op_cpx_dpw(); } - -void bCPU::flags_cpy_b() { +inline void bCPU::flags_cpy_b() { int32 r = regs.y.l - rd.l; regs.p.n = !!(r & 0x80); regs.p.z = ((uint8)r == 0); regs.p.c = (r >= 0); } -void bCPU::flags_cpy_w() { +inline void bCPU::flags_cpy_w() { int32 r = regs.y.w - rd.w; regs.p.n = !!(r & 0x8000); regs.p.z = ((uint16)r == 0); @@ -267,8 +251,6 @@ void bCPU::op_cpy_constw() { flags_cpy_w(); } -void bCPU::op_cpy_const() { (regs.p.x)?op_cpy_constb():op_cpy_constw(); } - /********************** *** 0xcc: cpy addr *** ********************** @@ -294,8 +276,6 @@ void bCPU::op_cpy_addrw() { flags_cpy_w(); } -void bCPU::op_cpy_addr() { (regs.p.x)?op_cpy_addrb():op_cpy_addrw(); } - /******************** *** 0xc4: cpy dp *** ******************** @@ -321,14 +301,12 @@ void bCPU::op_cpy_dpw() { flags_cpy_w(); } -void bCPU::op_cpy_dp() { (regs.p.x)?op_cpy_dpb():op_cpy_dpw(); } - -void bCPU::flags_ldx_b() { +inline void bCPU::flags_ldx_b() { regs.p.n = !!(regs.x.l & 0x80); regs.p.z = (regs.x.l == 0); } -void bCPU::flags_ldx_w() { +inline void bCPU::flags_ldx_w() { regs.p.n = !!(regs.x.w & 0x8000); regs.p.z = (regs.x.w == 0); } @@ -352,8 +330,6 @@ void bCPU::op_ldx_constw() { flags_ldx_w(); } -void bCPU::op_ldx_const() { (regs.p.x)?op_ldx_constb():op_ldx_constw(); } - /********************** *** 0xae: ldx addr *** ********************** @@ -379,8 +355,6 @@ void bCPU::op_ldx_addrw() { flags_ldx_w(); } -void bCPU::op_ldx_addr() { (regs.p.x)?op_ldx_addrb():op_ldx_addrw(); } - /************************ *** 0xbe: ldx addr,y *** ************************ @@ -409,8 +383,6 @@ void bCPU::op_ldx_addryw() { flags_ldx_w(); } -void bCPU::op_ldx_addry() { (regs.p.x)?op_ldx_addryb():op_ldx_addryw(); } - /******************** *** 0xa6: ldx dp *** ******************** @@ -436,8 +408,6 @@ void bCPU::op_ldx_dpw() { flags_ldx_w(); } -void bCPU::op_ldx_dp() { (regs.p.x)?op_ldx_dpb():op_ldx_dpw(); } - /********************** *** 0xb6: ldx dp,y *** ********************** @@ -466,14 +436,12 @@ void bCPU::op_ldx_dpyw() { flags_ldx_w(); } -void bCPU::op_ldx_dpy() { (regs.p.x)?op_ldx_dpyb():op_ldx_dpyw(); } - -void bCPU::flags_ldy_b() { +inline void bCPU::flags_ldy_b() { regs.p.n = !!(regs.y.l & 0x80); regs.p.z = (regs.y.l == 0); } -void bCPU::flags_ldy_w() { +inline void bCPU::flags_ldy_w() { regs.p.n = !!(regs.y.w & 0x8000); regs.p.z = (regs.y.w == 0); } @@ -497,8 +465,6 @@ void bCPU::op_ldy_constw() { flags_ldy_w(); } -void bCPU::op_ldy_const() { (regs.p.x)?op_ldy_constb():op_ldy_constw(); } - /********************** *** 0xac: ldy addr *** ********************** @@ -524,8 +490,6 @@ void bCPU::op_ldy_addrw() { flags_ldy_w(); } -void bCPU::op_ldy_addr() { (regs.p.x)?op_ldy_addrb():op_ldy_addrw(); } - /************************ *** 0xbc: ldy addr,x *** ************************ @@ -554,8 +518,6 @@ void bCPU::op_ldy_addrxw() { flags_ldy_w(); } -void bCPU::op_ldy_addrx() { (regs.p.x)?op_ldy_addrxb():op_ldy_addrxw(); } - /******************** *** 0xa4: ldy dp *** ******************** @@ -581,8 +543,6 @@ void bCPU::op_ldy_dpw() { flags_ldy_w(); } -void bCPU::op_ldy_dp() { (regs.p.x)?op_ldy_dpb():op_ldy_dpw(); } - /********************** *** 0xb4: ldy dp,x *** ********************** @@ -611,8 +571,6 @@ void bCPU::op_ldy_dpxw() { flags_ldy_w(); } -void bCPU::op_ldy_dpx() { (regs.p.x)?op_ldy_dpxb():op_ldy_dpxw(); } - /********************** *** 0x8e: stx addr *** ********************** @@ -636,8 +594,6 @@ void bCPU::op_stx_addrw() { op_write(OPMODE_DBR, aa.w + 1, regs.x.h); //4a } -void bCPU::op_stx_addr() { (regs.p.x)?op_stx_addrb():op_stx_addrw(); } - /******************** *** 0x86: stx dp *** ******************** @@ -661,8 +617,6 @@ void bCPU::op_stx_dpw() { op_write(OPMODE_DP, dp + 1, regs.x.h); //3a } -void bCPU::op_stx_dp() { (regs.p.x)?op_stx_dpb():op_stx_dpw(); } - /********************** *** 0x96: stx dp,y *** ********************** @@ -689,8 +643,6 @@ void bCPU::op_stx_dpyw() { op_write(OPMODE_DP, dp + regs.y.w + 1, regs.x.h); //4a } -void bCPU::op_stx_dpy() { (regs.p.x)?op_stx_dpyb():op_stx_dpyw(); } - /********************** *** 0x8c: sty addr *** ********************** @@ -714,8 +666,6 @@ void bCPU::op_sty_addrw() { op_write(OPMODE_DBR, aa.w + 1, regs.y.h); //4a } -void bCPU::op_sty_addr() { (regs.p.x)?op_sty_addrb():op_sty_addrw(); } - /******************** *** 0x84: sty dp *** ******************** @@ -739,8 +689,6 @@ void bCPU::op_sty_dpw() { op_write(OPMODE_DP, dp + 1, regs.y.h); //3a } -void bCPU::op_sty_dp() { (regs.p.x)?op_sty_dpb():op_sty_dpw(); } - /********************** *** 0x94: sty dp,x *** ********************** @@ -767,8 +715,6 @@ void bCPU::op_sty_dpxw() { op_write(OPMODE_DP, dp + regs.x.w + 1, regs.y.h); //4a } -void bCPU::op_sty_dpx() { (regs.p.x)?op_sty_dpxb():op_sty_dpxw(); } - /********************** *** 0x9c: stz addr *** ********************** @@ -792,8 +738,6 @@ void bCPU::op_stz_addrw() { op_write(OPMODE_DBR, aa.w + 1, 0); //4a } -void bCPU::op_stz_addr() { (regs.p.m)?op_stz_addrb():op_stz_addrw(); } - /************************ *** 0x9e: stz addr,x *** ************************ @@ -820,8 +764,6 @@ void bCPU::op_stz_addrxw() { op_write(OPMODE_DBR, aa.w + regs.x.w + 1, 0); //4a } -void bCPU::op_stz_addrx() { (regs.p.m)?op_stz_addrxb():op_stz_addrxw(); } - /******************** *** 0x64: stz dp *** ******************** @@ -845,8 +787,6 @@ void bCPU::op_stz_dpw() { op_write(OPMODE_DP, dp + 1, 0); //3a } -void bCPU::op_stz_dp() { (regs.p.m)?op_stz_dpb():op_stz_dpw(); } - /********************** *** 0x74: stz dp,x *** ********************** @@ -873,8 +813,6 @@ void bCPU::op_stz_dpxw() { op_write(OPMODE_DP, dp + regs.x.w + 1, 0); //4a } -void bCPU::op_stz_dpx() { (regs.p.m)?op_stz_dpxb():op_stz_dpxw(); } - /***************** *** 0xeb: xba *** ***************** @@ -928,8 +866,6 @@ void bCPU::op_trb_addrw() { op_write(OPMODE_DBR, aa.w, rd.l); //6 } -void bCPU::op_trb_addr() { (regs.p.m)?op_trb_addrb():op_trb_addrw(); } - /******************** *** 0x14: trb dp *** ******************** @@ -965,8 +901,6 @@ void bCPU::op_trb_dpw() { op_write(OPMODE_DP, dp, rd.l); //5 } -void bCPU::op_trb_dp() { (regs.p.m)?op_trb_dpb():op_trb_dpw(); } - /********************** *** 0x0c: tsb addr *** ********************** @@ -1002,8 +936,6 @@ void bCPU::op_tsb_addrw() { op_write(OPMODE_DBR, aa.w, rd.l); //6 } -void bCPU::op_tsb_addr() { (regs.p.m)?op_tsb_addrb():op_tsb_addrw(); } - /******************** *** 0x04: tsb dp *** ******************** @@ -1039,8 +971,6 @@ void bCPU::op_tsb_dpw() { op_write(OPMODE_DP, dp, rd.l); //5 } -void bCPU::op_tsb_dp() { (regs.p.m)?op_tsb_dpb():op_tsb_dpw(); } - /************************** *** 0x54: mvn src,dest *** ************************** @@ -1219,6 +1149,14 @@ bool c = regs.p.c; regs.x.h = 0x00; regs.y.h = 0x00; regs.s.h = 0x01; + optbl = optbl_e; + } else { + switch((regs.p >> 4) & 3) { + case 0:optbl = optbl_mx;break; + case 1:optbl = optbl_mX;break; + case 2:optbl = optbl_Mx;break; + case 3:optbl = optbl_MX;break; + } } } @@ -1343,6 +1281,13 @@ void bCPU::op_rep() { regs.p &= ~rd.l; if(regs.e) { regs.p |= 0x30; + } else { + switch((regs.p >> 4) & 3) { + case 0:optbl = optbl_mx;break; + case 1:optbl = optbl_mX;break; + case 2:optbl = optbl_Mx;break; + case 3:optbl = optbl_MX;break; + } } } @@ -1360,6 +1305,13 @@ void bCPU::op_sep() { regs.p |= rd.l; if(regs.e) { regs.p |= 0x30; + } else { + switch((regs.p >> 4) & 3) { + case 0:optbl = optbl_mx;break; + case 1:optbl = optbl_mX;break; + case 2:optbl = optbl_Mx;break; + case 3:optbl = optbl_MX;break; + } } if(regs.p.x) { regs.x.h = 0x00; @@ -1388,8 +1340,6 @@ void bCPU::op_taxw() { regs.p.z = (regs.x.w == 0); } -void bCPU::op_tax() { (regs.p.x)?op_taxb():op_taxw(); } - /***************** *** 0xa8: tay *** ***************** @@ -1411,8 +1361,6 @@ void bCPU::op_tayw() { regs.p.z = (regs.y.w == 0); } -void bCPU::op_tay() { (regs.p.x)?op_tayb():op_tayw(); } - /***************** *** 0x5b: tcd *** ***************** @@ -1496,8 +1444,6 @@ void bCPU::op_tsxw() { regs.p.z = (regs.x.w == 0); } -void bCPU::op_tsx() { (regs.p.x)?op_tsxb():op_tsxw(); } - /***************** *** 0x8a: txa *** ***************** @@ -1519,8 +1465,6 @@ void bCPU::op_txaw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_txa() { (regs.p.m)?op_txab():op_txaw(); } - /***************** *** 0x9a: txs *** ***************** @@ -1542,8 +1486,6 @@ void bCPU::op_txsw() { regs.p.z = (regs.s.w == 0); } -void bCPU::op_txs() { (regs.p.x)?op_txsb():op_txsw(); } - /***************** *** 0x9b: txy *** ***************** @@ -1565,8 +1507,6 @@ void bCPU::op_txyw() { regs.p.z = (regs.y.w == 0); } -void bCPU::op_txy() { (regs.p.x)?op_txyb():op_txyw(); } - /***************** *** 0x98: tya *** ***************** @@ -1588,8 +1528,6 @@ void bCPU::op_tyaw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_tya() { (regs.p.m)?op_tyab():op_tyaw(); } - /***************** *** 0xbb: tyx *** ***************** @@ -1610,5 +1548,3 @@ void bCPU::op_tyxw() { regs.p.n = !!(regs.x.w & 0x8000); regs.p.z = (regs.x.w == 0); } - -void bCPU::op_tyx() { (regs.p.x)?op_tyxb():op_tyxw(); } diff --git a/src/cpu/bcpu/bcpu_op_ora.cpp b/src/cpu/bcpu/bcpu_op_ora.cpp index d31bbabf..33e86b90 100644 --- a/src/cpu/bcpu/bcpu_op_ora.cpp +++ b/src/cpu/bcpu/bcpu_op_ora.cpp @@ -1,9 +1,9 @@ -void bCPU::flags_ora_b() { +inline void bCPU::flags_ora_b() { regs.p.n = !!(regs.a.l & 0x80); regs.p.z = (regs.a.l == 0); } -void bCPU::flags_ora_w() { +inline void bCPU::flags_ora_w() { regs.p.n = !!(regs.a.w & 0x8000); regs.p.z = (regs.a.w == 0); } @@ -27,8 +27,6 @@ void bCPU::op_ora_constw() { flags_ora_w(); } -void bCPU::op_ora_const() { (regs.p.m)?op_ora_constb():op_ora_constw(); } - /********************** *** 0x0d: ora addr *** ********************** @@ -54,8 +52,6 @@ void bCPU::op_ora_addrw() { flags_ora_w(); } -void bCPU::op_ora_addr() { (regs.p.m)?op_ora_addrb():op_ora_addrw(); } - /************************ *** 0x1d: ora addr,x *** ************************ @@ -84,8 +80,6 @@ void bCPU::op_ora_addrxw() { flags_ora_w(); } -void bCPU::op_ora_addrx() { (regs.p.m)?op_ora_addrxb():op_ora_addrxw(); } - /******************** *** 0x05: ora dp *** ******************** @@ -111,8 +105,6 @@ void bCPU::op_ora_dpw() { flags_ora_w(); } -void bCPU::op_ora_dp() { (regs.p.m)?op_ora_dpb():op_ora_dpw(); } - /********************** *** 0x12: ora (dp) *** ********************** @@ -144,8 +136,6 @@ void bCPU::op_ora_idpw() { flags_ora_w(); } -void bCPU::op_ora_idp() { (regs.p.m)?op_ora_idpb():op_ora_idpw(); } - /********************** *** 0x07: ora [dp] *** ********************** @@ -180,8 +170,6 @@ void bCPU::op_ora_ildpw() { flags_ora_w(); } -void bCPU::op_ora_ildp() { (regs.p.m)?op_ora_ildpb():op_ora_ildpw(); } - /********************** *** 0x0f: ora long *** ********************** @@ -210,8 +198,6 @@ void bCPU::op_ora_longw() { flags_ora_w(); } -void bCPU::op_ora_long() { (regs.p.m)?op_ora_longb():op_ora_longw(); } - /************************ *** 0x1f: ora long,x *** ************************ @@ -240,8 +226,6 @@ void bCPU::op_ora_longxw() { flags_ora_w(); } -void bCPU::op_ora_longx() { (regs.p.m)?op_ora_longxb():op_ora_longxw(); } - /************************ *** 0x19: ora addr,y *** ************************ @@ -270,8 +254,6 @@ void bCPU::op_ora_addryw() { flags_ora_w(); } -void bCPU::op_ora_addry() { (regs.p.m)?op_ora_addryb():op_ora_addryw(); } - /********************** *** 0x15: ora dp,x *** ********************** @@ -300,8 +282,6 @@ void bCPU::op_ora_dpxw() { flags_ora_w(); } -void bCPU::op_ora_dpx() { (regs.p.m)?op_ora_dpxb():op_ora_dpxw(); } - /************************ *** 0x01: ora (dp,x) *** ************************ @@ -336,8 +316,6 @@ void bCPU::op_ora_idpxw() { flags_ora_w(); } -void bCPU::op_ora_idpx() { (regs.p.m)?op_ora_idpxb():op_ora_idpxw(); } - /************************ *** 0x11: ora (dp),y *** ************************ @@ -372,8 +350,6 @@ void bCPU::op_ora_idpyw() { flags_ora_w(); } -void bCPU::op_ora_idpy() { (regs.p.m)?op_ora_idpyb():op_ora_idpyw(); } - /************************ *** 0x17: ora [dp],y *** ************************ @@ -408,8 +384,6 @@ void bCPU::op_ora_ildpyw() { flags_ora_w(); } -void bCPU::op_ora_ildpy() { (regs.p.m)?op_ora_ildpyb():op_ora_ildpyw(); } - /********************** *** 0x03: ora sr,s *** ********************** @@ -435,8 +409,6 @@ void bCPU::op_ora_srw() { flags_ora_w(); } -void bCPU::op_ora_sr() { (regs.p.m)?op_ora_srb():op_ora_srw(); } - /************************** *** 0x13: ora (sr,s),y *** ************************** @@ -470,5 +442,3 @@ void bCPU::op_ora_isryw() { regs.a.h |= op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_ora_w(); } - -void bCPU::op_ora_isry() { (regs.p.m)?op_ora_isryb():op_ora_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_pc.cpp b/src/cpu/bcpu/bcpu_op_pc.cpp index fb499632..2ec8b225 100644 --- a/src/cpu/bcpu/bcpu_op_pc.cpp +++ b/src/cpu/bcpu/bcpu_op_pc.cpp @@ -193,9 +193,14 @@ void bCPU::op_rtin() { regs.y.h = 0x00; } regs.pc.d = rd.d; -} -void bCPU::op_rti() { (regs.e)?op_rtie():op_rtin(); } + switch((regs.p >> 4) & 3) { + case 0:optbl = optbl_mx;break; + case 1:optbl = optbl_mX;break; + case 2:optbl = optbl_Mx;break; + case 3:optbl = optbl_MX;break; + } +} /***************** *** 0x60: rts *** diff --git a/src/cpu/bcpu/bcpu_op_sbc.cpp b/src/cpu/bcpu/bcpu_op_sbc.cpp index 5e4b36cf..012a7ff5 100644 --- a/src/cpu/bcpu/bcpu_op_sbc.cpp +++ b/src/cpu/bcpu/bcpu_op_sbc.cpp @@ -1,4 +1,4 @@ -void bCPU::flags_sbc_b() { +inline void bCPU::flags_sbc_b() { int32 r = regs.a.l - rd.l - !regs.p.c; //bcd if(regs.p.d) { @@ -12,7 +12,7 @@ int32 r = regs.a.l - rd.l - !regs.p.c; regs.a.l = r; } -void bCPU::flags_sbc_w() { +inline void bCPU::flags_sbc_w() { int32 r = regs.a.w - rd.w - !regs.p.c; //bcd if(regs.p.d) { @@ -47,8 +47,6 @@ void bCPU::op_sbc_constw() { flags_sbc_w(); } -void bCPU::op_sbc_const() { (regs.p.m)?op_sbc_constb():op_sbc_constw(); } - /********************** *** 0xed: sbc addr *** ********************** @@ -74,8 +72,6 @@ void bCPU::op_sbc_addrw() { flags_sbc_w(); } -void bCPU::op_sbc_addr() { (regs.p.m)?op_sbc_addrb():op_sbc_addrw(); } - /************************ *** 0xfd: sbc addr,x *** ************************ @@ -104,8 +100,6 @@ void bCPU::op_sbc_addrxw() { flags_sbc_w(); } -void bCPU::op_sbc_addrx() { (regs.p.m)?op_sbc_addrxb():op_sbc_addrxw(); } - /******************** *** 0xe5: sbc dp *** ******************** @@ -131,8 +125,6 @@ void bCPU::op_sbc_dpw() { flags_sbc_w(); } -void bCPU::op_sbc_dp() { (regs.p.m)?op_sbc_dpb():op_sbc_dpw(); } - /********************** *** 0xf2: sbc (dp) *** ********************** @@ -164,8 +156,6 @@ void bCPU::op_sbc_idpw() { flags_sbc_w(); } -void bCPU::op_sbc_idp() { (regs.p.m)?op_sbc_idpb():op_sbc_idpw(); } - /********************** *** 0xe7: sbc [dp] *** ********************** @@ -200,8 +190,6 @@ void bCPU::op_sbc_ildpw() { flags_sbc_w(); } -void bCPU::op_sbc_ildp() { (regs.p.m)?op_sbc_ildpb():op_sbc_ildpw(); } - /********************** *** 0xef: sbc long *** ********************** @@ -230,8 +218,6 @@ void bCPU::op_sbc_longw() { flags_sbc_w(); } -void bCPU::op_sbc_long() { (regs.p.m)?op_sbc_longb():op_sbc_longw(); } - /************************ *** 0xff: sbc long,x *** ************************ @@ -260,8 +246,6 @@ void bCPU::op_sbc_longxw() { flags_sbc_w(); } -void bCPU::op_sbc_longx() { (regs.p.m)?op_sbc_longxb():op_sbc_longxw(); } - /************************ *** 0xf9: sbc addr,y *** ************************ @@ -290,8 +274,6 @@ void bCPU::op_sbc_addryw() { flags_sbc_w(); } -void bCPU::op_sbc_addry() { (regs.p.m)?op_sbc_addryb():op_sbc_addryw(); } - /********************** *** 0xf5: sbc dp,x *** ********************** @@ -320,8 +302,6 @@ void bCPU::op_sbc_dpxw() { flags_sbc_w(); } -void bCPU::op_sbc_dpx() { (regs.p.m)?op_sbc_dpxb():op_sbc_dpxw(); } - /************************ *** 0xe1: sbc (dp,x) *** ************************ @@ -356,8 +336,6 @@ void bCPU::op_sbc_idpxw() { flags_sbc_w(); } -void bCPU::op_sbc_idpx() { (regs.p.m)?op_sbc_idpxb():op_sbc_idpxw(); } - /************************ *** 0xf1: sbc (dp),y *** ************************ @@ -392,8 +370,6 @@ void bCPU::op_sbc_idpyw() { flags_sbc_w(); } -void bCPU::op_sbc_idpy() { (regs.p.m)?op_sbc_idpyb():op_sbc_idpyw(); } - /************************ *** 0xf7: sbc [dp],y *** ************************ @@ -428,8 +404,6 @@ void bCPU::op_sbc_ildpyw() { flags_sbc_w(); } -void bCPU::op_sbc_ildpy() { (regs.p.m)?op_sbc_ildpyb():op_sbc_ildpyw(); } - /********************** *** 0xe3: sbc sr,s *** ********************** @@ -455,8 +429,6 @@ void bCPU::op_sbc_srw() { flags_sbc_w(); } -void bCPU::op_sbc_sr() { (regs.p.m)?op_sbc_srb():op_sbc_srw(); } - /************************** *** 0xf3: sbc (sr,s),y *** ************************** @@ -490,5 +462,3 @@ void bCPU::op_sbc_isryw() { rd.h = op_read(OPMODE_DBR, aa.w + regs.y.w + 1); //7a flags_sbc_w(); } - -void bCPU::op_sbc_isry() { (regs.p.m)?op_sbc_isryb():op_sbc_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_shift.cpp b/src/cpu/bcpu/bcpu_op_shift.cpp index 927712c6..23171da3 100644 --- a/src/cpu/bcpu/bcpu_op_shift.cpp +++ b/src/cpu/bcpu/bcpu_op_shift.cpp @@ -21,8 +21,6 @@ void bCPU::op_aslw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_asl() { (regs.p.m)?op_aslb():op_aslw(); } - /********************** *** 0x0e: asl addr *** ********************** @@ -62,8 +60,6 @@ void bCPU::op_asl_addrw() { regs.p.z = (rd.w == 0); } -void bCPU::op_asl_addr() { (regs.p.m)?op_asl_addrb():op_asl_addrw(); } - /************************ *** 0x1e: asl addr,x *** ************************ @@ -106,8 +102,6 @@ void bCPU::op_asl_addrxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_asl_addrx() { (regs.p.m)?op_asl_addrxb():op_asl_addrxw(); } - /******************** *** 0x06: asl dp *** ******************** @@ -147,8 +141,6 @@ void bCPU::op_asl_dpw() { regs.p.z = (rd.w == 0); } -void bCPU::op_asl_dp() { (regs.p.m)?op_asl_dpb():op_asl_dpw(); } - /********************** *** 0x16: asl dp,x *** ********************** @@ -191,8 +183,6 @@ void bCPU::op_asl_dpxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_asl_dpx() { (regs.p.m)?op_asl_dpxb():op_asl_dpxw(); } - /***************** *** 0x4a: lsr *** ***************** @@ -216,8 +206,6 @@ void bCPU::op_lsrw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_lsr() { (regs.p.m)?op_lsrb():op_lsrw(); } - /********************** *** 0x4e: lsr addr *** ********************** @@ -257,8 +245,6 @@ void bCPU::op_lsr_addrw() { regs.p.z = (rd.w == 0); } -void bCPU::op_lsr_addr() { (regs.p.m)?op_lsr_addrb():op_lsr_addrw(); } - /************************ *** 0x5e: lsr addr,x *** ************************ @@ -301,8 +287,6 @@ void bCPU::op_lsr_addrxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_lsr_addrx() { (regs.p.m)?op_lsr_addrxb():op_lsr_addrxw(); } - /******************** *** 0x46: lsr dp *** ******************** @@ -342,8 +326,6 @@ void bCPU::op_lsr_dpw() { regs.p.z = (rd.w == 0); } -void bCPU::op_lsr_dp() { (regs.p.m)?op_lsr_dpb():op_lsr_dpw(); } - /********************** *** 0x56: lsr dp,x *** ********************** @@ -386,8 +368,6 @@ void bCPU::op_lsr_dpxw() { regs.p.z = (rd.w == 0); } -void bCPU::op_lsr_dpx() { (regs.p.m)?op_lsr_dpxb():op_lsr_dpxw(); } - /***************** *** 0x2a: rol *** ***************** @@ -415,8 +395,6 @@ uint16 c = regs.p.c; regs.p.z = (regs.a.w == 0); } -void bCPU::op_rol() { (regs.p.m)?op_rolb():op_rolw(); } - /********************** *** 0x2e: rol addr *** ********************** @@ -460,8 +438,6 @@ uint16 c = regs.p.c; regs.p.z = (rd.w == 0); } -void bCPU::op_rol_addr() { (regs.p.m)?op_rol_addrb():op_rol_addrw(); } - /************************ *** 0x3e: rol addr,x *** ************************ @@ -508,8 +484,6 @@ uint16 c = regs.p.c; regs.p.z = (rd.w == 0); } -void bCPU::op_rol_addrx() { (regs.p.m)?op_rol_addrxb():op_rol_addrxw(); } - /******************** *** 0x26: rol dp *** ******************** @@ -553,8 +527,6 @@ uint16 c = regs.p.c; regs.p.z = (rd.w == 0); } -void bCPU::op_rol_dp() { (regs.p.m)?op_rol_dpb():op_rol_dpw(); } - /********************** *** 0x36: rol dp,x *** ********************** @@ -601,8 +573,6 @@ uint16 c = regs.p.c; regs.p.z = (rd.w == 0); } -void bCPU::op_rol_dpx() { (regs.p.m)?op_rol_dpxb():op_rol_dpxw(); } - /***************** *** 0x6a: ror *** ***************** @@ -630,8 +600,6 @@ uint16 c = (regs.p.c)?0x8000:0; regs.p.z = (regs.a.w == 0); } -void bCPU::op_ror() { (regs.p.m)?op_rorb():op_rorw(); } - /********************** *** 0x6e: ror addr *** ********************** @@ -675,8 +643,6 @@ uint16 c = (regs.p.c)?0x8000:0; regs.p.z = (rd.w == 0); } -void bCPU::op_ror_addr() { (regs.p.m)?op_ror_addrb():op_ror_addrw(); } - /************************ *** 0x7e: ror addr,x *** ************************ @@ -723,8 +689,6 @@ uint16 c = (regs.p.c)?0x8000:0; regs.p.z = (rd.w == 0); } -void bCPU::op_ror_addrx() { (regs.p.m)?op_ror_addrxb():op_ror_addrxw(); } - /******************** *** 0x66: ror dp *** ******************** @@ -768,8 +732,6 @@ uint16 c = (regs.p.c)?0x8000:0; regs.p.z = (rd.w == 0); } -void bCPU::op_ror_dp() { (regs.p.m)?op_ror_dpb():op_ror_dpw(); } - /********************** *** 0x76: ror dp,x *** ********************** @@ -815,5 +777,3 @@ uint16 c = (regs.p.c)?0x8000:0; regs.p.n = !!(rd.w & 0x8000); regs.p.z = (rd.w == 0); } - -void bCPU::op_ror_dpx() { (regs.p.m)?op_ror_dpxb():op_ror_dpxw(); } diff --git a/src/cpu/bcpu/bcpu_op_sta.cpp b/src/cpu/bcpu/bcpu_op_sta.cpp index 4dc9bf4b..eb88afaf 100644 --- a/src/cpu/bcpu/bcpu_op_sta.cpp +++ b/src/cpu/bcpu/bcpu_op_sta.cpp @@ -21,8 +21,6 @@ void bCPU::op_sta_addrw() { op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //4a } -void bCPU::op_sta_addr() { (regs.p.m)?op_sta_addrb():op_sta_addrw(); } - /************************ *** 0x9d: sta addr,x *** ************************ @@ -49,8 +47,6 @@ void bCPU::op_sta_addrxw() { op_write(OPMODE_DBR, aa.w + regs.x.w + 1, regs.a.h); //4a } -void bCPU::op_sta_addrx() { (regs.p.m)?op_sta_addrxb():op_sta_addrxw(); } - /******************** *** 0x85: sta dp *** ******************** @@ -74,8 +70,6 @@ void bCPU::op_sta_dpw() { op_write(OPMODE_DP, dp + 1, regs.a.h); //3a } -void bCPU::op_sta_dp() { (regs.p.m)?op_sta_dpb():op_sta_dpw(); } - /********************** *** 0x92: sta (dp) *** ********************** @@ -105,8 +99,6 @@ void bCPU::op_sta_idpw() { op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //5 } -void bCPU::op_sta_idp() { (regs.p.m)?op_sta_idpb():op_sta_idpw(); } - /********************** *** 0x87: sta [dp] *** ********************** @@ -139,8 +131,6 @@ void bCPU::op_sta_ildpw() { op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //6a } -void bCPU::op_sta_ildp() { (regs.p.m)?op_sta_ildpb():op_sta_ildpw(); } - /********************** *** 0x8f: sta long *** ********************** @@ -167,8 +157,6 @@ void bCPU::op_sta_longw() { op_write(OPMODE_LONG, aa.d + 1, regs.a.h); //5a } -void bCPU::op_sta_long() { (regs.p.m)?op_sta_longb():op_sta_longw(); } - /************************ *** 0x9f: sta long,x *** ************************ @@ -195,8 +183,6 @@ void bCPU::op_sta_longxw() { op_write(OPMODE_LONG, aa.d + regs.x.w + 1, regs.a.h); //5a } -void bCPU::op_sta_longx() { (regs.p.m)?op_sta_longxb():op_sta_longxw(); } - /************************ *** 0x99: sta addr,y *** ************************ @@ -223,8 +209,6 @@ void bCPU::op_sta_addryw() { op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //4a } -void bCPU::op_sta_addry() { (regs.p.m)?op_sta_addryb():op_sta_addryw(); } - /********************** *** 0x95: sta dp,x *** ********************** @@ -251,8 +235,6 @@ void bCPU::op_sta_dpxw() { op_write(OPMODE_DP, dp + regs.x.w + 1, regs.a.h); //4a } -void bCPU::op_sta_dpx() { (regs.p.m)?op_sta_dpxb():op_sta_dpxw(); } - /************************ *** 0x81: sta (dp,x) *** ************************ @@ -285,8 +267,6 @@ void bCPU::op_sta_idpxw() { op_write(OPMODE_DBR, aa.w + 1, regs.a.h); //6a } -void bCPU::op_sta_idpx() { (regs.p.m)?op_sta_idpxb():op_sta_idpxw(); } - /************************ *** 0x91: sta (dp),y *** ************************ @@ -319,8 +299,6 @@ void bCPU::op_sta_idpyw() { op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //5a } -void bCPU::op_sta_idpy() { (regs.p.m)?op_sta_idpyb():op_sta_idpyw(); } - /************************ *** 0x97: sta [dp],y *** ************************ @@ -353,8 +331,6 @@ void bCPU::op_sta_ildpyw() { op_write(OPMODE_LONG, aa.d + regs.y.w + 1, regs.a.h); //6a } -void bCPU::op_sta_ildpy() { (regs.p.m)?op_sta_ildpyb():op_sta_ildpyw(); } - /********************** *** 0x83: sta sr,s *** ********************** @@ -378,8 +354,6 @@ void bCPU::op_sta_srw() { op_write(OPMODE_SP, sp + 1, regs.a.h); //4a } -void bCPU::op_sta_sr() { (regs.p.m)?op_sta_srb():op_sta_srw(); } - /************************** *** 0x93: sta (sr,s),y *** ************************** @@ -411,5 +385,3 @@ void bCPU::op_sta_isryw() { op_write(OPMODE_DBR, aa.w + regs.y.w, regs.a.l); //7 op_write(OPMODE_DBR, aa.w + regs.y.w + 1, regs.a.h); //7a } - -void bCPU::op_sta_isry() { (regs.p.m)?op_sta_isryb():op_sta_isryw(); } diff --git a/src/cpu/bcpu/bcpu_op_stack.cpp b/src/cpu/bcpu/bcpu_op_stack.cpp index defddb1a..bb741e84 100644 --- a/src/cpu/bcpu/bcpu_op_stack.cpp +++ b/src/cpu/bcpu/bcpu_op_stack.cpp @@ -18,8 +18,6 @@ void bCPU::op_phaw() { stack_write(regs.a.l); //3 } -void bCPU::op_pha() { (regs.p.m)?op_phab():op_phaw(); } - /***************** *** 0x8b: phb *** ***************** @@ -94,8 +92,6 @@ void bCPU::op_phxw() { stack_write(regs.x.l); //3 } -void bCPU::op_phx() { (regs.p.x)?op_phxb():op_phxw(); } - /***************** *** 0x5a: phy *** ***************** @@ -116,8 +112,6 @@ void bCPU::op_phyw() { stack_write(regs.y.l); //3 } -void bCPU::op_phy() { (regs.p.x)?op_phyb():op_phyw(); } - /***************** *** 0x68: pla *** ***************** @@ -145,8 +139,6 @@ void bCPU::op_plaw() { regs.p.z = (regs.a.w == 0); } -void bCPU::op_pla() { (regs.p.m)?op_plab():op_plaw(); } - /***************** *** 0xab: plb *** ***************** @@ -196,7 +188,16 @@ void bCPU::op_plp() { cpu_io(); //2 cpu_io(); //3 regs.p = stack_read(); //4 - if(regs.e)regs.p |= 0x30; + if(regs.e) { + regs.p |= 0x30; + } else { + switch((regs.p >> 4) & 3) { + case 0:optbl = optbl_mx;break; + case 1:optbl = optbl_mX;break; + case 2:optbl = optbl_Mx;break; + case 3:optbl = optbl_MX;break; + } + } if(regs.p.x) { regs.x.h = 0x00; regs.y.h = 0x00; @@ -230,8 +231,6 @@ void bCPU::op_plxw() { regs.p.z = (regs.x.w == 0); } -void bCPU::op_plx() { (regs.p.x)?op_plxb():op_plxw(); } - /***************** *** 0x7a: ply *** ***************** @@ -259,8 +258,6 @@ void bCPU::op_plyw() { regs.p.z = (regs.y.w == 0); } -void bCPU::op_ply() { (regs.p.x)?op_plyb():op_plyw(); } - /********************** *** 0xf4: pea addr *** ********************** diff --git a/src/lib/libbase.h b/src/lib/libbase.h new file mode 100644 index 00000000..ed7810d9 --- /dev/null +++ b/src/lib/libbase.h @@ -0,0 +1,30 @@ +/* + libbase : version 0.01 ~byuu +*/ + +#ifndef __LIBBASE +#define __LIBBASE + +#include +#include +#include +#include + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long ulong; + +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 +#endif +#define null 0xffffffff + +#endif diff --git a/src/lib/libconfig.cpp b/src/lib/libconfig.cpp new file mode 100644 index 00000000..5fb4cf31 --- /dev/null +++ b/src/lib/libconfig.cpp @@ -0,0 +1,304 @@ +#include "libbase.h" +#include "libconfig.h" + +bool config_item::changed() { + return (is_string == true) ? (*strsource != strdef) : (*source != def); +} + +config_item::config_item() { + is_string = false; + source = 0; + strsource = 0; + def = 0; + strdef = ""; + type = 0; + name = ""; +} + +void config::add(uint32 *variable, char *name, uint32 def, uint32 type) { +int n; + if(item_count >= 4096)return; + n = item_count; + + item[n] = new config_item(); + + item[n]->is_string = false; + item[n]->name = name; + item[n]->source = variable; + item[n]->def = def; + item[n]->type = type; + *item[n]->source = item[n]->def; + + item_count++; +} + +void config::add(string *variable, char *name, char *def, uint32 type) { +int n; + if(item_count >= 4096)return; + n = item_count; + + item[n] = new config_item(); + item[n]->is_string = true; + item[n]->name = name; + item[n]->strsource = variable; + item[n]->strdef = def; + *item[n]->strsource = item[n]->strdef; + + item_count++; +} + +uint32 config::find(char *name) { + for(int i=0;iname == name) { + return i; + } + } + return null; +} + +uint32 config::get(char *name) { +int i = find(name); + if(i == null)return 0; + return *item[i]->source; +} + +string &config::strget(char *name) { +int i = find(name); + if(i == null) { + static string not_found; + not_found = ""; + return not_found; + } + return *item[i]->strsource; +} + +void config::set(char *name, uint32 value) { +int i = find(name); + if(i == null)return; + *item[i]->source = value; +} + +void config::set(char *name, char *value) { +int i = find(name); + if(i == null)return; + *item[i]->strsource = value; +} + +void config::load(char *fn) { +FILE *fp; +char *buffer; +int i, fsize; +uint32 l; + fp = fopen(fn, "rb"); +/* file doesn't exist yet, do nothing */ + if(!fp)return; + + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + +/* blank file, do nothing */ + if(fsize == 0) { + fclose(fp); + return; + } + + buffer = (char*)malloc(fsize + 1); + fread(buffer, 1, fsize, fp); + fclose(fp); + buffer[fsize] = 0; + + data = buffer; + free(buffer); + replace(data, "\r\n", "\n"); + qreplace(data, "\t", " "); + + split(line, "\n", data); + + for(i=0;isource = 1; + } else if(part[1] == "false" || part[1] == "no" || part[1] == "off" || part[1] == "disabled") { + *item[l]->source = 0; + } else if(item[l]->type == HEX) { + *item[l]->source = strhex(part[1]); + } else { /* fall back on DEC */ + *item[l]->source = strdec(part[1]); + } + } + } + } +} + +/* create a text string from config item[i] to be output via config->save() */ +void config::set_newline(int i) { +char t[16]; + if(item[i]->is_string == true) { + newline = item[i]->name; + newline += " = \""; + newline += *item[i]->strsource; + newline += "\""; + } else { + newline = item[i]->name; + newline += " = "; + switch(item[i]->type) { + case TRUEFALSE: + newline += (*item[i]->source)?"true":"false"; + break; + case YESNO: + newline += (*item[i]->source)?"yes":"no"; + break; + case ONOFF: + newline += (*item[i]->source)?"on":"off"; + break; + case ENABLED: + newline += (*item[i]->source)?"enabled":"disabled"; + break; + case HEX: + sprintf(t, "%x", *item[i]->source); + newline += t; + break; + case DEC: + default: + sprintf(t, "%d", *item[i]->source); + newline += t; + break; + } + } +} + +void config::save(char *fn) { +FILE *fp; +int i, fsize; +uint32 l; +char *buffer; +uint8 set[4096]; +bool blank = false; + fp = fopen(fn, "rb"); + if(!fp) { + blank = true; + } else { + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if(fsize == 0) { + blank = true; + } else { + buffer = (char*)malloc(fsize + 1); + fread(buffer, 1, fsize, fp); + fclose(fp); + buffer[fsize] = 0; + + data = buffer; + free(buffer); + } + } + + fp = fopen(fn, "wb"); +/* no write access? */ + if(!fp)return; + +/* list of config items. if the item is set in the + existing config file, then don't test it to see + if it needs to be written again later on */ + memset(set, 0, item_count); + + if(blank == false) { + replace(data, "\r\n", "\n"); + qreplace(data, "\t", " "); + + split(line, "\n", data); + split(oldline, "\n", data); + + for(i=0;ichanged() == false)continue; + + set_newline(i); + /* prevent a newline from appearing at the top of the file + when the config file is created for the first time */ + if(lines_written == 0 && blank == false)fprintf(fp, "\r\n"); + fprintf(fp, "%s\r\n", *newline); + lines_written++; + } + + fclose(fp); +} + +config::config() { + item_count = 0; +} + +config::~config() { + for(int i=0;i=0;i--) { + delete((_string*)list[i]); + } +} + +uint32 count(string &str) { + return str.count; +} + +void strresize(_string &str, uint32 size) { +char *t; +int sl; + if(str.size == size)return; + sl = strlen(str.s); + t = (char*)malloc(size + 1); + strcpy(t, str.s); + free(str.s); + str.s = t; + str.size = size; +} + +char *strptr(_string &str) { + return str.s; +} + +void strcpy(_string &dest, char *src) { +int srclen = strlen(src); + if(srclen > dest.size) { strresize(dest, srclen); } + strcpy(dest.s, src); +} + +void strset(_string &dest, uint32 pos, uint8 c) { +char *s; + if(pos > dest.size) { strresize(dest, pos); } + dest.s[pos] = c; +} + +void strcat(_string &dest, char *src) { +int srclen, destlen; + srclen = strlen(src); + destlen = strlen(dest.s); + if(srclen + destlen > dest.size) { strresize(dest, srclen + destlen); } + strcat(dest.s, src); +} + +void strinsert(_string &dest, char *src, uint32 pos) { +_string *s = new _string(); + strcpy(*s, strptr(dest) + pos); + strset(dest, pos, 0); + strcat(dest, src); + strcat(dest, *s); + delete(s); +} + +void strremove(_string &dest, uint32 start, uint32 length) { +int destlen; +char *s; +int i, sl = strlen(dest.s); + if(start > dest.size) { strresize(dest, start); } + if(!length) { + strset(dest, start, 0); + return; + } + s = dest.s; + for(i=start;i= 'A' && dest[i] <= 'Z') { + if(dest[i] != src[i] && dest[i] + 0x20 != src[i])return false; + } else if(dest[i] >='a' && dest[i] <= 'z') { + if(dest[i] != src[i] && dest[i] - 0x20 != src[i])return false; + } else { + if(dest[i] != src[i])return false; + } + } + return true; +} + +void strlower(char *str) { +int i, sl = strlen(str); + for(i=0;i= 'A' && str[i] <= 'Z')str[i] += 0x20; + } +} + +void strupper(char *str) { +int i, sl = strlen(str); + for(i=0;i= 'a' && str[i] <= 'z')str[i] -= 0x20; + } +} + +uint32 strpos(char *str, char *key) { +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; + } + return null; +} + +uint32 strqpos(char *str, char *key) { +int i, z, ssl = strlen(str), ksl = strlen(key); +uint8 x; + if(ksl > ssl)return null; + 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; + } else { + i++; + } + } + return null; +} + +void strtr(char *dest, char *before, char *after) { +int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after); + if((bsl != asl) || bsl == 0)return; + for(i=0;i ssl)return 1; + if(!memcmp(str, key, ksl))return 0; + return 1; +} + +uint32 stribegin(char *str, char *key) { +int i, ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return 1; + for(i=0;i= 'A' && str[i] <= 'Z') { + if(str[i] != key[i] && str[i]+0x20 != key[i])return 1; + } else if(str[i] >= 'a' && str[i] <= 'z') { + if(str[i] != key[i] && str[i]-0x20 != key[i])return 1; + } else { + if(str[i] != key[i])return 1; + } + } + return 0; +} + +uint32 strend(char *str, 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; +} + +uint32 striend(char *str, char *key) { +int i, z, ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return 1; + for(i=ssl-ksl, z=0;i= 'A' && str[i] <= 'Z') { + if(str[i] != key[z] && str[i]+0x20 != key[z])return 1; + } else if(str[i] >= 'a' && str[i] <= 'z') { + if(str[i] != key[z] && str[i]-0x20 != key[z])return 1; + } else { + if(str[i] != key[z])return 1; + } + } + return 0; +} + +void strltrim(char *str, char *key) { +int i, ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return; + if(!strbegin(str, key)) { + for(i=0;i ssl)return; + if(!stribegin(str, key)) { + for(i=0;i ssl)return; + if(!strend(str, key)) { + str[ssl - ksl] = 0; + } +} + +void strirtrim(char *str, char *key) { +int ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return; + if(!striend(str, key)) { + str[ssl - ksl] = 0; + } +} + +/* does not work on type char* because function increases string length */ +void strquote(_string &str) { +static string t; + t = "\""; + t += str; + t += "\""; + str = t; +} + +bool strunquote(char *str) { +int i, ssl = strlen(str); +/* make sure string is long enough to have quotes */ + if(ssl < 2)return false; + +/* make sure string actually has quotes */ + if(str[0] == '\"' && str[ssl - 1] == '\"'); + else if(str[0] == '\'' && str[ssl - 1] == '\''); + else return false; + +/* now remove them */ + for(i=0;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) { + x = str[i]; + if(x >= '0' && x <= '9')x -= '0'; + else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a; + else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a; + else return r; + r |= x << m; + } + return r; +} + +int strdec(char *str) { +uint32 m = 1; +int i, r = 0, ssl = strlen(str); +uint8 x; + for(i=0;i= '0' && str[i] <= '9'); + else if(str[i] == '-' && i == 0); + else break; + } + for(--i;i>=0;i--, m*=10) { + x = str[i]; + if(x >= '0' && x <= '9')x -= '0'; + else if(i == 0 && str[i] == '-') { + r *= -1; + return r; + } + else return r; + r += x * m; + } + return r; +} + +uint32 strbin(char *str) { +uint32 r = 0, m = 0; +int i, ssl = strlen(str); +uint8 x; + for(i=0;i=0;i--, m++) { + x = str[i]; + if(str[i] == '0' || str[i] == '1')x -= '0'; + else return r; + r |= x << m; + } + return r; +} + +#include "libstring_math.cpp" +#include "libstring_split.cpp" +#include "libstring_replace.cpp" +#include "libstring_sprintf.cpp" diff --git a/src/lib/libstring.h b/src/lib/libstring.h new file mode 100644 index 00000000..fd924a94 --- /dev/null +++ b/src/lib/libstring.h @@ -0,0 +1,276 @@ +/* + libstring : version 0.04 ~byuu +*/ + +#ifndef __LIBSTRING +#define __LIBSTRING + +#include "libvector.h" + +class string; +class _string; + +uint32 count(string &str); +void strresize(_string &str, uint32 size); +char* strptr(_string &str); +void strcpy(_string &dest, char *src); +void strset(_string &dest, uint32 pos, uint8 c); +void strcat(_string &dest, char *src); +void strinsert(_string &dest, char *src, uint32 pos); +void strremove(_string &dest, uint32 start, uint32 length = 0); +bool stricmp(char *dest, char *src); +void strlower(char *str); +void strupper(char *str); +uint32 strpos(char *str, char *key); +uint32 strqpos(char *str, char *key); +void strtr(char *dest, char *before, char *after); +uint32 strbegin(char *str, char *key); +uint32 stribegin(char *str, char *key); +uint32 strend(char *str, char *key); +uint32 striend(char *str, char *key); +void strltrim(char *str, char *key); +void striltrim(char *str, char *key); +void strrtrim(char *str, char *key); +void strirtrim(char *str, char *key); +void strquote(_string &str); +bool strunquote(char *str); +uint32 strhex(char *str); +int strdec(char *str); +uint32 strbin(char *str); +uint32 strmath(char *in_str); +uint32 strmathentity(char *str); +void replace (_string &str, char *key, char *token); +void qreplace(_string &str, char *key, char *token); +void split (string &dest, char *key, char *src); +void qsplit(string &dest, char *key, char *src); +void sprintf(_string &str, char *s, ...); + +class _string { +public: +char *s; +uint32 size; + +/* * */ + inline char* operator*() { return s; } + +/* = */ + inline _string& operator=(char *cpy); + inline _string& operator=(_string &cpy); + inline _string& operator=(string &cpy); + +/* += */ + inline _string& operator+=(char *cat); + inline _string& operator+=(_string &cat); + inline _string& operator+=(string &cat); + +/* -= */ + inline _string& operator-=(char *cut); + inline _string& operator-=(_string &cut); + inline _string& operator-=(string &cut); + +/* == */ + inline bool operator==(char *cmp); + inline bool operator==(_string &cmp); + inline bool operator==(string &cmp); + +/* != */ + inline bool operator!=(char *cmp); + inline bool operator!=(_string &cmp); + inline bool operator!=(string &cmp); + + inline operator char*() { return s; } + + _string(); + ~_string(); +}; + +class string { +public: +vector<_string*> list; +uint32 count, listcount; + void addto(uint32 num); //creates all needed strings to make list[num] valid + _string &str(uint32 num); //gets a _string reference, creating it + new strings if needed + +/* * */ + inline char* operator*() { return strptr(str(0)); } + +/* = */ + inline string& operator=(char *cpy); + inline string& operator=(_string &cpy); + inline string& operator=(string &cpy); + +/* += */ + inline string& operator+=(char *cat); + inline string& operator+=(_string &cat); + inline string& operator+=(string &cat); + +/* -= */ + inline string& operator-=(char *cut); + inline string& operator-=(_string &cut); + inline string& operator-=(string &cut); + +/* == */ + inline bool operator==(char *cmp); + inline bool operator==(_string &cmp); + inline bool operator==(string &cmp); + +/* != */ + inline bool operator!=(char *cmp); + inline bool operator!=(_string &cmp); + inline bool operator!=(string &cmp); + + inline operator char*() { return str(0).s; } + inline operator _string&() { return str(0); } + inline _string& operator[](uint32 i) { return str(i); } + inline _string& operator[](int i) { return str(i); } + + string(); + ~string(); +}; + +// +// = +// +inline _string& _string::operator=(char *cpy) { + strcpy(*this, cpy); + return *this; +} +inline _string& _string::operator=(_string &cpy) { + strcpy(*this, cpy); + return *this; +} +inline _string& _string::operator=(string &cpy) { + strcpy(*this, cpy.str(0)); + return *this; +} + +inline string& string::operator=(char *cpy) { + strcpy(str(0), cpy); + return *this; +} +inline string& string::operator=(_string &cpy) { + strcpy(str(0), cpy); + return *this; +} +inline string& string::operator=(string &cpy) { + strcpy(str(0), cpy.str(0)); + return *this; +} + +// +// += +// +inline _string& _string::operator+=(char *cat) { + strcat(*this, cat); + return *this; +} +inline _string& _string::operator+=(_string &cat) { + strcat(*this, cat); + return *this; +} +inline _string& _string::operator+=(string &cat) { + strcat(*this, cat.str(0)); + return *this; +} + +inline string& string::operator+=(char *cat) { + strcat(str(0), cat); + return *this; +} +inline string& string::operator+=(_string &cat) { + strcat(str(0), cat); + return *this; +} +inline string& string::operator+=(string &cat) { + strcat(str(0), cat.str(0)); + return *this; +} + +// +// -= +// +inline _string& _string::operator-=(char *cut) { + strrtrim(*this, cut); + return *this; +} +inline _string& _string::operator-=(_string &cut) { + strrtrim(*this, cut); + return *this; +} +inline _string& _string::operator-=(string &cut) { + strrtrim(*this, cut.str(0)); + return *this; +} + +inline string& string::operator-=(char *cut) { + strrtrim(str(0), cut); + return *this; +} +inline string& string::operator-=(_string &cut) { + strrtrim(str(0), cut); + return *this; +} +inline string& string::operator-=(string &cut) { + strrtrim(str(0), cut.str(0)); + return *this; +} + +// +// == +// +inline bool _string::operator==(char *cmp) { + if(!strcmp(*this, cmp))return true; + return false; +} +inline bool _string::operator==(_string &cmp) { + if(!strcmp(*this, cmp))return true; + return false; +} +inline bool _string::operator==(string &cmp) { + if(!strcmp(*this, cmp.str(0)))return true; + return false; +} + +inline bool string::operator==(char *cmp) { + if(!strcmp(str(0), cmp))return true; + return false; +} +inline bool string::operator==(_string &cmp) { + if(!strcmp(str(0), cmp))return true; + return false; +} +inline bool string::operator==(string &cmp) { + if(!strcmp(str(0), cmp.str(0)))return true; + return false; +} + +// +// != +// +inline bool _string::operator!=(char *cmp) { + if(!strcmp(*this, cmp))return false; + return true; +} +inline bool _string::operator!=(_string &cmp) { + if(!strcmp(*this, cmp))return false; + return true; +} +inline bool _string::operator!=(string &cmp) { + if(!strcmp(*this, cmp.str(0)))return false; + return true; +} + +inline bool string::operator!=(char *cmp) { + if(!strcmp(str(0), cmp))return false; + return true; +} +inline bool string::operator!=(_string &cmp) { + if(!strcmp(str(0), cmp))return false; + return true; +} +inline bool string::operator!=(string &cmp) { + if(!strcmp(str(0), cmp.str(0)))return false; + return true; +} + +#endif diff --git a/src/lib/libstring_math.cpp b/src/lib/libstring_math.cpp new file mode 100644 index 00000000..e2c26697 --- /dev/null +++ b/src/lib/libstring_math.cpp @@ -0,0 +1,177 @@ +#define STRMATH_ADD 1 +#define STRMATH_SUB 2 +#define STRMATH_MUL 3 +#define STRMATH_DIV 4 +#define STRMATH_MOD 5 +#define STRMATH_AND 6 +#define STRMATH_OR 7 +#define STRMATH_XOR 8 +#define STRMATH_SHL 9 +#define STRMATH_SHR 10 + +#define STRMATH_LINKED 64 + +#define STRMATHMODE_NEG 1 +#define STRMATHMODE_NOT 2 + +#define __strunktonum() \ + if (s1[0] == '0' && s1[1] == 'x')r = strhex(s1 + 2); \ + else if(s1[0] == '0' && s1[1] == 'b')r = strbin(s1 + 2); \ + else r = strdec(s1) + +#define __strmath_setmode() \ + if (str[i] == '-') { mode = STRMATHMODE_NEG; i++; } \ + else if(str[i] == '~') { mode = STRMATHMODE_NOT; i++; } \ + else if(str[i] == '+') { i++; } \ + else mode=0 + +#define __strmath_modeset() \ + if (mode == STRMATHMODE_NEG)r *= -1; \ + else if(mode == STRMATHMODE_NOT)r =~ r + +#define __strmath_set(__x) \ + s1[z] = 0; \ + z = 0; \ + __strunktonum(); \ + __strmath_modeset(); \ + array[array_size++] = r; \ + array_gate[array_size] = __x + +/*************************************** +strmath(str) + resolves all math entities from within + str, and returns numerical result + example: strmath("5+5")=10 +***************************************/ +uint32 p_strmath(char *str) { +int i = 0, ssl = strlen(str); +uint8 x, mode = 0; +uint32 r, array[128], array_size = 0, z = 0; +uint8 array_gate[128]; +char *s1; + if(!ssl)return 0; + s1 = (char*)malloc(ssl + 1); + __strmath_setmode(); + while(i < ssl) { + x = str[i++]; + if (x == '+') { __strmath_set(STRMATH_ADD); __strmath_setmode(); } + else if(x == '-') { __strmath_set(STRMATH_SUB); __strmath_setmode(); } + else if(x == '*') { __strmath_set(STRMATH_MUL); __strmath_setmode(); } + else if(x == '/') { __strmath_set(STRMATH_DIV); __strmath_setmode(); } + else if(x == '%') { __strmath_set(STRMATH_MOD); __strmath_setmode(); } + else if(x == '&') { __strmath_set(STRMATH_AND); __strmath_setmode(); } + else if(x == '|') { __strmath_set(STRMATH_OR ); __strmath_setmode(); } + else if(x == '^') { __strmath_set(STRMATH_XOR); __strmath_setmode(); } + else if(x == '<' && str[i] == '<') { __strmath_set(STRMATH_SHL); i++; __strmath_setmode(); } + else if(x == '>' && str[i] == '>') { __strmath_set(STRMATH_SHR); i++; __strmath_setmode(); } + else s1[z++] = x; + } + s1[z] = 0; + __strunktonum(); + __strmath_modeset(); + array[array_size++] = r; + free(s1); + + for(i=1;i>= array[i]; array_gate[i] = STRMATH_LINKED; } + } + + for(i=1;i maxpdepth)maxpdepth = pdepth; + } else if(str[i]==')') { + if(pdepth == 0) { + free(str); + return null; //error! too many )'s + } + pdepth --; + } + } + + if(pdepth != 0) { + free(str); + return null; //error! unequal ('s to )'s + } + + pdepth = maxpdepth; + while(pdepth) { + cpdepth = 0; + for(i=0;i' && str[i+1] == '>'))return 1; + } + return 0; +} diff --git a/src/lib/libstring_replace.cpp b/src/lib/libstring_replace.cpp new file mode 100644 index 00000000..9857ec16 --- /dev/null +++ b/src/lib/libstring_replace.cpp @@ -0,0 +1,82 @@ +void replace(_string &str, char *key, char *token) { +int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); +uint32 replace_count = 0, size = ssl; +char *data; + if(ksl > ssl)return; + if(tsl > ksl) { //the new string may be longer than the old string... + for(i=0;i<=ssl-ksl;) { //so let's find out how big of a string we'll need... + if(!memcmp(str.s + i, key, ksl)) { + replace_count++; + i += ksl; + } else i++; + } + size = ssl + ((tsl - ksl) * replace_count); + if(size > str.size)strresize(str, size); + } + data = (char*)malloc(size + 1); + for(i=z=0;i ssl)return; + if(tsl > ksl) { + for(i=0;i<=ssl-ksl;) { + x = str.s[i]; + if(x == '\"' || x == '\'') { + l = i; + i++; + while(str.s[i++] != x) { + if(i == ssl) { + i = l; + break; + } + } + } + if(!memcmp(str.s + i, key, ksl)) { + replace_count++; + i += ksl; + } else i++; + } + size = ssl + ((tsl - ksl) * replace_count); + if(size > str.size)strresize(str, size); + } + data = (char*)malloc(size + 1); + for(i=z=0;i= ssl)i = l; + else { + memcpy(data + z, str.s + l, i - l); + z += i - l; + } + } + if(i <= ssl - ksl) { + if(!memcmp(str.s + i, key, ksl)) { + memcpy(data + z, token, tsl); + z += tsl; + i += ksl; + replace_count++; + } else data[z++] = str.s[i++]; + } else data[z++] = str.s[i++]; + } + data[z] = 0; + strcpy(str, data); + free(data); +} diff --git a/src/lib/libstring_split.cpp b/src/lib/libstring_split.cpp new file mode 100644 index 00000000..1e2eefbe --- /dev/null +++ b/src/lib/libstring_split.cpp @@ -0,0 +1,41 @@ +void split(string &dest, char *key, char *src) { +int i, ssl = strlen(src), ksl = strlen(key); +uint8 x; +uint32 lp = 0, split_count = 0; + for(i=0;i<=ssl-ksl;) { + if(!memcmp(src + i, key, ksl)) { + x = src[i]; + src[i] = 0; + strcpy(dest[split_count++], src + lp); + src[i] = x; + i += ksl; + lp = i; + } else i++; + } + strcpy(dest[split_count++], src + lp); + dest.count = split_count; +} + +void qsplit(string &dest, char *key, char *src) { +int i, z, ssl = strlen(src), ksl = strlen(key); +uint8 x; +uint32 lp = 0, split_count = 0; + for(i=0;i<=ssl-ksl;) { + x = src[i]; + if(x=='\"' || x=='\'') { + z = i++; + while(src[i] != x && i < ssl)i++; + if(i >= ssl)i = z; + } + if(!memcmp(src + i, key, ksl)) { + x = src[i]; + src[i] = 0; + strcpy(dest[split_count++], src + lp); + src[i] = x; + i += ksl; + lp = i; + } else i++; + } + strcpy(dest[split_count++], src + lp); + dest.count = split_count; +} diff --git a/src/lib/libstring_sprintf.cpp b/src/lib/libstring_sprintf.cpp new file mode 100644 index 00000000..ab86833d --- /dev/null +++ b/src/lib/libstring_sprintf.cpp @@ -0,0 +1,69 @@ +void numtobin(char *s, uint32 num) { +uint32 mask = 0x80000000, len = 0, z = 0; + for(;mask;mask>>=1,len++) { if(num&mask)break; } + len = 32 - len; + do { + if(num&(1<<(len-1)))s[z++] = '1'; + else s[z++] = '0'; + }while(--len); + s[z] = 0; +} + +void sprintf(_string &str, char *s, ...) { +va_list args; +char t[2], n[256]; +int i, l, sl, z; +uint8 pad_type, pad_len; +uint32 num; +char *r; + va_start(args, s); + strcpy(str, ""); + for(i=0;i= '0' && s[i+2] <= '9')) { + pad_type = 1; + if(s[i+3] >= '0' && s[i+3] <= '9') { pad_len = (s[i+2]-'0')*10 + (s[i+3]-'0'); i+=4; } + else { pad_len = (s[i+2]-'0'); i+=3; } + } + else if(s[i] >= '0' && s[i] <= '9') { + pad_type = 2; + if(s[i+1] >= '0' && s[i+1] <= '9') { pad_len = (s[i]-'0')*10 + (s[i+1]-'0'); i+=2; } + else { pad_len = (s[i]-'0'); i+=1; } + } + else { pad_type = 0; } + + if(s[i] == 'd') { + num = va_arg(args, uint32); + sprintf(n, "%d", num); + } else if(s[i] == 'x') { + num = va_arg(args, uint32); + sprintf(n, "%x", num); + } else if(s[i] == 'b') { + num = va_arg(args, uint32); + numtobin(n, num); + } else if(s[i] == 's') { + r = va_arg(args, char*); + } + + if(pad_type != 0) { + if(s[i] == 's')sl = strlen(r); + else sl = strlen(n); + if(sl < pad_len) { + while(sl < pad_len) { + strcat(str, (pad_type == 1)?"0":" "); + sl++; + } + } + } + + if(s[i] == 's')strcat(str, r); + else strcat(str, n); + } else { + t[0] = s[i]; + t[1] = 0; + strcat(str, t); + } + } + va_end(args); +} diff --git a/src/lib/libvector.h b/src/lib/libvector.h new file mode 100644 index 00000000..d0e98ac0 --- /dev/null +++ b/src/lib/libvector.h @@ -0,0 +1,71 @@ +/* + libvector : version 0.01 ~byuu +*/ + +#ifndef __LIBVECTOR +#define __LIBVECTOR + +template class vector { +public: +T *array; +int size, sizelimit; + int findsize(int newsize) { + int r = 1; + while(r >= 1) { + r <<= 1; + if(r > sizelimit)return sizelimit; + if(r >= newsize)return r; + } + return size; + } + + void resize(int newsize) { + T *newarray; + newsize = findsize(newsize); + + if(newsize > sizelimit)newsize = sizelimit; + if(newsize == size)return; + + newarray = (T*)malloc(sizeof(T) * newsize); + if(newsize >= size) { + memcpy(newarray, array, sizeof(T) * size); + } else { + memcpy(newarray, array, sizeof(T) * newsize); + } + free(array); + + array = newarray; + size = newsize; + } + + vector(int newsize, int newsizelimit) { + size = newsize; + sizelimit = newsizelimit; + array = (T*)malloc(sizeof(T) * size); + } + + vector(int newsize) { + size = newsize; + sizelimit = 1 << 24; + array = (T*)malloc(sizeof(T) * size); + } + + vector() { + size = 16; + sizelimit = 1 << 24; + array = (T*)malloc(sizeof(T) * size); + } + + ~vector() { + if(array)free(array); + } + + inline T &operator[](int index) { + static T __null = (T)0; + if(index >= size)resize(index + 1); + if(index > sizelimit)return __null; + return array[index]; + } +}; + +#endif diff --git a/src/memory/bmemory/bmemory.cpp b/src/memory/bmemory/bmemory.cpp index ce5313fb..f9affb43 100644 --- a/src/memory/bmemory/bmemory.cpp +++ b/src/memory/bmemory/bmemory.cpp @@ -307,6 +307,15 @@ uint32 b, w; snes->notify(SNES::MEM_WRITE, addr, value); } +void bMemBus::power() { + memset(wram, 0, 0x020000); + reset(); +} + +void bMemBus::reset() { + fastROM = false; +} + bMemBus::bMemBus() { rom = new bROM(); diff --git a/src/memory/bmemory/bmemory.h b/src/memory/bmemory/bmemory.h index e5803e33..c45e079f 100644 --- a/src/memory/bmemory/bmemory.h +++ b/src/memory/bmemory/bmemory.h @@ -26,6 +26,9 @@ byte *wram; uint8 read (uint32 addr); void write(uint32 addr, byte value); + void power(); + void reset(); + bMemBus(); ~bMemBus(); }; diff --git a/src/memory/memory.h b/src/memory/memory.h index 9004dc5c..61812599 100644 --- a/src/memory/memory.h +++ b/src/memory/memory.h @@ -33,6 +33,9 @@ bool fastROM; virtual bool set_mmio_mapper(uint16 addr, MMIO *mapper); virtual uint8 speed(uint32 addr); + virtual void power() = 0; + virtual void reset() = 0; + MemBus(); ~MemBus(); }; diff --git a/src/ppu/bppu/bppu.cpp b/src/ppu/bppu/bppu.cpp index 85f64779..ae6025c9 100644 --- a/src/ppu/bppu/bppu.cpp +++ b/src/ppu/bppu/bppu.cpp @@ -7,11 +7,25 @@ void bPPU::run() {} void bPPU::scanline() { uint16 v = clock->vcounter(); if(v > 0 && v < clock->visible_scanlines()) { + if(clock->interlace() || regs.oam_halve == true) { + output->frame_mode |= PPUOutput::INTERLACE; + output->scanline_mode[v] |= PPUOutput::INTERLACE; + } + if(regs.bg_mode == 5 || regs.bg_mode == 6) { + output->frame_mode |= PPUOutput::DOUBLEWIDTH; + output->scanline_mode[v] |= PPUOutput::DOUBLEWIDTH; + } render_line(v); } } -void bPPU::frame() {} +void bPPU::frame() { + snes->notify(SNES::RENDER_FRAME); + output->frame_mode = PPUOutput::NORMAL; + for(int i=0;i<239;i++) { + output->scanline_mode[i] = PPUOutput::NORMAL; + } +} void bPPU::power() { memset(vram, 0, 65536); @@ -21,7 +35,8 @@ void bPPU::power() { } void bPPU::reset() { - memset(output, 0, 512 * 478 * 2); + memset(output->buffer, 0, 512 * 478 * 2); + frame(); //$2100 regs.display_disabled = 0; diff --git a/src/ppu/bppu/bppu_mmio.cpp b/src/ppu/bppu/bppu_mmio.cpp index f87f067e..4122ff31 100644 --- a/src/ppu/bppu/bppu_mmio.cpp +++ b/src/ppu/bppu/bppu_mmio.cpp @@ -487,13 +487,6 @@ uint16 r = regs.vcounter; //STAT77 uint8 bPPU::mmio_r213e() { uint8 r = 0x00; - r |= clock->interlace_field() << 7; - if(!(cpu->pio_status() & 0x80)) { - r |= 1 << 6; - } else if(regs.counters_latched == true) { - r |= 1 << 6; - regs.counters_latched = false; - } r |= 0x01; //PPU1 version number return r; } @@ -503,6 +496,14 @@ uint8 bPPU::mmio_r213f() { uint8 r = 0x00; regs.latch_hcounter = 0; regs.latch_vcounter = 0; + + r |= clock->interlace_field() << 7; + if(!(cpu->pio_status() & 0x80)) { + r |= 1 << 6; + } else if(regs.counters_latched == true) { + r |= 1 << 6; + regs.counters_latched = false; + } r |= (1 << 5); r |= 0x03; //PPU2 version number return r; diff --git a/src/ppu/bppu/bppu_render.cpp b/src/ppu/bppu/bppu_render.cpp index cbac39e2..9640a9a6 100644 --- a/src/ppu/bppu/bppu_render.cpp +++ b/src/ppu/bppu/bppu_render.cpp @@ -113,7 +113,7 @@ void bPPU::render_line_mode7() { void bPPU::render_line(uint16 line) { if(regs.display_disabled == true) { - memset(output + (line << 1) * 512, 0, 2048); + memset(output->buffer + (line << 1) * 512, 0, 2048); return; } diff --git a/src/ppu/bppu/bppu_render.h b/src/ppu/bppu/bppu_render.h index 7ee49de5..128b54ec 100644 --- a/src/ppu/bppu/bppu_render.h +++ b/src/ppu/bppu/bppu_render.h @@ -56,8 +56,8 @@ struct { }current_sprite; void render_line_to_output(); -uint16 addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg); -uint16 addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg); +inline uint16 addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg); +inline uint16 addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg); void render_bg_tile(uint8 color_depth, uint8 bg, uint16 tile_num); void set_pixel(uint8 bg, uint16 x, uint8 pal_index); void set_layer_pixels(uint8 layer_count, uint8 *layer_bg_lookup); diff --git a/src/ppu/bppu/bppu_render_main.cpp b/src/ppu/bppu/bppu_render_main.cpp index c6acc8ca..875a77ce 100644 --- a/src/ppu/bppu/bppu_render_main.cpp +++ b/src/ppu/bppu/bppu_render_main.cpp @@ -14,7 +14,7 @@ namespace bPPUAddSubTables { }; }; -uint16 bPPU::addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg) { +inline uint16 bPPU::addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg) { int r, g, b; uint16 cdest = pal_pixel(cdest_index); uint16 csrc = pal_pixel(csrc_index); @@ -52,7 +52,7 @@ uint16 res; return ((r) | (g << 5) | (b << 10)); } -uint16 bPPU::addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg) { +inline uint16 bPPU::addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg) { int r, g, b; uint16 cdest = pal_pixel(cdest_index); uint16 csrc = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10); @@ -190,16 +190,17 @@ uint8 *dest; void bPPU::render_line_to_output() { int x, x1; -uint16 *ptr, *ptri, *ltable; +uint16 *ptr, *ltable; uint16 c, cx, cy; -uint16 screen_width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256; -uint16 vline_pos = clock->vcounter(); +uint16 screen_width; +uint16 v, vline_pos = clock->vcounter(); + v = vline_pos; + screen_width = (output->scanline_mode[v] & PPUOutput::DOUBLEWIDTH)?512:256; - if(clock->interlace() == false) { - ptr = (uint16*)output + ((vline_pos << 1) ) * 512; - ptri = (uint16*)output + ((vline_pos << 1) + 1) * 512; + if(!(output->scanline_mode[v] & PPUOutput::INTERLACE)) { + ptr = (uint16*)output->buffer + ((vline_pos << 1)) * 512; } else { - ptr = (uint16*)output + ((vline_pos << 1) + clock->interlace_field()) * 512; + ptr = (uint16*)output->buffer + ((vline_pos << 1) + clock->interlace_field()) * 512; } ltable = (uint16*)light_table + (regs.display_brightness * 65536); @@ -244,16 +245,12 @@ uint16 vline_pos = clock->vcounter(); break; } - if(clock->interlace() == false) { - *(ptr + (x1 )) = *(ltable + cx); - *(ptri + (x1++)) = *(ltable + cx); - if(screen_width != 256)continue; - *(ptr + (x1 )) = *(ltable + cx); - *(ptri + (x1++)) = *(ltable + cx); + if(screen_width == 256) { + *(ptr + (x1)) = *(ltable + cx); + x1 += 2; } else { - *(ptr + (x1++)) = *(ltable + cx); - if(screen_width != 256)continue; - *(ptr + (x1++)) = *(ltable + cx); + *(ptr + (x1)) = *(ltable + cx); + x1 += 1; } } } diff --git a/src/ppu/ppu.cpp b/src/ppu/ppu.cpp index c29f8817..9b0466a4 100644 --- a/src/ppu/ppu.cpp +++ b/src/ppu/ppu.cpp @@ -1,11 +1,23 @@ #include "../base.h" +PPUOutput::PPUOutput() { + buffer = (uint16*)memalloc(512 * 478 * 2, "PPUOutput::buffer"); + memset(buffer, 0, 512 * 478 * 2); + frame_mode = NORMAL; + for(int i=0;i<239;i++) { + scanline_mode[i] = NORMAL; + } +} + +PPUOutput::~PPUOutput() { + if(buffer)memfree(buffer, "PPUOutput::buffer"); +} + PPU::PPU() { mmio = &mmio_unmapped; - output = (uint16*)memalloc(512 * 478 * 2, "PPU::output"); - memset(output, 0, 512 * 478 * 2); + output = new PPUOutput(); } PPU::~PPU() { - if(output)memfree(output, "PPU::output"); + if(output)delete(output); } diff --git a/src/ppu/ppu.h b/src/ppu/ppu.h index d68452b0..c008bcc3 100644 --- a/src/ppu/ppu.h +++ b/src/ppu/ppu.h @@ -1,7 +1,21 @@ +class PPUOutput { +public: +enum { + NORMAL = 0, + INTERLACE = 1, + DOUBLEWIDTH = 2 +}; +uint8 frame_mode; +uint8 scanline_mode[239]; +uint16 *buffer; + PPUOutput(); + ~PPUOutput(); +}; + class PPU { public: -uint16 *output; -MMIO *mmio; +PPUOutput *output; +MMIO *mmio; virtual uint8 vram_read (uint16 addr) = 0; virtual void vram_write (uint16 addr, uint8 value) = 0; virtual uint8 oam_read (uint16 addr) = 0; diff --git a/src/reader/reader.cpp b/src/reader/reader.cpp index a6089f7c..d430885b 100644 --- a/src/reader/reader.cpp +++ b/src/reader/reader.cpp @@ -12,7 +12,12 @@ int i; char *filetype = fn + i; /* make sure we support this file format before loading it */ - if(strcmp(filetype, ".smc"))return false; + if(stricmp(filetype, ".smc") && + stricmp(filetype, ".swc") && + stricmp(filetype, ".fig") && + stricmp(filetype, ".ufo") && + stricmp(filetype, ".gd3") && + stricmp(filetype, ".078"))return false; fp = fopen(fn, "rb"); if(!fp)return false; @@ -21,7 +26,12 @@ char *filetype = fn + i; fsize = ftell(fp); fseek(fp, 0, SEEK_SET); - if(!strcmp(filetype, ".smc")) { + if(!stricmp(filetype, ".smc") || + !stricmp(filetype, ".swc") || + !stricmp(filetype, ".fig") || + !stricmp(filetype, ".ufo") || + !stricmp(filetype, ".gd3") || + !stricmp(filetype, ".078")) { /* remove header if it exists */ if((fsize & 0xfff) == 0x200) { fsize -= 0x200; diff --git a/src/snes/snes.cpp b/src/snes/snes.cpp index e26a8ca3..a5510833 100644 --- a/src/snes/snes.cpp +++ b/src/snes/snes.cpp @@ -8,7 +8,7 @@ void SNES::power() { clock->power(); cpu->power(); ppu->power(); - mem_bus->fastROM = false; + mem_bus->power(); int i; mem_bus->flush_mmio_mappers(); @@ -17,6 +17,8 @@ int i; for(i=0x2180;i<=0x2183;i++)mem_bus->set_mmio_mapper(i, cpu->mmio); mem_bus->set_mmio_mapper(0x21c2, cpu->mmio); mem_bus->set_mmio_mapper(0x21c3, cpu->mmio); + mem_bus->set_mmio_mapper(0x4016, cpu->mmio); + mem_bus->set_mmio_mapper(0x4017, cpu->mmio); for(i=0x4200;i<=0x421f;i++)mem_bus->set_mmio_mapper(i, cpu->mmio); for(i=0x4300;i<=0x437f;i++)mem_bus->set_mmio_mapper(i, cpu->mmio); } @@ -25,7 +27,7 @@ void SNES::reset() { clock->reset(); cpu->reset(); ppu->reset(); - mem_bus->fastROM = false; + mem_bus->reset(); } /*************************** diff --git a/src/snes/snes.h b/src/snes/snes.h index 022d880f..aeff4b21 100644 --- a/src/snes/snes.h +++ b/src/snes/snes.h @@ -28,6 +28,7 @@ enum { //debugging functions enum { NO_ACTION = 0, + RENDER_FRAME, CPU_EXEC_OPCODE, MEM_READ, MEM_WRITE, VRAM_READ, VRAM_WRITE, diff --git a/src/win/Makefile b/src/win/Makefile index 09278bbb..f0d80f1e 100644 --- a/src/win/Makefile +++ b/src/win/Makefile @@ -1,6 +1,7 @@ CC = cl CFLAGS = /nologo /O2 /Ob2 OBJS = winmain.obj \ + libstring.obj libconfig.obj \ clock.obj bclock.obj \ memory.obj bmemory.obj \ reader.obj \ @@ -21,6 +22,14 @@ clean: winmain.obj: *.cpp *.h $(CC) $(CFLAGS) /c winmain.cpp +################# +### libraries ### +################# +libstring.obj: ../lib/*.cpp ../lib/*.h + $(CC) $(CFLAGS) /c ../lib/libstring.cpp +libconfig.obj: ../lib/*.cpp ../lib/*.h + $(CC) $(CFLAGS) /c ../lib/libconfig.cpp + ############# ### clock ### ############# diff --git a/src/win/bsnes.cpp b/src/win/bsnes.cpp index 40da0a78..1450a00d 100644 --- a/src/win/bsnes.cpp +++ b/src/win/bsnes.cpp @@ -33,10 +33,10 @@ void bSNES::run() { switch(run_status) { case RUN: - while(clock->update_frame() == false) { + while(update_frame == false) { clock->run(); } - render_frame(); + update_frame = false; return; case STOP: break; @@ -53,8 +53,8 @@ void bSNES::run() { break; case RUNTOFRAME: clock->run(); - if(clock->update_frame() == true) { - render_frame(); + if(update_frame == true) { + update_frame = false; set_status(STOP); disassemble_cpu_op(); } else if(w_bp->hit() == true) { @@ -83,14 +83,10 @@ void bSNES::run() { } break; } - - if(clock->update_frame() == true) { - render_frame(); - } } void bSNES::render_frame() { - renderer.update(); + renderer->update(); } /*********************** @@ -229,6 +225,15 @@ void bSNES::write(uint8 type, uint32 addr, uint8 value) { } void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { +/* system messages */ + switch(message) { + case RENDER_FRAME: + update_frame = true; + render_frame(); + break; + } + +/* debugging messages */ if(is_debugger_enabled == false)return; switch(message) { @@ -262,6 +267,9 @@ void bSNES::notify(uint32 message, uint32 param1, uint32 param2) { void bSNES::disassemble_cpu_op() { char t[512]; +/* don't disassemble opcodes when no ROM is loaded */ + if(is_debugger_activated == false)return; + /* don't disassemble opcodes that won't be printed to console/traced to log anyway */ if(!w_console->can_write(Console::CPU_MESSAGE) && !w_console->tracing_enabled)return; @@ -311,6 +319,10 @@ void bSNES::debugger_update() { disassemble_cpu_op(); } +bool bSNES::debugger_activated() { + return is_debugger_activated; +} + void bSNES::debugger_activate() { HWND hwnd; uint32 i, style; @@ -343,6 +355,8 @@ uint32 i, style; SetWindowLong(hwnd, GWL_STYLE, style); } InvalidateRect(w_memory->hwnd, 0, TRUE); + + is_debugger_activated = true; } void bSNES::debugger_deactivate() { @@ -378,11 +392,14 @@ uint32 i, style; } w_memory->clear(); InvalidateRect(w_memory->hwnd, 0, TRUE); + + is_debugger_activated = false; } bSNES::bSNES() { - run_status = STOP; + run_status = STOP; debug_command = false; + update_frame = false; debugger_disable(); } diff --git a/src/win/bsnes.h b/src/win/bsnes.h index 3838a528..bcb23c0b 100644 --- a/src/win/bsnes.h +++ b/src/win/bsnes.h @@ -8,12 +8,18 @@ bool l, r, select, start; class bSNES : public SNES { private: +//If true, indicates a ROM is loaded and debugger output +//is possible. +bool is_debugger_activated; + //When true, notify() ignores read/write requests, as they //have been generated by the debugging interface and not by //the emulator. bool debug_command; uint32 run_status; +bool update_frame; + bJoypad joypad1, joypad2; public: @@ -56,6 +62,7 @@ struct { //whether or not the debugger *can* be used //e.g., debugger cannot be used without ROM loaded + bool debugger_activated(); void debugger_activate(); void debugger_deactivate(); diff --git a/src/win/config.cpp b/src/win/config.cpp new file mode 100644 index 00000000..1c28ad53 --- /dev/null +++ b/src/win/config.cpp @@ -0,0 +1,15 @@ +#define __config_add(name, def, type) add(&name, #name, def, type) + +class Config : public config { +public: + +struct { + uint32 mode; + uint32 use_vram; +}video; + + Config() { + __config_add(video.mode, 1, DEC); + __config_add(video.use_vram, true, TRUEFALSE); + } +}cfg; diff --git a/src/win/lib.cpp b/src/win/lib.cpp index 2c9b27f3..8486ece7 100644 --- a/src/win/lib.cpp +++ b/src/win/lib.cpp @@ -68,44 +68,6 @@ va_list args; } } -uint32 strhex(char *str) { -uint32 r = 0, m = 0; -int i, ssl = strlen(str); -uint8 x; - for(i=0;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) { - x = str[i]; - if(x >= '0' && x <= '9')x -= '0'; - else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a; - else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a; - else return r; - r |= x << m; - } - return r; -} - -uint32 strdec(char *str) { -uint32 m = 1; -int i, r = 0, ssl = strlen(str); -uint8 x; - for(i=0;i= '0' && str[i] <= '9'); - else break; - } - for(--i;i>=0;i--, m*=10) { - x = str[i]; - if(x >= '0' && x <= '9')x -= '0'; - else return r; - r += x * m; - } - return r; -} - uint32 load_file(char *fn, uint8 **buffer) { FILE *fp; uint8 *data; diff --git a/src/win/timer.cpp b/src/win/timer.cpp new file mode 100644 index 00000000..36e973fc --- /dev/null +++ b/src/win/timer.cpp @@ -0,0 +1,43 @@ +class fpstimer { +private: +SYSTEMTIME st; +int second, ticks; +public: + void start(); + void tick(); + int get_ticks(); + void reset(); + bool second_passed(); + + fpstimer(); +}; + +void fpstimer::start() { + GetSystemTime(&st); + second = st.wSecond; +} + +void fpstimer::tick() { + ticks++; +} + +int fpstimer::get_ticks() { + return ticks; +} + +void fpstimer::reset() { + ticks = 0; +} + +bool fpstimer::second_passed() { + GetSystemTime(&st); + if(st.wSecond != second) { + second = st.wSecond; + return true; + } + return false; +} + +fpstimer::fpstimer() { + second = ticks = 0; +} diff --git a/src/win/ui.cpp b/src/win/ui.cpp index 68c587c4..b7f18d31 100644 --- a/src/win/ui.cpp +++ b/src/win/ui.cpp @@ -29,6 +29,7 @@ void CreateWindows() { } void init_ui0() { + renderer = new Render(); w_main = new MainWindow(); w_console = new Console(); w_bp = new BreakpointEditor(); @@ -39,7 +40,7 @@ void init_ui1() { CreateFonts(); CreateWindows(); SetFocus(w_main->hwnd); - renderer.set_window(w_main->hwnd); - renderer.to_windowed(); + renderer->set_window(w_main->hwnd); + renderer->to_windowed(); bsnes->debugger_deactivate(); } diff --git a/src/win/ui.h b/src/win/ui.h index e5384512..e2c8d5b9 100644 --- a/src/win/ui.h +++ b/src/win/ui.h @@ -141,7 +141,7 @@ bool visible, menu_visible; class MainWindow : public Window { public: -uint8 video_mode, frameskip; +uint8 frameskip; void set_frameskip(uint8 fs); void set_video_mode(uint8 mode); void menu_load(); @@ -227,7 +227,7 @@ uint32 edit_mode, edit_addr, edit_mask; MemoryEditor *w_memory; #include -class render { +class Render { public: LPDIRECTDRAW lpdd; LPDIRECTDRAWSURFACE lpdds, lpddsb; @@ -239,13 +239,14 @@ uint8 color_depth; void set_window(HWND hwnd_handle); void to_windowed(); void to_fullscreen(); + void set_source_window(RECT *rs); void redraw(); void update16(); void update32(); void update(); void destroy(); void update_color_lookup_table(); - render(); + Render(); }; -render renderer; +Render *renderer; diff --git a/src/win/ui_main.cpp b/src/win/ui_main.cpp index 9746b55c..1d5bf2d1 100644 --- a/src/win/ui_main.cpp +++ b/src/win/ui_main.cpp @@ -12,35 +12,37 @@ void MainWindow::set_frameskip(uint8 fs) { CheckMenuItem(w_main->hmenu, MENU_SETTINGS_FRAMESKIP_OFF + fs, MF_CHECKED); clock->set_frameskip(fs); + w_main->frameskip = fs; } void MainWindow::set_video_mode(uint8 mode) { + hide(); CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED); CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED); CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_960x720w, MF_UNCHECKED); switch(mode) { case VIDEOMODE_256x224w: CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_CHECKED); - w_main->resize(256, 223); + resize(256, 223); break; case VIDEOMODE_512x448w: CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_512x448w, MF_CHECKED); - w_main->resize(512, 446); + resize(512, 446); break; case VIDEOMODE_960x720w: CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_960x720w, MF_CHECKED); - w_main->resize(960, 720); + resize(960, 720); break; } if(bsnes->debugger_enabled() == true) { - w_main->to_bottom(); - w_main->to_right(); + to_bottom(); + to_right(); } else { - w_main->to_middle(); - w_main->to_center(); + to_middle(); + to_center(); } - video_mode = mode; - w_main->show(); + cfg.video.mode = mode; + show(); } void MainWindow::menu_load() { @@ -135,7 +137,7 @@ long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { PostQuitMessage(0); break; case WM_PAINT: - renderer.redraw(); + renderer->redraw(); break; } return DefWindowProc(hwnd, msg, wparam, lparam); @@ -199,11 +201,10 @@ HMENU hsubmenu, hbranchmenu; AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_DEBUGGER, "&Debugger"); AppendMenu(w_main->hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings"); - w_main->set_video_mode(w_main->video_mode); - w_main->set_frameskip(0); w_main->show_menu(); + w_main->set_video_mode(cfg.video.mode); + w_main->set_frameskip(0); } MainWindow::MainWindow() { - video_mode = VIDEOMODE_512x448w; } diff --git a/src/win/ui_render.cpp b/src/win/ui_render.cpp index c124bd44..19b81736 100644 --- a/src/win/ui_render.cpp +++ b/src/win/ui_render.cpp @@ -4,14 +4,14 @@ //mov eax,[array+eax*4] -> lea ebx,[parray] ; mov ebx,[ebx+eax*4] uint32 color_lookup_table[65536]; -render::render() { +Render::Render() { lpdd = 0; lpdds = 0; lpddsb = 0; lpddc = 0; } -void render::update_color_lookup_table() { +void Render::update_color_lookup_table() { int i, r, g, b; lpdds->GetSurfaceDesc(&ddsd); color_depth = ddsd.ddpfPixelFormat.dwRGBBitCount; @@ -45,9 +45,9 @@ int i, r, g, b; } } -void render::set_window(HWND hwnd_handle) { hwnd = hwnd_handle; } +void Render::set_window(HWND hwnd_handle) { hwnd = hwnd_handle; } -void render::to_windowed() { +void Render::to_windowed() { destroy(); DirectDrawCreate(0, &lpdd, 0); lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL); @@ -65,7 +65,12 @@ void render::to_windowed() { memset(&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if(cfg.video.use_vram) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + } else { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } ddsd.dwWidth = 512; ddsd.dwHeight = 478; lpdd->CreateSurface(&ddsd, &lpddsb, 0); @@ -74,7 +79,7 @@ void render::to_windowed() { update(); } -void render::to_fullscreen() { +void Render::to_fullscreen() { destroy(); DirectDrawCreate(0, &lpdd, 0); lpdd->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); @@ -93,7 +98,12 @@ void render::to_fullscreen() { memset(&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if(cfg.video.use_vram) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + } else { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } ddsd.dwWidth = 512; ddsd.dwHeight = 478; lpdd->CreateSurface(&ddsd, &lpddsb, 0); @@ -102,7 +112,16 @@ void render::to_fullscreen() { update(); } -void render::redraw() { +void Render::set_source_window(RECT *rs) { + switch(ppu->output->frame_mode) { + case 0:SetRect(rs, 0, 0, 256, 223);break; + case 1:SetRect(rs, 0, 0, 256, 446);break; + case 2:SetRect(rs, 0, 0, 512, 223);break; + case 3:SetRect(rs, 0, 0, 512, 446);break; + } +} + +void Render::redraw() { RECT rd, rs; POINT p; HRESULT hr; @@ -110,87 +129,177 @@ HRESULT hr; ClientToScreen(hwnd, &p); GetClientRect(hwnd, &rd); OffsetRect(&rd, p.x, p.y); - if(clock->overscan() == false) { - SetRect(&rs, 0, 2, 512, 448); - } else { - SetRect(&rs, 0, 2 + 15, 512, 448 + 15); - } + set_source_window(&rs); hr = lpdds->Blt(&rd, lpddsb, &rs, DDBLT_WAIT, 0); if(hr == DDERR_SURFACELOST) { lpdds->Restore(); lpddsb->Restore(); } + +uint32 fps; +char s[256], t[256]; + fps_timer->tick(); + if(fps_timer->second_passed() == true) { + sprintf(s, "bsnes v" BSNES_VERSION " ~byuu"); + if(rom_image->loaded() == true) { + fps = fps_timer->get_ticks(); + if(w_main->frameskip == 0) { + sprintf(t, " : %d fps", fps); + } else { + sprintf(t, " : %d fps [fs: %d]", fps * (1 + w_main->frameskip), w_main->frameskip); + } + strcat(s, t); + } + SetWindowText(w_main->hwnd, s); + fps_timer->reset(); + } } -void render::update16() { +void Render::update16() { HRESULT hr; hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); if(hr != DD_OK)return; -uint16 *_src_data = (uint16*)ppu->output; -uint16 *_dest_data = (uint16*)ddsd.lpSurface; -uint32 _pitch = ddsd.lPitch; - __asm { - mov edi,_dest_data - mov edx,_pitch - add edi,edx - add edi,edx - sub edx,1024 - mov esi,_src_data - add esi,2048 - mov ebx,478-2 - xor eax,eax - loop_y: - mov ecx,512 - loop_x: - lodsw - mov eax,dword ptr[color_lookup_table+eax*4] - stosw - dec ecx - jnz loop_x - add edi,edx - dec ebx - jnz loop_y +uint16 *src = (uint16*)ppu->output->buffer; +uint16 *dest = (uint16*)ddsd.lpSurface; +uint32 pitch; +int x, y; +/* skip first scanline */ + src += 1024; + + if(clock->overscan() == true) { + if(ppu->output->frame_mode & PPUOutput::INTERLACE) { + src += 1024 * 16; + } else { + src += 1024 * 8; + } } + if(ppu->output->frame_mode == PPUOutput::NORMAL) { + /* 256x223 */ + pitch = (ddsd.lPitch >> 1) - 256; + y = 223; + while(y--) { + x = 256; + while(x--) { + *dest++ = color_lookup_table[*src]; + src += 2; + } + dest += pitch; + src += 512; + } + } else if(ppu->output->frame_mode == PPUOutput::INTERLACE) { + /* 256x446 */ + pitch = (ddsd.lPitch >> 1) - 256; + y = 446; + while(y--) { + x = 256; + while(x--) { + *dest++ = color_lookup_table[*src]; + src += 2; + } + dest += pitch; + } + } else if(ppu->output->frame_mode == PPUOutput::DOUBLEWIDTH) { + /* 512x223 */ + pitch = (ddsd.lPitch >> 1) - 512; + y = 223; + while(y--) { + x = 512; + while(x--) { + *dest++ = color_lookup_table[*src++]; + } + dest += pitch; + src += 512; + } + } else { + /* 512x446 */ + pitch = (ddsd.lPitch >> 1) - 512; + y = 446; + while(y--) { + x = 512; + while(x--) { + *dest++ = color_lookup_table[*src++]; + } + dest += pitch; + } + } lpddsb->Unlock(0); } -void render::update32() { +void Render::update32() { HRESULT hr; hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0); if(hr != DD_OK)return; -uint16 *_src_data = (uint16*)ppu->output; -uint32 *_dest_data = (uint32*)ddsd.lpSurface; -uint32 _pitch = ddsd.lPitch; - __asm { - mov edi,_dest_data - mov edx,_pitch - add edi,edx - add edi,edx - sub edx,2048 - mov esi,_src_data - add esi,2048 - mov ebx,478-2 - loop_y: - mov ecx,512 - loop_x: - lodsw - and eax,0xffff - mov eax,dword ptr[color_lookup_table+eax*4] - stosd - dec ecx - jnz loop_x - add edi,edx - dec ebx - jnz loop_y +uint16 *src = (uint16*)ppu->output->buffer; +uint32 *dest = (uint32*)ddsd.lpSurface; +uint32 pitch; +int x, y; +/* skip first scanline */ + src += 1024; + + if(clock->overscan() == true) { + if(ppu->output->frame_mode & PPUOutput::INTERLACE) { + src += 1024 * 16; + } else { + src += 1024 * 8; + } } + if(ppu->output->frame_mode == PPUOutput::NORMAL) { + /* 256x223 */ + pitch = (ddsd.lPitch >> 2) - 256; + y = 223; + while(y--) { + x = 256; + while(x--) { + *dest++ = color_lookup_table[*src]; + src += 2; + } + dest += pitch; + src += 512; + } + } else if(ppu->output->frame_mode == PPUOutput::INTERLACE) { + /* 256x446 */ + pitch = (ddsd.lPitch >> 2) - 256; + y = 446; + while(y--) { + x = 256; + while(x--) { + *dest++ = color_lookup_table[*src]; + src += 2; + } + dest += pitch; + } + } else if(ppu->output->frame_mode == PPUOutput::DOUBLEWIDTH) { + /* 512x223 */ + pitch = (ddsd.lPitch >> 2) - 512; + y = 223; + while(y--) { + x = 512; + while(x--) { + *dest++ = color_lookup_table[*src++]; + } + dest += pitch; + src += 512; + } + } else { + /* 512x446 */ + pitch = (ddsd.lPitch >> 2) - 512; + y = 446; + while(y--) { + x = 512; + while(x--) { + *dest++ = color_lookup_table[*src++]; + } + dest += pitch; + } + } lpddsb->Unlock(0); } -void render::update() { +void Render::update() { switch(color_depth) { case 15: case 16: @@ -203,7 +312,7 @@ void render::update() { redraw(); } -void render::destroy() { +void Render::destroy() { if(lpddc) { lpddc->Release(); lpddc = 0; diff --git a/src/win/winmain.cpp b/src/win/winmain.cpp index 361eca32..0b81b322 100644 --- a/src/win/winmain.cpp +++ b/src/win/winmain.cpp @@ -1,11 +1,16 @@ #define INTERFACE_MAIN -#define BSNES_VERSION "0.006" +#define BSNES_VERSION "0.007" #include "winmain.h" #include "../base.h" +#include "config.cpp" + #include "bsnes.h" #include "ui.h" +#include "timer.cpp" +fpstimer *fps_timer; + #include "lib.cpp" #include "rom.cpp" @@ -31,7 +36,13 @@ void term_snes() { int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; +string cfg_fn; + _getcwd(cfg_fn, 4096); + cfg_fn += "\\bsnes.cfg"; + cfg.load(cfg_fn); meminit(); + fps_timer = new fpstimer(); + fps_timer->start(); rom_image = new ROMImage(); init_ui0(); @@ -56,6 +67,8 @@ MSG msg; bsnes->run(); } + cfg.save(cfg_fn); + delete(rom_image); term_snes(); memterm(); return 0; diff --git a/src/win/winmain.h b/src/win/winmain.h index 93a4753a..f990b93c 100644 --- a/src/win/winmain.h +++ b/src/win/winmain.h @@ -1,3 +1,8 @@ //can't use common dialogs with this defined... //#define WIN32_LEAN_AND_MEAN #include +#include +#include "../lib/libbase.h" +#include "../lib/libvector.h" +#include "../lib/libstring.h" +#include "../lib/libconfig.h"