mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-08 17:03:47 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1980fab09 | ||
|
|
ebb234ba5f | ||
|
|
2cc7fe30b4 | ||
|
|
5c3c872b78 | ||
|
|
36bf915244 | ||
|
|
045a0f7e79 | ||
|
|
a209e6ffbe | ||
|
|
3bf672dd97 | ||
|
|
157ddf3e8f | ||
|
|
ea23bf53ae | ||
|
|
d4598e1d01 | ||
|
|
f9a8564af0 | ||
|
|
6d66b1136d | ||
|
|
b01f18c34c | ||
|
|
1ebdb69516 | ||
|
|
add0f74387 | ||
|
|
b20f70f333 | ||
|
|
9aebf7bc6b | ||
|
|
a7bf219d5d | ||
|
|
04118be59a | ||
|
|
f24d17859f |
No files matched your search
+63
@@ -0,0 +1,63 @@
|
||||
bsnes (TM) Open Source Reference License
|
||||
Copyright (C) 2004 - 2007 byuu
|
||||
All rights reserved
|
||||
|
||||
1. Definitions
|
||||
|
||||
The terms "reproduce", "reproduction", "distribute" and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.
|
||||
|
||||
"The software" means this software package as a whole, including, but not
|
||||
limited to, this license, binaries, source code, documentation, and data.
|
||||
|
||||
"You" means the licensee of the software.
|
||||
|
||||
"The licensor" means the copyright holder of the software, byuu.
|
||||
|
||||
2. Grant of Rights
|
||||
|
||||
Subject to the terms of this license, the licensor grants you a
|
||||
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
|
||||
reproduce the software for non-commercial use only, provided the software
|
||||
remains unmodified, and there is no charge for the software itself, its' use,
|
||||
nor for the medium upon which the software is distributed. The reproduction of
|
||||
modified or derivative works of the software is strictly prohibited, except when
|
||||
transmitted solely to the licensor.
|
||||
|
||||
3. Limitations
|
||||
|
||||
This license does not grant you any rights to use the licensor's name, logo or
|
||||
trademarks.
|
||||
|
||||
The software is provided "as is", and any express or implied warranties,
|
||||
including, but not limited to, the implied warranties of merchantability and
|
||||
fitness for a particular purpose are disclaimed. In no event shall the licensor
|
||||
be liable for any direct, indirect, incidental, special, exemplary, or
|
||||
consequential damages (including, but not limited to, procurement of substitute
|
||||
goods or services; loss of use, data, or profits; or business interruption)
|
||||
however caused and on any theory of liability, whether in contract, strict
|
||||
liability, or tort (including negligence or otherwise) arising in any way out of
|
||||
the use of the software, even if advised of the possibility of such damage.
|
||||
|
||||
In the event that this license is determined to be invalid or unenforceable, the
|
||||
Grant of Rights will become null and void, and no rights shall be granted to the
|
||||
licensee, within the scope of U.S. copyright law.
|
||||
|
||||
4. Exemptions
|
||||
|
||||
The software includes the work of other copyright holders, which is licensed
|
||||
under different agreements, and exempt from this license. Below is a complete
|
||||
list of all such software, and their respective copyright holders and licenses.
|
||||
Further, respective source code files are labeled with their correct licensing
|
||||
information in the header. The lack of such a header indicates said file falls
|
||||
under the bsnes license.
|
||||
|
||||
HQ2x Filter, author: MaxST, license: LGPL
|
||||
JMA, author: NSRT Team, license: GPL *
|
||||
libco, author: byuu, license: public domain
|
||||
libui, author: byuu, license: public domain
|
||||
NTSC Filter, author: blargg, license: LGPL
|
||||
S-DD1, author: Andreas Naive, license: public domain
|
||||
zlib, license: zlib license
|
||||
|
||||
* bsnes has received an exemption from the copyright holder to use this work.
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
bsnes
|
||||
Version 0.021
|
||||
Author: byuu
|
||||
|
||||
|
||||
General:
|
||||
--------
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
||||
October 14th, 2004.
|
||||
|
||||
The latest version can be downloaded from:
|
||||
http://byuu.org/
|
||||
|
||||
Please see license.txt for important licensing information.
|
||||
|
||||
|
||||
Known Limitations:
|
||||
------------------
|
||||
S-CPU
|
||||
- Invalid DMA / HDMA transfers (eg WRAM<>WRAM) not fully emulated
|
||||
- Multiply / Divide register delays not implemented
|
||||
|
||||
S-PPU
|
||||
- Uses scanline-based renderer. This is very inaccurate, but very few games
|
||||
rely on mid-scanline writes to function correctly
|
||||
- Does not support FirstSprite+Y priority
|
||||
- OAM / CGRAM accesses during active display not supported correctly
|
||||
- RTO flags are not calculated on frames that are skipped when frameskipping
|
||||
is enabled. This provides a major speedup, however it will cause in issues
|
||||
in games that test these flags, eg the SNES Test Program Electronics Test.
|
||||
Turning frameskipping off will allow RTO flag calculation on every frame
|
||||
|
||||
Hardware Bugs
|
||||
- CPUr1 HDMA crashing bug not emulated
|
||||
- CPU<>APU communication bus conflicts not emulated
|
||||
|
||||
|
||||
Unsupported Hardware:
|
||||
---------------------
|
||||
SA-1
|
||||
Coprocessor used in many popular games, including:
|
||||
- Dragon Ball Z Hyper Dimension
|
||||
- Kirby Super Star
|
||||
- Kirby's Dreamland 3
|
||||
- Marvelous
|
||||
- SD Gundam G-NEXT
|
||||
- Super Mario RPG
|
||||
|
||||
Super FX
|
||||
Coprocessor used in many popular games, including:
|
||||
- Doom
|
||||
- Star Fox
|
||||
- Star Fox 2 (unreleased beta)
|
||||
- Super Mario World 2: Yoshi's Island
|
||||
|
||||
SPC7110
|
||||
Coprocessor used only by the following games:
|
||||
- Far East of Eden Zero
|
||||
- Far East of Eden Zero: Shounen Jump no Shou
|
||||
- Momotarou Densetsu Happy
|
||||
- Super Power League 4
|
||||
|
||||
DSP-3
|
||||
Coprocessor used only by SD Gundam GX
|
||||
|
||||
DSP-4
|
||||
Coprocessor used only by Top Gear 3000
|
||||
|
||||
ST010 / ST011 / ST018
|
||||
SETA coprocessors used by very few games
|
||||
|
||||
BS-X (Broadcast Satellite)
|
||||
Add-on unit sold only in Japan that played specially-made games that were
|
||||
downloaded via satellite
|
||||
|
||||
BS-X Flashcart
|
||||
Flash cartridge used by BS-X, as well as some standalone games by Asciisoft
|
||||
|
||||
Super Gameboy
|
||||
Cartridge passthrough used for playing Gameboy games
|
||||
|
||||
|
||||
Unsupported Controllers:
|
||||
------------------------
|
||||
Mouse
|
||||
Super Scope
|
||||
Justifier
|
||||
Multitap (4-port and 5-port)
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
######################
|
||||
### bsnes makefile ###
|
||||
######################
|
||||
|
||||
ifeq ($(PLATFORM),)
|
||||
_null_: help
|
||||
endif
|
||||
|
||||
##################################
|
||||
### platform-specific settings ###
|
||||
##################################
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-lui)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
AS = nasm
|
||||
ASFLAGS = -f elf
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_gtk
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-lui-x64)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf64
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco_x86_64
|
||||
LIBUI = libui_gtk
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-lui)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-lui-pgi)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-lui-pgo)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
#####################################
|
||||
### compiler / assembler switches ###
|
||||
#####################################
|
||||
|
||||
ifeq ($(CC),gcc)
|
||||
OUT = -obsnes
|
||||
CPP = g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),cl)
|
||||
OUT = /Febsnes
|
||||
CPP = cl
|
||||
OBJ = obj
|
||||
CARGS = /c $< /Fo$@
|
||||
DEFINE = /D
|
||||
endif
|
||||
|
||||
ifeq ($(AS),nasm)
|
||||
ASARGS = $< -o $@
|
||||
endif
|
||||
|
||||
ifeq ($(AS),yasm)
|
||||
ASARGS = $< -o $@
|
||||
endif
|
||||
|
||||
###################
|
||||
### OS switches ###
|
||||
###################
|
||||
|
||||
ifeq ($(OS),unix)
|
||||
RM = rm -f
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
OUT := $(OUT).exe
|
||||
RM = del
|
||||
LIBS += kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
endif
|
||||
|
||||
####################################
|
||||
### main target and dependencies ###
|
||||
####################################
|
||||
|
||||
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \
|
||||
libstring.$(OBJ) \
|
||||
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) bmemory.$(OBJ) \
|
||||
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
|
||||
bppu.$(OBJ) snes.$(OBJ) srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) \
|
||||
dsp2.$(OBJ) obc1.$(OBJ)
|
||||
|
||||
ifeq ($(GZIP_SUPPORT),true)
|
||||
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
|
||||
gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \
|
||||
trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ)
|
||||
CFLAGS += $(DEFINE)GZIP_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(JMA_SUPPORT),true)
|
||||
OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \
|
||||
iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
|
||||
CFLAGS += $(DEFINE)JMA_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
ifeq ($(CC),cl)
|
||||
OBJECTS += bsnes.res
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(OBJECTS)
|
||||
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
|
||||
# mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
######################
|
||||
|
||||
%.$(OBJ): $<
|
||||
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
||||
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
|
||||
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
|
||||
|
||||
#########################
|
||||
### platform-specific ###
|
||||
#########################
|
||||
main.$(OBJ): ui/main.cpp config/* ui/* ui/video/* ui/audio/* ui/input/* \
|
||||
ui/lui/* ui/lui/settings/* \
|
||||
ui/win/* ui/win/settings/* ui/win/debugger/*
|
||||
bsnes.res : ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
|
||||
|
||||
#############
|
||||
### libco ###
|
||||
#############
|
||||
libco_x86.$(OBJ) : lib/libco_x86.asm lib/*
|
||||
libco_x86_64.$(OBJ): lib/libco_x86_64.asm lib/*
|
||||
|
||||
#############
|
||||
### libui ###
|
||||
#############
|
||||
libui_gtk.$(OBJ): lib/libui_gtk.cpp lib/*
|
||||
libui_win.$(OBJ): lib/libui_win.cpp lib/*
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
libstring.$(OBJ): lib/libstring.cpp lib/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
#################
|
||||
reader.$(OBJ): reader/reader.cpp reader/*
|
||||
cart.$(OBJ) : cart/cart.cpp cart/*
|
||||
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
memory.$(OBJ) : memory/memory.cpp memory/*
|
||||
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
|
||||
|
||||
###########
|
||||
### cpu ###
|
||||
###########
|
||||
cpu.$(OBJ) : cpu/cpu.cpp cpu/*
|
||||
scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
||||
|
||||
###########
|
||||
### smp ###
|
||||
###########
|
||||
smp.$(OBJ) : smp/smp.cpp smp/*
|
||||
ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
||||
|
||||
###########
|
||||
### dsp ###
|
||||
###########
|
||||
adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
|
||||
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
srtc.$(OBJ): chip/srtc/srtc.cpp chip/srtc/*
|
||||
sdd1.$(OBJ): chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
c4.$(OBJ) : chip/c4/c4.cpp chip/c4/*
|
||||
dsp1.$(OBJ): chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
dsp2.$(OBJ): chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obc1.$(OBJ): chip/obc1/obc1.cpp chip/obc1/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/*
|
||||
compress.$(OBJ): reader/zlib/compress.c reader/zlib/*
|
||||
crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/*
|
||||
deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/*
|
||||
gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/*
|
||||
inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/*
|
||||
inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/*
|
||||
inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/*
|
||||
ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/*
|
||||
trees.$(OBJ) : reader/zlib/trees.c reader/zlib/*
|
||||
unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/*
|
||||
zip.$(OBJ) : reader/zlib/zip.c reader/zlib/*
|
||||
zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/*
|
||||
|
||||
###########
|
||||
### jma ###
|
||||
###########
|
||||
jma.$(OBJ) : reader/jma/jma.cpp reader/jma/*
|
||||
jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/*
|
||||
lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/*
|
||||
7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/*
|
||||
iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/*
|
||||
inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/*
|
||||
lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/*
|
||||
winout.$(OBJ) : reader/jma/winout.cpp reader/jma/*
|
||||
|
||||
####################
|
||||
### misc targets ###
|
||||
####################
|
||||
clean:
|
||||
-@$(RM) *.$(OBJ)
|
||||
-@$(RM) *.res
|
||||
-@$(RM) *.pgd
|
||||
-@$(RM) *.pgc
|
||||
-@$(RM) *.ilk
|
||||
-@$(RM) *.pdb
|
||||
-@$(RM) *.manifest
|
||||
|
||||
help:
|
||||
@echo Please specify which platform to compile for with PLATFORM=platform_name
|
||||
+9
-22
@@ -1,4 +1,4 @@
|
||||
#define BSNES_VERSION "0.018"
|
||||
#define BSNES_VERSION "0.021"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define MEMCORE bMemBus
|
||||
@@ -13,47 +13,34 @@
|
||||
//game genie + pro action replay code support (~1-3% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
//enable GZ, ZIP format support
|
||||
#define GZIP_SUPPORT
|
||||
|
||||
//enable JMA support
|
||||
#define JMA_SUPPORT
|
||||
|
||||
//snes core polymorphism
|
||||
//(allow runtime cpu/smp/dsp/ppu/bus selection, ~10% speed hit)
|
||||
//#define POLYMORPHISM
|
||||
|
||||
#include "lib/libbase.h"
|
||||
|
||||
#if defined(PROCESSOR_X86)
|
||||
#define ARCH_LSB
|
||||
#include "lib/libco_x86.h"
|
||||
#elif defined(PROCESSOR_X86_64)
|
||||
#define ARCH_LSB
|
||||
#include "lib/libco_x86_64.h"
|
||||
#elif defined(PROCESSOR_G5)
|
||||
#define ARCH_MSB
|
||||
#else
|
||||
#error "unsupported processor"
|
||||
#endif
|
||||
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libco_x86.h"
|
||||
#include "lib/libsort.h"
|
||||
#include "lib/libarray.h"
|
||||
#include "lib/libvector.h"
|
||||
#include "lib/libfile.h"
|
||||
#include "lib/libups.h"
|
||||
#include "lib/libstring.h"
|
||||
#include "lib/libconfig.h"
|
||||
|
||||
inline uint16 read16(uint8 *addr, uint pos) {
|
||||
#ifdef ARCH_LSB
|
||||
return *((uint16*)(addr + pos));
|
||||
#else
|
||||
return (addr[pos]) | (addr[pos + 1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(char *, ...);
|
||||
void dprintf(char *, ...);
|
||||
void dprintf(uint, char *, ...);
|
||||
void alert(char*, ...);
|
||||
void dprintf(char*, ...);
|
||||
void dprintf(uint, char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
|
||||
Binary file not shown.
+91
-353
@@ -1,9 +1,20 @@
|
||||
#include "../base.h"
|
||||
#include "database.cpp"
|
||||
|
||||
#include "cart_normal.cpp"
|
||||
#include "cart_st.cpp"
|
||||
#include "cart_stdual.cpp"
|
||||
|
||||
#include "cart_file.cpp"
|
||||
#include "cart_header.cpp"
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
void Cartridge::read_dbi() {
|
||||
void Cartridge::load_begin(uint cart_type) {
|
||||
if(loaded() == true)return;
|
||||
|
||||
info.type = cart_type;
|
||||
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
@@ -13,372 +24,89 @@ void Cartridge::read_dbi() {
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
info.header_index = 0x7fc0;
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = PCB;
|
||||
strcpy(info.name, dbi.name);
|
||||
strcpy(info.pcb, dbi.pcb);
|
||||
strcpy(info.name, "");
|
||||
strcpy(info.pcb, "");
|
||||
info.region = NTSC;
|
||||
info.cart_mmio = false;
|
||||
|
||||
info.rom_size = dbi.rom;
|
||||
info.ram_size = dbi.ram;
|
||||
}
|
||||
info.rom_size = 0;
|
||||
info.ram_size = 0;
|
||||
|
||||
void Cartridge::read_header() {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0) {
|
||||
info.mapper = LOROM;
|
||||
strcpy(info.pcb, "UNL-LOROM");
|
||||
} else if(info.header_index == 0xffc0) {
|
||||
info.mapper = HIROM;
|
||||
strcpy(info.pcb, "UNL-HIROM");
|
||||
} else { //info.header_index == 0x40ffc0
|
||||
info.mapper = EXHIROM;
|
||||
strcpy(info.pcb, "UNL-EXHIROM");
|
||||
}
|
||||
|
||||
uint8 mapper = rom[info.header_index + MAPPER];
|
||||
uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
info.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.c4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
|
||||
info.dsp1_mapper = DSP1_LOROM_1MB;
|
||||
} else if((mapper & 0x2f) == 0x20) {
|
||||
info.dsp1_mapper = DSP1_LOROM_2MB;
|
||||
} else if((mapper & 0x2f) == 0x21) {
|
||||
info.dsp1_mapper = DSP1_HIROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
info.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
|
||||
|
||||
if(rom[info.header_index + SRAM_SIZE] & 7) {
|
||||
info.ram_size = 1024 << (rom[info.header_index + SRAM_SIZE] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
||||
info.name[21] = 0;
|
||||
|
||||
for(int i = 0; i < 22; i++) {
|
||||
if(info.name[i] & 0x80) {
|
||||
info.name[i] = '?';
|
||||
}
|
||||
file.count = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
strcpy(file.rom_name[i], "");
|
||||
strcpy(file.ram_name[i], "");
|
||||
file.rom_size[i] = 0;
|
||||
file.ram_size[i] = 0;
|
||||
file.rom_data[i] = 0;
|
||||
file.ram_data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0,
|
||||
score_hi = 0,
|
||||
score_ex = 0;
|
||||
void Cartridge::load(const char *rom_fn) {
|
||||
if(!rom_fn || !*rom_fn)return;
|
||||
|
||||
if(info.rom_size < 0x010000) {
|
||||
//cart too small to be anything but lorom
|
||||
info.header_index = 0x007fc0;
|
||||
return;
|
||||
}
|
||||
|
||||
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
|
||||
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
|
||||
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + SRAM_SIZE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + SRAM_SIZE] < 0x08)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + REGION] < 14)score_lo++;
|
||||
if(rom[0xffc0 + REGION] < 14)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
|
||||
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
|
||||
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
|
||||
|
||||
uint16 cksum, icksum;
|
||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_lo += 8;
|
||||
}
|
||||
|
||||
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(info.rom_size < 0x401000) {
|
||||
score_ex = 0;
|
||||
} else {
|
||||
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
|
||||
else score_ex += 16;
|
||||
}
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
info.header_index = 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
info.header_index = 0x00ffc0;
|
||||
} else {
|
||||
info.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_sram() {
|
||||
if(info.ram_size == 0) {
|
||||
sram = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
FileReader ff(sram_fn);
|
||||
if(!ff.ready()) {
|
||||
sram = (uint8*)malloc(info.ram_size);
|
||||
memset(sram, 0xff, info.ram_size);
|
||||
return;
|
||||
}
|
||||
|
||||
sram = ff.read(info.ram_size);
|
||||
}
|
||||
|
||||
void Cartridge::save_sram() {
|
||||
if(info.ram_size == 0)return;
|
||||
|
||||
FileWriter ff(sram_fn);
|
||||
if(!ff.ready())return;
|
||||
|
||||
ff.write(sram, info.ram_size);
|
||||
}
|
||||
|
||||
void Cartridge::load_rom(Reader &rf) {
|
||||
uint size = rf.size();
|
||||
bool header = ((size & 0x7fff) == 512);
|
||||
info.rom_size = size - (header ? 512 : 0);
|
||||
if(info.rom_size & 0x7fff) {
|
||||
info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
|
||||
}
|
||||
|
||||
uint8 *base_rom = rf.read(info.rom_size + (header ? 512 : 0));
|
||||
if(header) {
|
||||
memcpy(rom_header, base_rom, 512);
|
||||
} else {
|
||||
memset(rom_header, 0x00, 512);
|
||||
}
|
||||
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memcpy(rom, base_rom + (header ? 512 : 0), info.rom_size);
|
||||
SafeFree(base_rom);
|
||||
|
||||
info.crc32 = 0xffffffff;
|
||||
for(int32 i = 0; i < info.rom_size; i++) {
|
||||
info.crc32 = crc32_adjust(info.crc32, rom[i]);
|
||||
}
|
||||
info.crc32 = ~info.crc32;
|
||||
}
|
||||
|
||||
void Cartridge::patch_rom(Reader &rf) {
|
||||
UPS<ramfile, ramfile, ramfile> ups;
|
||||
uint patchsize = rf.size();
|
||||
uint8 *patchdata = rf.read();
|
||||
|
||||
fopen(ups.original, 0, file::mode_writeread);
|
||||
fopen(ups.modified, 0, file::mode_writeread);
|
||||
fopen(ups.patch.fp, 0, file::mode_writeread);
|
||||
|
||||
fwrite(ups.original, rom, info.rom_size);
|
||||
fwrite(ups.patch.fp, patchdata, patchsize);
|
||||
|
||||
if(ups.apply() == true) {
|
||||
info.crc32 = ups.modified_crc32;
|
||||
info.rom_size = ups.modified_filesize;
|
||||
rom = (uint8*)realloc(rom, info.rom_size);
|
||||
fseek(ups.modified, 0, file::seek_start);
|
||||
fread(ups.modified, rom, info.rom_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool Cartridge::load(const char *fn) {
|
||||
if(cart_loaded == true)return false;
|
||||
if(strlen(fn) < 3)return false;
|
||||
|
||||
dprintf("* Loading \"%s\"...", fn);
|
||||
|
||||
strcpy(rom_fn, fn);
|
||||
|
||||
switch(Reader::detect(rom_fn)) {
|
||||
|
||||
case Reader::RF_NORMAL: {
|
||||
FileReader ff(rom_fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
load_rom(ff);
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(rom_fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
load_rom(gf);
|
||||
} break;
|
||||
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(rom_fn);
|
||||
load_rom(zf);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(rom_fn);
|
||||
load_rom(jf);
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//remove ROM extension
|
||||
strcpy(sram_fn, fn);
|
||||
char fn[4096], ram_fn[4096];
|
||||
strcpy(fn, rom_fn);
|
||||
//correct folder slashes
|
||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
||||
if(sram_fn[i] == '.') {
|
||||
sram_fn[i] = 0;
|
||||
if(fn[i] == '\\')fn[i] = '/';
|
||||
}
|
||||
|
||||
uint i = file.count++;
|
||||
strcpy(file.rom_name[i], fn);
|
||||
|
||||
strcpy(fn, rom_fn);
|
||||
//remove ROM extension
|
||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
||||
if(fn[i] == '.') {
|
||||
fn[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//add SRAM extension
|
||||
strcat(sram_fn, ".");
|
||||
strcat(sram_fn, config::fs.save_ext.sget());
|
||||
if(i == 0) {
|
||||
strcpy(file.patch_name, fn);
|
||||
strcat(file.patch_name, ".ups");
|
||||
}
|
||||
strcpy(fn, strptr(config::file_updatepath(fn, config::path.save)));
|
||||
if(i == 0) {
|
||||
strcpy(file.cheat_name, fn);
|
||||
strcat(file.cheat_name, ".cht");
|
||||
}
|
||||
strcpy(file.ram_name[i], fn);
|
||||
strcat(file.ram_name[i], ".");
|
||||
strcat(file.ram_name[i], config::path.save_ext);
|
||||
}
|
||||
|
||||
stringarray save_path;
|
||||
strcpy(save_path, config::fs.save_path.sget());
|
||||
replace(save_path, "\\", "/");
|
||||
if(strlen(save_path) && !strend(save_path, "/")) { strcat(save_path, "/"); }
|
||||
|
||||
if(strlen(save_path) != 0) {
|
||||
//override default path (current directory)
|
||||
stringarray new_fn, parts;
|
||||
strcpy(new_fn, sram_fn);
|
||||
replace(new_fn, "\\", "/");
|
||||
split(parts, "/", new_fn);
|
||||
|
||||
//add new SRAM path
|
||||
strcpy(new_fn, save_path);
|
||||
|
||||
//append fs.base_path if fs.sram_path is not fully-qualified path
|
||||
if(strbegin(new_fn, "./") == true) {
|
||||
strltrim(new_fn, "./");
|
||||
strcpy(new_fn[1], new_fn[0]);
|
||||
strcpy(new_fn[0], config::fs.base_path.sget());
|
||||
strcat(new_fn[0], new_fn[1]);
|
||||
}
|
||||
|
||||
//finally, append SRAM file name
|
||||
strcat(new_fn, parts[count(parts) - 1]);
|
||||
strcpy(sram_fn, strptr(new_fn));
|
||||
bool Cartridge::load_end() {
|
||||
for(int i = 0; i < file.count; i++) {
|
||||
load_file(file.rom_name[i], file.rom_data[i], file.rom_size[i]);
|
||||
}
|
||||
|
||||
//load cheat file if it exists
|
||||
strcpy(cheat_fn, sram_fn);
|
||||
strrtrim(cheat_fn, config::fs.save_ext.sget());
|
||||
strrtrim(cheat_fn, ".");
|
||||
strcat(cheat_fn, ".cht");
|
||||
|
||||
if(fexists(cheat_fn) == true) {
|
||||
FileReader ff(cheat_fn);
|
||||
cheat.load(ff);
|
||||
if(fexists(file.cheat_name) == true) {
|
||||
cheat.clear();
|
||||
cheat.load(file.cheat_name);
|
||||
}
|
||||
|
||||
//load patch file if it exists
|
||||
strcpy(patch_fn, sram_fn);
|
||||
strrtrim(patch_fn, config::fs.save_ext.sget());
|
||||
strrtrim(patch_fn, ".");
|
||||
strcat(patch_fn, ".ups");
|
||||
|
||||
if(fexists(patch_fn) == true) {
|
||||
FileReader ff(patch_fn);
|
||||
patch_rom(ff);
|
||||
switch(info.type) {
|
||||
case CART_NORMAL: {
|
||||
load_rom_normal();
|
||||
load_ram_normal();
|
||||
} break;
|
||||
case CART_ST: {
|
||||
load_rom_st();
|
||||
load_ram_st();
|
||||
} break;
|
||||
case CART_STDUAL: {
|
||||
load_rom_stdual();
|
||||
load_ram_stdual();
|
||||
} break;
|
||||
}
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
else {
|
||||
strrtrim(patch_fn, ".ups");
|
||||
strcat(patch_fn, ".upz");
|
||||
if(fexists(patch_fn) == true) {
|
||||
ZipReader zf(patch_fn);
|
||||
patch_rom(zf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(read_database() == true) {
|
||||
read_dbi();
|
||||
} else {
|
||||
find_header();
|
||||
read_header();
|
||||
}
|
||||
|
||||
load_sram();
|
||||
cart_loaded = true;
|
||||
|
||||
r_mem->load_cart();
|
||||
return true;
|
||||
}
|
||||
@@ -388,13 +116,23 @@ bool Cartridge::unload() {
|
||||
|
||||
r_mem->unload_cart();
|
||||
|
||||
if(sram) { save_sram(); }
|
||||
SafeFree(rom);
|
||||
SafeFree(sram);
|
||||
switch(info.type) {
|
||||
case CART_NORMAL: {
|
||||
save_ram_normal();
|
||||
} break;
|
||||
case CART_ST: {
|
||||
save_ram_st();
|
||||
} break;
|
||||
case CART_STDUAL: {
|
||||
save_ram_stdual();
|
||||
} break;
|
||||
}
|
||||
|
||||
if(cheat.count() > 0 || fexists(cheat_fn)) {
|
||||
FileWriter ff(cheat_fn);
|
||||
cheat.save(ff);
|
||||
safe_free(rom);
|
||||
safe_free(ram);
|
||||
|
||||
if(cheat.count() > 0 || fexists(file.cheat_name) == true) {
|
||||
cheat.save(file.cheat_name);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
@@ -407,8 +145,8 @@ Cartridge::Cartridge() {
|
||||
|
||||
cart_loaded = false;
|
||||
|
||||
rom = 0;
|
||||
sram = 0;
|
||||
rom = 0;
|
||||
ram = 0;
|
||||
}
|
||||
|
||||
Cartridge::~Cartridge() {
|
||||
|
||||
+39
-10
@@ -15,10 +15,15 @@ db_item dbi;
|
||||
|
||||
//
|
||||
|
||||
bool cart_loaded;
|
||||
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096];
|
||||
enum {
|
||||
CART_NORMAL,
|
||||
CART_ST,
|
||||
CART_STDUAL,
|
||||
};
|
||||
|
||||
uint8 rom_header[512], *rom, *sram;
|
||||
bool cart_loaded;
|
||||
|
||||
uint8 rom_header[512], *rom, *ram;
|
||||
|
||||
enum {
|
||||
//header fields
|
||||
@@ -26,7 +31,7 @@ enum {
|
||||
MAPPER = 0x15,
|
||||
ROM_TYPE = 0x16,
|
||||
ROM_SIZE = 0x17,
|
||||
SRAM_SIZE = 0x18,
|
||||
RAM_SIZE = 0x18,
|
||||
REGION = 0x19,
|
||||
LICENSE = 0x1a,
|
||||
VERSION = 0x1b,
|
||||
@@ -53,6 +58,17 @@ enum {
|
||||
};
|
||||
|
||||
struct {
|
||||
uint count;
|
||||
char cheat_name[4096], patch_name[4096];
|
||||
char rom_name[8][4096], ram_name[8][4096];
|
||||
uint rom_size[8], ram_size[8];
|
||||
uint8 *rom_data[8], *ram_data[8];
|
||||
} file;
|
||||
|
||||
struct {
|
||||
uint type;
|
||||
|
||||
//cart information
|
||||
uint32 crc32;
|
||||
char name[128];
|
||||
char pcb[32];
|
||||
@@ -78,15 +94,28 @@ struct {
|
||||
uint header_index;
|
||||
} info;
|
||||
|
||||
void load_rom(Reader &rf);
|
||||
void patch_rom(Reader &rf);
|
||||
void load_sram();
|
||||
void save_sram();
|
||||
void read_dbi();
|
||||
bool load_file(const char *fn, uint8 *&data, uint &size);
|
||||
bool save_file(const char *fn, uint8 *data, uint size);
|
||||
|
||||
void load_rom_normal();
|
||||
void load_ram_normal();
|
||||
void save_ram_normal();
|
||||
|
||||
void load_rom_st();
|
||||
void load_ram_st();
|
||||
void save_ram_st();
|
||||
|
||||
void load_rom_stdual();
|
||||
void load_ram_stdual();
|
||||
void save_ram_stdual();
|
||||
|
||||
void find_header();
|
||||
void read_header();
|
||||
|
||||
bool loaded() { return cart_loaded; }
|
||||
bool load(const char *fn);
|
||||
void load_begin(uint cart_type);
|
||||
void load(const char *rom_fn);
|
||||
bool load_end();
|
||||
bool unload();
|
||||
|
||||
Cartridge();
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "../reader/filereader.h"
|
||||
|
||||
#if defined(GZIP_SUPPORT)
|
||||
#include "../reader/gzreader.h"
|
||||
#include "../reader/zipreader.h"
|
||||
#endif
|
||||
|
||||
#if defined(JMA_SUPPORT)
|
||||
#include "../reader/jmareader.h"
|
||||
#endif
|
||||
|
||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
dprintf("* Loading \"%s\"...", fn);
|
||||
|
||||
if(fexists(fn) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(Reader::detect(fn)) {
|
||||
|
||||
case Reader::RF_NORMAL: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(fn);
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||
FileWriter ff(fn);
|
||||
if(!ff.ready())return false;
|
||||
ff.write(data, size);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
void Cartridge::read_header() {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0) {
|
||||
info.mapper = LOROM;
|
||||
strcpy(info.pcb, "UNL-LOROM");
|
||||
} else if(info.header_index == 0xffc0) {
|
||||
info.mapper = HIROM;
|
||||
strcpy(info.pcb, "UNL-HIROM");
|
||||
} else { //info.header_index == 0x40ffc0
|
||||
info.mapper = EXHIROM;
|
||||
strcpy(info.pcb, "UNL-EXHIROM");
|
||||
}
|
||||
|
||||
uint8 mapper = rom[info.header_index + MAPPER];
|
||||
uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
info.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.c4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
|
||||
info.dsp1_mapper = DSP1_LOROM_1MB;
|
||||
} else if((mapper & 0x2f) == 0x20) {
|
||||
info.dsp1_mapper = DSP1_LOROM_2MB;
|
||||
} else if((mapper & 0x2f) == 0x21) {
|
||||
info.dsp1_mapper = DSP1_HIROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
info.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
|
||||
|
||||
if(rom[info.header_index + RAM_SIZE] & 7) {
|
||||
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
||||
info.name[21] = 0;
|
||||
|
||||
for(int i = 0; i < 22; i++) {
|
||||
if(info.name[i] & 0x80) {
|
||||
info.name[i] = '?';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0,
|
||||
score_hi = 0,
|
||||
score_ex = 0;
|
||||
|
||||
if(info.rom_size < 0x010000) {
|
||||
//cart too small to be anything but lorom
|
||||
info.header_index = 0x007fc0;
|
||||
return;
|
||||
}
|
||||
|
||||
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
|
||||
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
|
||||
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + RAM_SIZE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + RAM_SIZE] < 0x08)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + REGION] < 14)score_lo++;
|
||||
if(rom[0xffc0 + REGION] < 14)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
|
||||
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
|
||||
|
||||
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
|
||||
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
|
||||
|
||||
uint16 cksum, icksum;
|
||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_lo += 8;
|
||||
}
|
||||
|
||||
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
|
||||
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
|
||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(info.rom_size < 0x401000) {
|
||||
score_ex = 0;
|
||||
} else {
|
||||
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
|
||||
else score_ex += 16;
|
||||
}
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
info.header_index = 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
info.header_index = 0x00ffc0;
|
||||
} else {
|
||||
info.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
void Cartridge::load_rom_normal() {
|
||||
uint size = 0;
|
||||
for(int i = 0; i < file.count; i++) {
|
||||
size += file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
||||
}
|
||||
|
||||
info.rom_size = size;
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memset(rom, 0, info.rom_size);
|
||||
|
||||
uint offset = 0;
|
||||
for(int i = 0; i < file.count; i++) {
|
||||
uint8 *data = file.rom_data[i] + (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
||||
uint size = file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
||||
memcpy(rom + offset, data, size);
|
||||
offset += size;
|
||||
safe_free(file.rom_data[i]);
|
||||
}
|
||||
|
||||
info.crc32 = crc32_calculate(rom, info.rom_size);
|
||||
|
||||
if(read_database() == true) {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = PCB;
|
||||
strcpy(info.name, dbi.name);
|
||||
strcpy(info.pcb, dbi.pcb);
|
||||
info.region = NTSC;
|
||||
info.cart_mmio = false;
|
||||
|
||||
info.rom_size = dbi.rom;
|
||||
info.ram_size = dbi.ram;
|
||||
} else {
|
||||
find_header();
|
||||
read_header();
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_ram_normal() {
|
||||
if(info.ram_size == 0) {
|
||||
ram = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ram = (uint8*)malloc(info.ram_size);
|
||||
memset(ram, 0xff, info.ram_size);
|
||||
|
||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
||||
memcpy(ram, file.ram_data[0], min(info.ram_size, file.ram_size[0]));
|
||||
safe_free(file.ram_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::save_ram_normal() {
|
||||
if(info.ram_size == 0)return;
|
||||
|
||||
save_file(file.ram_name[0], ram, info.ram_size);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
void Cartridge::load_rom_st() {
|
||||
uint8 *data;
|
||||
uint size;
|
||||
string bios = config::file_updatepath("stbios.bin", config::path.bios);
|
||||
info.rom_size = 0x200000;
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memset(rom, 0, info.rom_size);
|
||||
|
||||
load_file(strptr(bios), data, size);
|
||||
memcpy(rom, data, min(size, 0x040000));
|
||||
safe_free(data);
|
||||
|
||||
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
|
||||
safe_free(file.rom_data[0]);
|
||||
|
||||
//
|
||||
strcpy(info.name, "???");
|
||||
strcpy(info.pcb, "STC-SOLO");
|
||||
|
||||
info.mapper = PCB;
|
||||
info.region = NTSC;
|
||||
|
||||
info.rom_size = 0x200000;
|
||||
info.ram_size = 0x020000;
|
||||
//
|
||||
|
||||
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
|
||||
if(read_database() == true) {
|
||||
strcpy(info.name, dbi.name);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_ram_st() {
|
||||
ram = (uint8*)malloc(info.ram_size);
|
||||
memset(ram, 0xff, info.ram_size);
|
||||
|
||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
||||
memcpy(ram, file.ram_data[0], min(file.ram_size[0], 0x020000));
|
||||
safe_free(file.ram_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::save_ram_st() {
|
||||
save_file(file.ram_name[0], ram, 0x020000);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
void Cartridge::load_rom_stdual() {
|
||||
uint8 *data;
|
||||
uint size;
|
||||
string bios = config::file_updatepath("stbios.bin", config::path.bios);
|
||||
info.rom_size = 0x300000;
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memset(rom, 0, info.rom_size);
|
||||
|
||||
load_file(strptr(bios), data, size);
|
||||
memcpy(rom, data, min(size, 0x040000));
|
||||
safe_free(data);
|
||||
|
||||
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
|
||||
safe_free(file.rom_data[0]);
|
||||
|
||||
memcpy(rom + 0x200000, file.rom_data[1], min(file.rom_size[1], 0x100000));
|
||||
safe_free(file.rom_data[1]);
|
||||
|
||||
char name_a[4096], name_b[4096];
|
||||
strcpy(name_a, "???");
|
||||
strcpy(name_b, "???");
|
||||
//
|
||||
info.mapper = PCB;
|
||||
info.region = NTSC;
|
||||
|
||||
info.rom_size = 0x300000;
|
||||
info.ram_size = 0x040000;
|
||||
//
|
||||
|
||||
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
|
||||
if(read_database() == true) {
|
||||
strcpy(name_a, dbi.name);
|
||||
}
|
||||
|
||||
info.crc32 = crc32_calculate(rom + 0x200000, file.rom_size[1]);
|
||||
if(read_database() == true) {
|
||||
strcpy(name_b, dbi.name);
|
||||
}
|
||||
|
||||
//
|
||||
info.crc32 = 0;
|
||||
strcpy(info.name, name_a);
|
||||
strcat(info.name, " + ");
|
||||
strcat(info.name, name_b);
|
||||
strcpy(info.pcb, "STC-DUAL");
|
||||
}
|
||||
|
||||
void Cartridge::load_ram_stdual() {
|
||||
ram = (uint8*)malloc(info.ram_size);
|
||||
memset(ram, 0xff, info.ram_size);
|
||||
|
||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
||||
memcpy(ram + 0x000000, file.ram_data[0], min(file.ram_size[0], 0x020000));
|
||||
safe_free(file.ram_data[0]);
|
||||
}
|
||||
|
||||
if(load_file(file.ram_name[1], file.ram_data[1], file.ram_size[1]) == true) {
|
||||
memcpy(ram + 0x020000, file.ram_data[1], min(file.ram_size[1], 0x020000));
|
||||
safe_free(file.ram_data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::save_ram_stdual() {
|
||||
save_file(file.ram_name[0], ram + 0x000000, 0x020000);
|
||||
save_file(file.ram_name[1], ram + 0x020000, 0x020000);
|
||||
}
|
||||
Binary file not shown.
+77
-11
@@ -1,32 +1,98 @@
|
||||
[0xbb5c4238]
|
||||
name = "Bishoujo Senshi Sailor Moon Sailor Stars - Fuwa Fuwa Panic 2 (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 8mbit
|
||||
ram = 32kbit
|
||||
|
||||
[0x8eb753f3]
|
||||
name = "Crayon Shin-chan - Nagagutsu Dobon!! (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x7aedd703]
|
||||
name = "Der Langrisser (Japan) [!]"
|
||||
pcb = "SHVC-1A3M-30"
|
||||
rom = 16mbit
|
||||
ram = 64kbit
|
||||
|
||||
[0x35f9eecc]
|
||||
name = "Der Langrisser (Japan) (V1.1)"
|
||||
pcb = "SHVC-1A3M-30" ;unverified (guess)
|
||||
rom = 16mbit
|
||||
ram = 64kbit
|
||||
|
||||
[0x19bdcb19]
|
||||
name = "Derby Stallion '96 (Japan) [!]"
|
||||
pcb = "BSC-1A5M-01"
|
||||
rom = 24mbit
|
||||
ram = 256kbit
|
||||
|
||||
[0x4296500d]
|
||||
name = "Gegege no Kitarou - Youkai Donjara (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 16kbit
|
||||
|
||||
[0x14c66fca]
|
||||
name = "Gekisou Sentai Car Rangers (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x32b2b3dd]
|
||||
name = "Poi Poi Ninja World (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x9684526d]
|
||||
name = "Romancing SaGa (Japan) (V1.1) [!]"
|
||||
pcb = "SHVC-1A3B-12"
|
||||
rom = 8mbit
|
||||
ram = 64kbit
|
||||
|
||||
[0x675b6382]
|
||||
name = "RPG Tsukuru 2 (Japan)"
|
||||
pcb = "BSC-1A7M-01" ;unverified
|
||||
rom = 16mbit
|
||||
ram = 512kbit
|
||||
[0xafd74dcb]
|
||||
name = "SD Gundam Generation A - Ichinen Sensouki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x48ecae44]
|
||||
name = "SD Gundam Generation B - Grips Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x72b4235f]
|
||||
name = "SD Gundam Generation C - Axis Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x792d884c]
|
||||
name = "SD Gundam Generation D - Babylonia Kenkoku Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0xefd3a865]
|
||||
name = "SD Gundam Generation E - Zanskar Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0xc5dfa8fd]
|
||||
name = "SD Gundam Generation F - Colony Kakutouki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x43ad5a45]
|
||||
name = "SD Ultra Battle - Seven Densetsu (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x04939d14]
|
||||
name = "SD Ultra Battle - Ultra Densetsu (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0xa5c0045e]
|
||||
name = "Secret of Evermore (USA) [!]"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
FILE *fp;
|
||||
|
||||
uint decode_size(substring &str) {
|
||||
uint decode_size(string &str) {
|
||||
//hex encoding
|
||||
if(strbegin(str, "0x")) {
|
||||
strltrim(str, "0x");
|
||||
@@ -31,8 +31,8 @@ uint decode_size(substring &str) {
|
||||
return strdec(str);
|
||||
}
|
||||
|
||||
void build_block(substring &block) {
|
||||
string line, hashpart, part;
|
||||
void build_block(string &block) {
|
||||
stringarray line, hashpart, part;
|
||||
split(line, "\n", block);
|
||||
|
||||
if(strbegin(line[0], "[") == false) {
|
||||
@@ -58,26 +58,26 @@ db_item dbi;
|
||||
strset(line[i], pos, 0);
|
||||
}
|
||||
|
||||
if(strmatch(line[i], ""))continue;
|
||||
if(line[i] == "")continue;
|
||||
|
||||
split(part, "=", line[i]);
|
||||
strunquote(part[1]);
|
||||
|
||||
if(strmatch(part[0], "name")) {
|
||||
if(part[0] == "name") {
|
||||
strncpy(dbi.name, strptr(part[1]), 128);
|
||||
dbi.name[128] = 0;
|
||||
}
|
||||
|
||||
if(strmatch(part[0], "pcb")) {
|
||||
if(part[0] == "pcb") {
|
||||
strncpy(dbi.pcb, strptr(part[1]), 32);
|
||||
dbi.pcb[31] = 0;
|
||||
}
|
||||
|
||||
if(strmatch(part[0], "rom")) {
|
||||
if(part[0] == "rom") {
|
||||
dbi.rom = decode_size(part[1]);
|
||||
}
|
||||
|
||||
if(strmatch(part[0], "ram")) {
|
||||
if(part[0] == "ram") {
|
||||
dbi.ram = decode_size(part[1]);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ db_item dbi;
|
||||
}
|
||||
|
||||
void build_database() {
|
||||
string data, block;
|
||||
stringarray data, block;
|
||||
if(strfread(data, "cartdb.txt") == false)return;
|
||||
|
||||
fp = fopen("cart.db", "wb");
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
@make -r PLATFORM=win-visualc-lui
|
||||
@move bsnes.exe ../bsnes.exe>nul
|
||||
@pause
|
||||
+6
-3
@@ -1,4 +1,5 @@
|
||||
#include "../base.h"
|
||||
#include "../reader/filereader.h"
|
||||
|
||||
Cheat cheat;
|
||||
|
||||
@@ -268,14 +269,15 @@ void Cheat::disable(uint32 n) {
|
||||
* cheat file manipulation routines
|
||||
*****/
|
||||
|
||||
bool Cheat::load(Reader &rf) {
|
||||
bool Cheat::load(const char *fn) {
|
||||
FileReader rf(fn);
|
||||
if(!rf.ready())return false;
|
||||
|
||||
uint8 *raw_data = rf.read();
|
||||
stringarray data, line;
|
||||
raw_data[rf.size()] = 0;
|
||||
strcpy(data, (char*)raw_data);
|
||||
SafeFree(raw_data);
|
||||
safe_free(raw_data);
|
||||
replace(data, "\r\n", "\n");
|
||||
|
||||
split(line, "\n", data);
|
||||
@@ -299,7 +301,8 @@ stringarray data, line;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::save(Writer &wf) {
|
||||
bool Cheat::save(const char *fn) {
|
||||
FileWriter wf(fn);
|
||||
if(!wf.ready())return false;
|
||||
|
||||
string data;
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@ public:
|
||||
bool enabled(uint32 n);
|
||||
void enable (uint32 n);
|
||||
void disable(uint32 n);
|
||||
bool load(Reader &rf);
|
||||
bool save(Writer &wf);
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn);
|
||||
void clear();
|
||||
|
||||
Cheat();
|
||||
|
||||
+21
-21
@@ -10,34 +10,34 @@ void OBC1::power() {
|
||||
}
|
||||
|
||||
void OBC1::reset() {
|
||||
memset(cartridge.sram, 0xff, 0x2000);
|
||||
status.baseptr = (cartridge.sram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
|
||||
status.address = (cartridge.sram[0x1ff6] & 0x7f);
|
||||
status.shift = (cartridge.sram[0x1ff6] & 3) << 1;
|
||||
memset(cartridge.ram, 0xff, 0x2000);
|
||||
status.baseptr = (cartridge.ram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
|
||||
status.address = (cartridge.ram[0x1ff6] & 0x7f);
|
||||
status.shift = (cartridge.ram[0x1ff6] & 3) << 1;
|
||||
}
|
||||
|
||||
uint8 OBC1::read(uint16 addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if((addr & 0x1ff8) != 0x1ff0) {
|
||||
return cartridge.sram[addr];
|
||||
return cartridge.ram[addr];
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 0];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 0];
|
||||
case 0x1ff1:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 1];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 1];
|
||||
case 0x1ff2:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 2];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 2];
|
||||
case 0x1ff3:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 3];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 3];
|
||||
case 0x1ff4:
|
||||
return cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
return cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
case 0x1ff5:
|
||||
case 0x1ff6:
|
||||
case 0x1ff7:
|
||||
return cartridge.sram[addr];
|
||||
return cartridge.ram[addr];
|
||||
}
|
||||
|
||||
//never used, blocks compiler warning
|
||||
@@ -48,40 +48,40 @@ void OBC1::write(uint16 addr, uint8 data) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if((addr & 0x1ff8) != 0x1ff0) {
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 0] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 0] = data;
|
||||
break;
|
||||
case 0x1ff1:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 1] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 1] = data;
|
||||
break;
|
||||
case 0x1ff2:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 2] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 2] = data;
|
||||
break;
|
||||
case 0x1ff3:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 3] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 3] = data;
|
||||
break;
|
||||
case 0x1ff4: {
|
||||
uint8 temp;
|
||||
temp = cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
temp = cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||
cartridge.sram[status.baseptr + (status.address >> 2) + 0x200] = temp;
|
||||
cartridge.ram[status.baseptr + (status.address >> 2) + 0x200] = temp;
|
||||
} break;
|
||||
case 0x1ff5:
|
||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
break;
|
||||
case 0x1ff6:
|
||||
status.address = (data & 0x7f);
|
||||
status.shift = (data & 3) << 1;
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
break;
|
||||
case 0x1ff7:
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ understood.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
typedef uint8_t bool8;
|
||||
|
||||
class SDD1_IM { //Input Manager
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
@make PLATFORM=win-visualc-lui clean
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
make PLATFORM=x-gcc-lui clean
|
||||
+88
-54
@@ -2,72 +2,106 @@ Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
Setting FS::base_path(0, "fs.base_path",
|
||||
"Directory that bsnes resides in", "");
|
||||
Setting FS::rom_path(&config_file, "fs.rom_path",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
Setting FS::save_path(&config_file, "fs.save_path",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
string file_updatepath(const char *req_file, const char *req_path) {
|
||||
string file(req_file);
|
||||
replace(file, "\\", "/");
|
||||
if(!req_path || strlen(req_path) == 0) { return file; }
|
||||
|
||||
Setting FS::save_ext(&config_file, "fs.save_ext",
|
||||
string path(req_path);
|
||||
replace(path, "\\", "/");
|
||||
if(!strend(path, "/")) { strcat(path, "/"); }
|
||||
|
||||
if(strbegin(path, "./")) {
|
||||
strltrim(path, "./");
|
||||
string temp;
|
||||
strcpy(temp, config::path.base);
|
||||
strcat(temp, path);
|
||||
strcpy(path, temp);
|
||||
}
|
||||
|
||||
stringarray part;
|
||||
split(part, "/", file);
|
||||
strcat(path, part[count(part) - 1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
StringSetting Path::base(0, "fs.base_path",
|
||||
"Path that bsnes resides in", "");
|
||||
StringSetting Path::rom(&config_file, "path.rom",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
StringSetting Path::save(&config_file, "path.save",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
StringSetting Path::bios(&config_file, "path.bios",
|
||||
"Path where BIOS file(s) are located\n"
|
||||
"Supported BIOS files:\n"
|
||||
"stbios.bin - Bandai Sufami Turbo"
|
||||
"", "./bios");
|
||||
|
||||
StringSetting Path::save_ext(&config_file, "path.save_ext",
|
||||
"Extension to be used for all save RAM files", "srm");
|
||||
|
||||
Setting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
|
||||
"Use precalculated TV-style gamma ramp", true, Setting::TRUE_FALSE);
|
||||
Setting SNES::sepia(&config_file, "snes.colorfilter.sepia",
|
||||
"Convert color to sepia tone", false, Setting::TRUE_FALSE);
|
||||
Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
|
||||
"Convert color to grayscale tone", false, Setting::TRUE_FALSE);
|
||||
Setting SNES::invert(&config_file, "snes.colorfilter.invert",
|
||||
"Invert output image colors", false, Setting::TRUE_FALSE);
|
||||
Setting SNES::contrast(&config_file, "snes.colorfilter.contrast",
|
||||
"Contrast", 0, Setting::DEC);
|
||||
Setting SNES::brightness(&config_file, "snes.colorfilter.brightness",
|
||||
"Brightness", 0, Setting::DEC);
|
||||
Setting SNES::gamma(&config_file, "snes.colorfilter.gamma",
|
||||
"Gamma", 80, Setting::DEC);
|
||||
IntegerSetting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
|
||||
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
|
||||
IntegerSetting SNES::sepia(&config_file, "snes.colorfilter.sepia",
|
||||
"Convert color to sepia tone", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
|
||||
"Convert color to grayscale tone", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::invert(&config_file, "snes.colorfilter.invert",
|
||||
"Invert output image colors", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::contrast(&config_file, "snes.colorfilter.contrast",
|
||||
"Contrast", IntegerSetting::Decimal, 0);
|
||||
IntegerSetting SNES::brightness(&config_file, "snes.colorfilter.brightness",
|
||||
"Brightness", IntegerSetting::Decimal, 0);
|
||||
IntegerSetting SNES::gamma(&config_file, "snes.colorfilter.gamma",
|
||||
"Gamma", IntegerSetting::Decimal, 80);
|
||||
|
||||
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
|
||||
IntegerSetting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
|
||||
"Merge fields in NTSC video filter\n"
|
||||
"Set to true if using filter at any refresh rate other than 60hz\n"
|
||||
"", true, Setting::TRUE_FALSE);
|
||||
"", IntegerSetting::Boolean, true);
|
||||
|
||||
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
|
||||
false, Setting::TRUE_FALSE);
|
||||
IntegerSetting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
|
||||
IntegerSetting::Boolean, false);
|
||||
|
||||
Setting SNES::controller_port0(&config_file, "snes.controller_port_1",
|
||||
"Controller attached to SNES port 1", ::SNES::DEVICEID_JOYPAD1, Setting::DEC);
|
||||
Setting SNES::controller_port1(&config_file, "snes.controller_port_2",
|
||||
"Controller attached to SNES port 2", ::SNES::DEVICEID_JOYPAD2, Setting::DEC);
|
||||
IntegerSetting SNES::controller_port0(&config_file, "snes.controller_port_1",
|
||||
"Controller attached to SNES port 1", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD1);
|
||||
IntegerSetting SNES::controller_port1(&config_file, "snes.controller_port_2",
|
||||
"Controller attached to SNES port 2", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD2);
|
||||
|
||||
Setting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
|
||||
"NTSC S-CPU clock rate (in hz)", 21477272, Setting::DEC);
|
||||
Setting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
|
||||
"PAL S-CPU clock rate (in hz)", 21241370, Setting::DEC);
|
||||
Setting CPU::hdma_enable(0, "cpu.hdma_enable",
|
||||
"Enable HDMA effects", true, Setting::TRUE_FALSE);
|
||||
IntegerSetting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
|
||||
"NTSC S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21477272);
|
||||
IntegerSetting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
|
||||
"PAL S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21281370);
|
||||
|
||||
Setting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", 24576000, Setting::DEC);
|
||||
Setting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", 24576000, Setting::DEC);
|
||||
IntegerSetting CPU::hdma_enable(0, "cpu.hdma_enable",
|
||||
"Enable HDMA effects", IntegerSetting::Boolean, true);
|
||||
|
||||
Setting PPU::render_scanline_position(&config_file, "ppu.render_scanline_position",
|
||||
IntegerSetting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
||||
IntegerSetting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
||||
|
||||
IntegerSetting PPU::Hack::render_scanline_position(&config_file, "ppu.hack.render_scanline_position",
|
||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||
256, Setting::DEC);
|
||||
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE);
|
||||
IntegerSetting::Decimal, 512);
|
||||
IntegerSetting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
|
||||
"Cache OAM OBJ attributes one scanline before rendering\n"
|
||||
"This is technically closer to the actual operation of the SNES,\n"
|
||||
"but can cause problems in some games if enabled",
|
||||
IntegerSetting::Boolean, false);
|
||||
|
||||
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::TRUE_FALSE);
|
||||
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::TRUE_FALSE);
|
||||
IntegerSetting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", IntegerSetting::Boolean, true);
|
||||
|
||||
};
|
||||
+25
-20
@@ -2,38 +2,43 @@ extern Config config_file;
|
||||
|
||||
namespace config {
|
||||
|
||||
extern struct FS {
|
||||
static Setting base_path, rom_path, save_path;
|
||||
static Setting save_ext;
|
||||
} fs;
|
||||
string file_updatepath(const char *, const char *);
|
||||
|
||||
extern struct Path {
|
||||
static StringSetting base, rom, save, bios;
|
||||
static StringSetting save_ext;
|
||||
} path;
|
||||
|
||||
extern struct SNES {
|
||||
static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
|
||||
static Setting ntsc_merge_fields;
|
||||
static Setting mute;
|
||||
static Setting controller_port0;
|
||||
static Setting controller_port1;
|
||||
static IntegerSetting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
|
||||
static IntegerSetting ntsc_merge_fields;
|
||||
static IntegerSetting mute;
|
||||
static IntegerSetting controller_port0;
|
||||
static IntegerSetting controller_port1;
|
||||
} snes;
|
||||
|
||||
extern struct CPU {
|
||||
static Setting ntsc_clock_rate, pal_clock_rate;
|
||||
static Setting hdma_enable;
|
||||
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
|
||||
static IntegerSetting hdma_enable;
|
||||
} cpu;
|
||||
|
||||
extern struct SMP {
|
||||
static Setting ntsc_clock_rate, pal_clock_rate;
|
||||
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
|
||||
} smp;
|
||||
|
||||
extern struct PPU {
|
||||
static Setting render_scanline_position;
|
||||
static Setting opt_enable;
|
||||
struct Hack {
|
||||
static IntegerSetting render_scanline_position;
|
||||
static IntegerSetting obj_cache;
|
||||
} hack;
|
||||
|
||||
static Setting bg1_pri0_enable, bg1_pri1_enable;
|
||||
static Setting bg2_pri0_enable, bg2_pri1_enable;
|
||||
static Setting bg3_pri0_enable, bg3_pri1_enable;
|
||||
static Setting bg4_pri0_enable, bg4_pri1_enable;
|
||||
static Setting oam_pri0_enable, oam_pri1_enable;
|
||||
static Setting oam_pri2_enable, oam_pri3_enable;
|
||||
static IntegerSetting opt_enable;
|
||||
static IntegerSetting bg1_pri0_enable, bg1_pri1_enable;
|
||||
static IntegerSetting bg2_pri0_enable, bg2_pri1_enable;
|
||||
static IntegerSetting bg3_pri0_enable, bg3_pri1_enable;
|
||||
static IntegerSetting bg4_pri0_enable, bg4_pri1_enable;
|
||||
static IntegerSetting oam_pri0_enable, oam_pri1_enable;
|
||||
static IntegerSetting oam_pri2_enable, oam_pri3_enable;
|
||||
} ppu;
|
||||
|
||||
};
|
||||
@@ -1,97 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "core/core.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
#include "bcpu_exec.cpp"
|
||||
#include "bcpu_mmio.cpp"
|
||||
#include "bcpu_int.cpp"
|
||||
|
||||
uint8 bCPU::pio_status() { return status.pio; }
|
||||
|
||||
void bCPU::run() {
|
||||
if(run_state.hdma) {
|
||||
exec_hdma();
|
||||
return;
|
||||
}
|
||||
|
||||
if(run_state.dma) {
|
||||
exec_dma();
|
||||
return;
|
||||
}
|
||||
|
||||
if(status.cycle_pos == 0) { //interrupts only trigger on opcode edges
|
||||
if(run_state.irq && !run_state.stp) {
|
||||
run_state.irq = false;
|
||||
if(time.nmi_pending == true) {
|
||||
time.nmi_pending = false;
|
||||
aa.w = (regs.e == false) ? 0xffea : 0xfffa;
|
||||
} else if(time.irq_pending == true) {
|
||||
time.irq_pending = false;
|
||||
aa.w = (regs.e == false) ? 0xffee : 0xfffe;
|
||||
}
|
||||
irq_run();
|
||||
}
|
||||
}
|
||||
|
||||
exec_cycle();
|
||||
}
|
||||
|
||||
void bCPU::power() {
|
||||
region = snes->region();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
reset();
|
||||
}
|
||||
|
||||
void bCPU::reset() {
|
||||
//reset vector location
|
||||
regs.pc.d = 0;
|
||||
regs.pc.l = r_mem->read(0xfffc);
|
||||
regs.pc.h = r_mem->read(0xfffd);
|
||||
|
||||
//registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
regs.d = 0x0000;
|
||||
regs.db = 0x00;
|
||||
regs.p = 0x34;
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
|
||||
time_reset();
|
||||
mmio_reset();
|
||||
dma_reset();
|
||||
|
||||
run_state.hdma = false;
|
||||
run_state.dma = false;
|
||||
run_state.irq = false;
|
||||
run_state.wai = false;
|
||||
run_state.stp = false;
|
||||
|
||||
status.cycle_pos = 0;
|
||||
status.cycle_count = 0;
|
||||
status.cycles_executed = 0;
|
||||
|
||||
apu_port[0] = 0x00;
|
||||
apu_port[1] = 0x00;
|
||||
apu_port[2] = 0x00;
|
||||
apu_port[3] = 0x00;
|
||||
|
||||
frame();
|
||||
|
||||
//initial latch values for $213c/$213d
|
||||
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
|
||||
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
|
||||
add_cycles(186);
|
||||
}
|
||||
|
||||
bCPU::bCPU() {
|
||||
init_op_tables();
|
||||
}
|
||||
|
||||
bCPU::~bCPU() {}
|
||||
@@ -1,165 +0,0 @@
|
||||
class bCPU : public CPU {
|
||||
public:
|
||||
#include "core/core.h"
|
||||
#include "memory/memory.h"
|
||||
#include "dma/dma.h"
|
||||
#include "timing/timing.h"
|
||||
|
||||
enum { NTSC = 0, PAL = 1 };
|
||||
uint8 region;
|
||||
|
||||
enum {
|
||||
DMASTATE_DMASYNC,
|
||||
DMASTATE_DMASYNC2,
|
||||
DMASTATE_DMASYNC3,
|
||||
DMASTATE_RUN,
|
||||
DMASTATE_CPUSYNC,
|
||||
|
||||
HDMASTATE_IDMASYNC,
|
||||
HDMASTATE_IDMASYNC2,
|
||||
HDMASTATE_IDMASYNC3,
|
||||
HDMASTATE_ICPUSYNC,
|
||||
|
||||
HDMASTATE_DMASYNC,
|
||||
HDMASTATE_DMASYNC2,
|
||||
HDMASTATE_DMASYNC3,
|
||||
HDMASTATE_RUN,
|
||||
HDMASTATE_CPUSYNC
|
||||
};
|
||||
|
||||
struct {
|
||||
bool hdma;
|
||||
bool dma;
|
||||
bool irq;
|
||||
bool stp;
|
||||
bool wai;
|
||||
} run_state;
|
||||
|
||||
struct {
|
||||
uint8 cycle_pos, cycle_count;
|
||||
uint8 opcode;
|
||||
uint32 cycles_executed;
|
||||
|
||||
uint8 dma_state, hdma_state;
|
||||
uint32 dma_cycle_count, hdma_cycle_count;
|
||||
|
||||
//$4207-$420a
|
||||
uint16 virq_trigger, hirq_trigger;
|
||||
|
||||
//$2181-$2183
|
||||
uint32 wram_addr;
|
||||
|
||||
//$4016-$4017
|
||||
bool joypad_strobe_latch;
|
||||
uint8 joypad1_read_pos, joypad2_read_pos;
|
||||
|
||||
//$4200
|
||||
bool nmi_enabled;
|
||||
bool hirq_enabled, virq_enabled;
|
||||
bool auto_joypad_poll;
|
||||
|
||||
//$4201
|
||||
uint8 pio;
|
||||
|
||||
//$4202-$4203
|
||||
uint8 mul_a, mul_b;
|
||||
|
||||
//$4204-$4206
|
||||
uint16 div_a;
|
||||
uint8 div_b;
|
||||
|
||||
//$4207-$420a
|
||||
uint16 hirq_pos, virq_pos;
|
||||
|
||||
//$4214-$4216
|
||||
uint16 r4214;
|
||||
uint16 r4216;
|
||||
} status;
|
||||
|
||||
inline bool hdma_test();
|
||||
inline bool nmi_test();
|
||||
inline bool irq_test();
|
||||
|
||||
inline uint8 pio_status();
|
||||
inline void run();
|
||||
inline uint32 clocks_executed();
|
||||
inline void power();
|
||||
inline void reset();
|
||||
|
||||
inline void irq_run();
|
||||
|
||||
//mmio commands
|
||||
void mmio_reset();
|
||||
uint8 mmio_r2180();
|
||||
uint8 mmio_r4016();
|
||||
uint8 mmio_r4017();
|
||||
uint8 mmio_r4210();
|
||||
uint8 mmio_r4211();
|
||||
uint8 mmio_r4212();
|
||||
uint8 mmio_r4213();
|
||||
uint8 mmio_r4214();
|
||||
uint8 mmio_r4215();
|
||||
uint8 mmio_r4216();
|
||||
uint8 mmio_r4217();
|
||||
uint8 mmio_r4218();
|
||||
uint8 mmio_r4219();
|
||||
uint8 mmio_r421a();
|
||||
uint8 mmio_r421b();
|
||||
uint8 mmio_r43x0(uint8 i);
|
||||
uint8 mmio_r43x1(uint8 i);
|
||||
uint8 mmio_r43x2(uint8 i);
|
||||
uint8 mmio_r43x3(uint8 i);
|
||||
uint8 mmio_r43x4(uint8 i);
|
||||
uint8 mmio_r43x5(uint8 i);
|
||||
uint8 mmio_r43x6(uint8 i);
|
||||
uint8 mmio_r43x7(uint8 i);
|
||||
uint8 mmio_r43x8(uint8 i);
|
||||
uint8 mmio_r43x9(uint8 i);
|
||||
uint8 mmio_r43xa(uint8 i);
|
||||
uint8 mmio_r43xb(uint8 i);
|
||||
void mmio_w2180(uint8 value);
|
||||
void mmio_w2181(uint8 value);
|
||||
void mmio_w2182(uint8 value);
|
||||
void mmio_w2183(uint8 value);
|
||||
void mmio_w4016(uint8 value);
|
||||
void mmio_w4200(uint8 value);
|
||||
void mmio_w4201(uint8 value);
|
||||
void mmio_w4202(uint8 value);
|
||||
void mmio_w4203(uint8 value);
|
||||
void mmio_w4204(uint8 value);
|
||||
void mmio_w4205(uint8 value);
|
||||
void mmio_w4206(uint8 value);
|
||||
void mmio_w4207(uint8 value);
|
||||
void mmio_w4208(uint8 value);
|
||||
void mmio_w4209(uint8 value);
|
||||
void mmio_w420a(uint8 value);
|
||||
void mmio_w420b(uint8 value);
|
||||
void mmio_w420c(uint8 value);
|
||||
void mmio_w420d(uint8 value);
|
||||
void mmio_w43x0(uint8 value, uint8 i);
|
||||
void mmio_w43x1(uint8 value, uint8 i);
|
||||
void mmio_w43x2(uint8 value, uint8 i);
|
||||
void mmio_w43x3(uint8 value, uint8 i);
|
||||
void mmio_w43x4(uint8 value, uint8 i);
|
||||
void mmio_w43x5(uint8 value, uint8 i);
|
||||
void mmio_w43x6(uint8 value, uint8 i);
|
||||
void mmio_w43x7(uint8 value, uint8 i);
|
||||
void mmio_w43x8(uint8 value, uint8 i);
|
||||
void mmio_w43x9(uint8 value, uint8 i);
|
||||
void mmio_w43xa(uint8 value, uint8 i);
|
||||
void mmio_w43xb(uint8 value, uint8 i);
|
||||
|
||||
uint8 mmio_read (uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
enum { CYCLE_OPREAD, CYCLE_READ, CYCLE_WRITE, CYCLE_IO };
|
||||
inline void pre_exec_cycle();
|
||||
inline void exec_hdma();
|
||||
inline void exec_dma();
|
||||
inline void exec_cycle();
|
||||
inline void last_cycle();
|
||||
inline bool in_opcode();
|
||||
|
||||
bCPU();
|
||||
~bCPU();
|
||||
};
|
||||
@@ -1,163 +0,0 @@
|
||||
void bCPU::last_cycle() {
|
||||
time.nmi_pending |= nmi_test();
|
||||
time.irq_pending |= irq_test();
|
||||
|
||||
run_state.irq = (time.nmi_pending || time.irq_pending);
|
||||
}
|
||||
|
||||
void bCPU::pre_exec_cycle() {
|
||||
if(!run_state.dma && !run_state.hdma)return;
|
||||
|
||||
int c, z;
|
||||
if(run_state.hdma) {
|
||||
switch(status.hdma_state) {
|
||||
case HDMASTATE_ICPUSYNC:
|
||||
case HDMASTATE_CPUSYNC:
|
||||
c = status.cycle_count;
|
||||
z = c - (status.hdma_cycle_count % c);
|
||||
if(!z)z = c;
|
||||
add_cycles(z);
|
||||
run_state.hdma = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(run_state.dma) {
|
||||
switch(status.dma_state) {
|
||||
case DMASTATE_CPUSYNC:
|
||||
c = status.cycle_count;
|
||||
z = c - (status.dma_cycle_count % c);
|
||||
if(!z)z = c;
|
||||
add_cycles(z);
|
||||
run_state.dma = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::exec_hdma() {
|
||||
int n;
|
||||
static int z;
|
||||
switch(status.hdma_state) {
|
||||
case HDMASTATE_IDMASYNC:
|
||||
status.hdma_cycle_count = 0;
|
||||
z = 0;
|
||||
if(!run_state.dma) {
|
||||
exec_cycle();
|
||||
status.hdma_state = HDMASTATE_IDMASYNC2;
|
||||
} else {
|
||||
status.hdma_state = HDMASTATE_IDMASYNC3;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_IDMASYNC2:
|
||||
n = 8 - dma_counter() + 8;
|
||||
add_cycles(n);
|
||||
status.hdma_cycle_count += n;
|
||||
status.hdma_state = HDMASTATE_IDMASYNC3;
|
||||
break;
|
||||
case HDMASTATE_IDMASYNC3:
|
||||
hdma_init();
|
||||
if(!run_state.dma) {
|
||||
status.hdma_state = HDMASTATE_ICPUSYNC;
|
||||
} else {
|
||||
run_state.hdma = false;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_ICPUSYNC:
|
||||
exec_cycle();
|
||||
break;
|
||||
|
||||
case HDMASTATE_DMASYNC:
|
||||
status.hdma_cycle_count = 0;
|
||||
z = 0;
|
||||
if(!run_state.dma) {
|
||||
exec_cycle();
|
||||
status.hdma_state = HDMASTATE_DMASYNC2;
|
||||
} else {
|
||||
status.hdma_state = HDMASTATE_DMASYNC3;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_DMASYNC2:
|
||||
n = 8 - dma_counter() + 8;
|
||||
add_cycles(n);
|
||||
status.hdma_cycle_count += n;
|
||||
status.hdma_state = HDMASTATE_DMASYNC3;
|
||||
break;
|
||||
case HDMASTATE_DMASYNC3:
|
||||
if(channel[z].hdma_line_counter) {
|
||||
add_cycles(8);
|
||||
status.hdma_cycle_count += 8;
|
||||
}
|
||||
if(++z < 8)break;
|
||||
status.hdma_state = HDMASTATE_RUN;
|
||||
break;
|
||||
case HDMASTATE_RUN:
|
||||
hdma_run(); //updates status.hdma_cycle_count
|
||||
if(!run_state.dma) {
|
||||
status.hdma_state = HDMASTATE_CPUSYNC;
|
||||
} else {
|
||||
run_state.hdma = false;
|
||||
}
|
||||
break;
|
||||
case HDMASTATE_CPUSYNC:
|
||||
exec_cycle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::exec_dma() {
|
||||
int n;
|
||||
static int z;
|
||||
switch(status.dma_state) {
|
||||
case DMASTATE_DMASYNC:
|
||||
exec_cycle();
|
||||
status.dma_state = DMASTATE_DMASYNC2;
|
||||
break;
|
||||
case DMASTATE_DMASYNC2:
|
||||
n = 8 - dma_counter() + 8;
|
||||
add_cycles(n);
|
||||
status.dma_cycle_count = n;
|
||||
z = 0;
|
||||
status.dma_state = DMASTATE_DMASYNC3;
|
||||
break;
|
||||
case DMASTATE_DMASYNC3:
|
||||
if(channel[z].dma_enabled == true) {
|
||||
add_cycles(8);
|
||||
status.dma_cycle_count += 8;
|
||||
}
|
||||
if(++z < 8)break;
|
||||
status.dma_state = DMASTATE_RUN;
|
||||
break;
|
||||
case DMASTATE_RUN:
|
||||
dma_run(); //updates status.dma_cycle_count
|
||||
cycle_edge();
|
||||
break;
|
||||
case DMASTATE_CPUSYNC:
|
||||
exec_cycle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::exec_cycle() {
|
||||
if(status.cycle_pos) {
|
||||
(this->*optbl[status.opcode])();
|
||||
#ifdef DEBUGGER
|
||||
if(status.cycle_pos == 0) {
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_END);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//on first cycle?
|
||||
#ifdef DEBUGGER
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
|
||||
#endif
|
||||
status.opcode = op_readpc();
|
||||
status.cycle_pos = 1;
|
||||
}
|
||||
|
||||
//only return true when we are on an opcode edge
|
||||
bool bCPU::in_opcode() {
|
||||
return (status.cycle_pos != 0);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
void bCPU::irq_run() {
|
||||
mem_read(regs.pc.d);
|
||||
cpu_io();
|
||||
if(!regs.e)op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
||||
rd.l = op_readaddr(aa.w + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
#ifdef DEBUGGER
|
||||
//let debugger know the new IRQ opcode address
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_END);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool bCPU::nmi_test() {
|
||||
if(time.nmi_transition == 0)return false;
|
||||
time.nmi_transition = 0;
|
||||
|
||||
run_state.wai = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bCPU::irq_test() {
|
||||
if(time.irq_transition == 1)goto _true;
|
||||
|
||||
if(time.irq_read == 0) {
|
||||
if(time.irq_line == 1 && (irq_trigger_pos_match(0) || irq_trigger_pos_match(2))) {
|
||||
return false;
|
||||
}
|
||||
goto _true;
|
||||
}
|
||||
|
||||
if(time.irq_line == 0) {
|
||||
time.irq_line = 1;
|
||||
goto _true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
_true:
|
||||
time.irq_transition = 0;
|
||||
|
||||
run_state.wai = false;
|
||||
return (regs.p.i) ? false : true;
|
||||
}
|
||||
@@ -1,650 +0,0 @@
|
||||
void bCPU::mmio_reset() {
|
||||
//$2181-$2183
|
||||
status.wram_addr = 0x000000;
|
||||
|
||||
//$4016-$4017
|
||||
status.joypad_strobe_latch = 0;
|
||||
status.joypad1_read_pos = 0;
|
||||
status.joypad2_read_pos = 0;
|
||||
|
||||
//$4200
|
||||
status.nmi_enabled = false;
|
||||
status.hirq_enabled = false;
|
||||
status.virq_enabled = false;
|
||||
status.auto_joypad_poll = false;
|
||||
|
||||
//$4201
|
||||
status.pio = 0xff;
|
||||
|
||||
//$4202-$4203
|
||||
status.mul_a = 0xff;
|
||||
status.mul_b = 0xff;
|
||||
|
||||
//$4204-$4206
|
||||
status.div_a = 0xffff;
|
||||
status.div_b = 0xff;
|
||||
|
||||
//$4207-$420a
|
||||
status.hirq_pos = 0x01ff;
|
||||
status.virq_pos = 0x01ff;
|
||||
|
||||
//$4214-$4217
|
||||
status.r4214 = 0x0000;
|
||||
status.r4216 = 0x0000;
|
||||
}
|
||||
|
||||
//WMDATA
|
||||
uint8 bCPU::mmio_r2180() {
|
||||
uint8 r;
|
||||
r = r_mem->read(0x7e0000 | status.wram_addr);
|
||||
status.wram_addr++;
|
||||
status.wram_addr &= 0x01ffff;
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
//7-2 = MDR
|
||||
//1-0 = Joypad serial data
|
||||
/* The joypad contains a small bit shifter that has 16 bits.
|
||||
* Reading from 4016 reads one bit from this buffer, then moves
|
||||
* the buffer left one, and adds a '1' to the rightmost bit.
|
||||
* Writing a one to $4016 will fill the buffer with the current
|
||||
* joypad button states, and lock the bit shifter at position
|
||||
* zero. All reads will be the first buffer state, or 'B'.
|
||||
* A zero must be written back to $4016 to unlock the buffer,
|
||||
* so that reads will increment the bit shifting position.
|
||||
*/
|
||||
uint8 bCPU::mmio_r4016() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0xfc;
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B);
|
||||
} else {
|
||||
switch(status.joypad1_read_pos) {
|
||||
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B); break;
|
||||
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y); break;
|
||||
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT); break;
|
||||
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START); break;
|
||||
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP); break;
|
||||
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN); break;
|
||||
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT); break;
|
||||
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT); break;
|
||||
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A); break;
|
||||
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X); break;
|
||||
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L); break;
|
||||
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R); break;
|
||||
case 12: break;
|
||||
case 13: break;
|
||||
case 14: break;
|
||||
case 15: break; //bits 12-15 always return 0
|
||||
//all subsequent reads return joypad connection status
|
||||
case 16: r |= 1; break; //joypad connected bit
|
||||
}
|
||||
if(++status.joypad1_read_pos > 16)status.joypad1_read_pos = 16;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOYSER1
|
||||
//7-5 = MDR
|
||||
//4-2 = Always 1 (pins are connected to GND)
|
||||
//1-0 = Joypad serial data
|
||||
uint8 bCPU::mmio_r4017() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0xe0;
|
||||
r |= 0x1c;
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B);
|
||||
} else {
|
||||
switch(status.joypad2_read_pos) {
|
||||
case 0: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B); break;
|
||||
case 1: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y); break;
|
||||
case 2: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT); break;
|
||||
case 3: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START); break;
|
||||
case 4: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP); break;
|
||||
case 5: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN); break;
|
||||
case 6: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT); break;
|
||||
case 7: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT); break;
|
||||
case 8: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A); break;
|
||||
case 9: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X); break;
|
||||
case 10: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L); break;
|
||||
case 11: r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R); break;
|
||||
case 12: break;
|
||||
case 13: break;
|
||||
case 14: break;
|
||||
case 15: break; //bits 12-15 always return 0
|
||||
//all subsequent reads return joypad connection status
|
||||
case 16: r |= 1; break; //joypad connected bit
|
||||
}
|
||||
if(++status.joypad2_read_pos > 16)status.joypad2_read_pos = 16;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//RDNMI
|
||||
//7 = NMI acknowledge
|
||||
//6-4 = MDR
|
||||
//3-0 = CPU (5a22) version
|
||||
uint8 bCPU::mmio_r4210() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0x70;
|
||||
r |= uint8(!time.nmi_read) << 7;
|
||||
|
||||
if(!nmi_trigger_pos_match(0) && !nmi_trigger_pos_match(2)) {
|
||||
time.nmi_read = 1;
|
||||
}
|
||||
|
||||
r |= (cpu_version & 0x0f);
|
||||
return r;
|
||||
}
|
||||
|
||||
//TIMEUP
|
||||
//7 = IRQ acknowledge
|
||||
//6-0 = MDR
|
||||
uint8 bCPU::mmio_r4211() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0x7f;
|
||||
r |= uint8(!time.irq_read) << 7;
|
||||
|
||||
if(!irq_trigger_pos_match(0) && !irq_trigger_pos_match(2)) {
|
||||
time.irq_read = 1;
|
||||
time.irq_line = 1;
|
||||
time.irq_transition = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//HVBJOY
|
||||
//7 = in vblank
|
||||
//6 = in hblank
|
||||
//5-1 = MDR
|
||||
//0 = joypad ready
|
||||
uint8 bCPU::mmio_r4212() {
|
||||
uint8 r;
|
||||
r = regs.mdr & 0x3e;
|
||||
|
||||
uint16 vs = overscan() ? 240 : 225;
|
||||
|
||||
//auto joypad polling
|
||||
if(time.v >= vs && time.v <= (vs + 2))r |= 0x01;
|
||||
|
||||
//hblank
|
||||
if(time.hc <= 2 || time.hc >= 1096)r |= 0x40;
|
||||
|
||||
//vblank
|
||||
if(time.v >= vs)r |= 0x80;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//RDIO
|
||||
uint8 bCPU::mmio_r4213() {
|
||||
return status.pio;
|
||||
}
|
||||
|
||||
//RDDIVL
|
||||
uint8 bCPU::mmio_r4214() {
|
||||
return status.r4214;
|
||||
}
|
||||
|
||||
//RDDIVH
|
||||
uint8 bCPU::mmio_r4215() {
|
||||
return status.r4214 >> 8;
|
||||
}
|
||||
|
||||
//RDMPYL
|
||||
uint8 bCPU::mmio_r4216() {
|
||||
return status.r4216;
|
||||
}
|
||||
|
||||
//RDMPYH
|
||||
uint8 bCPU::mmio_r4217() {
|
||||
return status.r4216 >> 8;
|
||||
}
|
||||
|
||||
//JOY1L
|
||||
uint8 bCPU::mmio_r4218() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = 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
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_A) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_X) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_L) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_R) << 4;
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOY1H
|
||||
uint8 bCPU::mmio_r4219() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = 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
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_B) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_Y) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_SELECT) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_START) << 4;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_UP) << 3;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_DOWN) << 2;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_LEFT) << 1;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD1, SNES::JOYPAD_RIGHT);
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOY2L
|
||||
uint8 bCPU::mmio_r421a() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = 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
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_A) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_X) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_L) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_R) << 4;
|
||||
return r;
|
||||
}
|
||||
|
||||
//JOY2H
|
||||
uint8 bCPU::mmio_r421b() {
|
||||
uint8 r = 0x00;
|
||||
uint16 v = 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
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_B) << 7;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_Y) << 6;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_SELECT) << 5;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_START) << 4;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_UP) << 3;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_DOWN) << 2;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_LEFT) << 1;
|
||||
r |= (uint8)snes->get_input_status(SNES::DEVICEID_JOYPAD2, SNES::JOYPAD_RIGHT);
|
||||
return r;
|
||||
}
|
||||
|
||||
//DMAPx
|
||||
uint8 bCPU::mmio_r43x0(uint8 i) {
|
||||
return channel[i].dmap;
|
||||
}
|
||||
|
||||
//BBADx
|
||||
uint8 bCPU::mmio_r43x1(uint8 i) {
|
||||
return channel[i].destaddr;
|
||||
}
|
||||
|
||||
//A1TxL
|
||||
uint8 bCPU::mmio_r43x2(uint8 i) {
|
||||
return channel[i].srcaddr;
|
||||
}
|
||||
|
||||
//A1TxH
|
||||
uint8 bCPU::mmio_r43x3(uint8 i) {
|
||||
return channel[i].srcaddr >> 8;
|
||||
}
|
||||
|
||||
//A1Bx
|
||||
uint8 bCPU::mmio_r43x4(uint8 i) {
|
||||
return channel[i].srcbank;
|
||||
}
|
||||
|
||||
//DASxL
|
||||
uint8 bCPU::mmio_r43x5(uint8 i) {
|
||||
return channel[i].xfersize;
|
||||
}
|
||||
|
||||
//DASxH
|
||||
uint8 bCPU::mmio_r43x6(uint8 i) {
|
||||
return channel[i].xfersize >> 8;
|
||||
}
|
||||
|
||||
//DASBx
|
||||
uint8 bCPU::mmio_r43x7(uint8 i) {
|
||||
return channel[i].hdma_ibank;
|
||||
}
|
||||
|
||||
//A2AxL
|
||||
uint8 bCPU::mmio_r43x8(uint8 i) {
|
||||
return channel[i].hdma_addr;
|
||||
}
|
||||
|
||||
//A2AxH
|
||||
uint8 bCPU::mmio_r43x9(uint8 i) {
|
||||
return channel[i].hdma_addr >> 8;
|
||||
}
|
||||
|
||||
//NTRLx
|
||||
uint8 bCPU::mmio_r43xa(uint8 i) {
|
||||
return channel[i].hdma_line_counter;
|
||||
}
|
||||
|
||||
//???
|
||||
uint8 bCPU::mmio_r43xb(uint8 i) {
|
||||
return channel[i].hdma_unknown;
|
||||
}
|
||||
|
||||
uint8 bCPU::mmio_read(uint16 addr) {
|
||||
//APU
|
||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||
return r_smp->port_read(addr & 3);
|
||||
}
|
||||
|
||||
//HDMA
|
||||
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
||||
uint i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
case 0x0: return mmio_r43x0(i);
|
||||
case 0x1: return mmio_r43x1(i);
|
||||
case 0x2: return mmio_r43x2(i);
|
||||
case 0x3: return mmio_r43x3(i);
|
||||
case 0x4: return mmio_r43x4(i);
|
||||
case 0x5: return mmio_r43x5(i);
|
||||
case 0x6: return mmio_r43x6(i);
|
||||
case 0x7: return mmio_r43x7(i);
|
||||
case 0x8: return mmio_r43x8(i);
|
||||
case 0x9: return mmio_r43x9(i);
|
||||
case 0xa: return mmio_r43xa(i);
|
||||
case 0xb: return mmio_r43xb(i);
|
||||
case 0xc: return regs.mdr; //unmapped
|
||||
case 0xd: return regs.mdr; //unmapped
|
||||
case 0xe: return regs.mdr; //unmapped
|
||||
case 0xf: return mmio_r43xb(i); //mirror of 43xb
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x2180: return mmio_r2180(); //WMDATA
|
||||
case 0x4016: return mmio_r4016(); //JOYSER0
|
||||
case 0x4017: return mmio_r4017(); //JOYSER1
|
||||
case 0x4210: return mmio_r4210(); //RDNMI
|
||||
case 0x4211: return mmio_r4211(); //TIMEUP
|
||||
case 0x4212: return mmio_r4212(); //HVBJOY
|
||||
case 0x4213: return mmio_r4213(); //RDIO
|
||||
case 0x4214: return mmio_r4214(); //RDDIVL
|
||||
case 0x4215: return mmio_r4215(); //RDDIVH
|
||||
case 0x4216: return mmio_r4216(); //RDMPYL
|
||||
case 0x4217: return mmio_r4217(); //RDMPYH
|
||||
case 0x4218: return mmio_r4218(); //JOY1L
|
||||
case 0x4219: return mmio_r4219(); //JOY1H
|
||||
case 0x421a: return mmio_r421a(); //JOY2L
|
||||
case 0x421b: return mmio_r421b(); //JOY2H
|
||||
case 0x421c: return 0x00;
|
||||
case 0x421d: return 0x00;
|
||||
case 0x421e: return 0x00;
|
||||
case 0x421f: return 0x00;
|
||||
}
|
||||
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
//WMDATA
|
||||
void bCPU::mmio_w2180(uint8 value) {
|
||||
r_mem->write(0x7e0000 | status.wram_addr, value);
|
||||
status.wram_addr++;
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//WMADDL
|
||||
void bCPU::mmio_w2181(uint8 value) {
|
||||
status.wram_addr = (status.wram_addr & 0xffff00) | value;
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//WMADDM
|
||||
void bCPU::mmio_w2182(uint8 value) {
|
||||
status.wram_addr = (status.wram_addr & 0xff00ff) | (value << 8);
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//WMADDH
|
||||
void bCPU::mmio_w2183(uint8 value) {
|
||||
status.wram_addr = (status.wram_addr & 0x00ffff) | (value << 16);
|
||||
status.wram_addr &= 0x01ffff;
|
||||
}
|
||||
|
||||
//JOYSER0
|
||||
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
|
||||
//strobing $4016.d0 affects both controller port latches.
|
||||
//$4017 bit 0 writes are ignored.
|
||||
void bCPU::mmio_w4016(uint8 value) {
|
||||
status.joypad_strobe_latch = bool(value & 1);
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
snes->poll_input();
|
||||
status.joypad1_read_pos = 0;
|
||||
status.joypad2_read_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//NMITIMEN
|
||||
void bCPU::mmio_w4200(uint8 value) {
|
||||
status.nmi_enabled = bool(value & 0x80);
|
||||
status.virq_enabled = bool(value & 0x20);
|
||||
status.hirq_enabled = bool(value & 0x10);
|
||||
status.auto_joypad_poll = bool(value & 0x01);
|
||||
|
||||
if(time.nmi_read == 0) {
|
||||
if(time.nmi_line == 1 && !status.nmi_enabled == 0) {
|
||||
time.nmi_transition = 1;
|
||||
}
|
||||
time.nmi_line = !status.nmi_enabled;
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
time.irq_line = 1;
|
||||
time.irq_read = 1;
|
||||
time.irq_transition = 0;
|
||||
}
|
||||
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//WRIO
|
||||
void bCPU::mmio_w4201(uint8 value) {
|
||||
if((status.pio & 0x80) && !(value & 0x80)) {
|
||||
r_ppu->latch_counters();
|
||||
}
|
||||
status.pio = value;
|
||||
}
|
||||
|
||||
//WRMPYA
|
||||
void bCPU::mmio_w4202(uint8 value) {
|
||||
status.mul_a = value;
|
||||
}
|
||||
|
||||
//WRMPYB
|
||||
void bCPU::mmio_w4203(uint8 value) {
|
||||
status.mul_b = value;
|
||||
status.r4216 = status.mul_a * status.mul_b;
|
||||
}
|
||||
|
||||
//WRDIVL
|
||||
void bCPU::mmio_w4204(uint8 value) {
|
||||
status.div_a = (status.div_a & 0xff00) | (value);
|
||||
}
|
||||
|
||||
//WRDIVH
|
||||
void bCPU::mmio_w4205(uint8 value) {
|
||||
status.div_a = (status.div_a & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//WRDIVB
|
||||
void bCPU::mmio_w4206(uint8 value) {
|
||||
status.div_b = value;
|
||||
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
|
||||
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
|
||||
}
|
||||
|
||||
//HTIMEL
|
||||
void bCPU::mmio_w4207(uint8 value) {
|
||||
status.hirq_pos = ((status.hirq_pos & 0xff00) | value) & 0x01ff;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//HTIMEH
|
||||
void bCPU::mmio_w4208(uint8 value) {
|
||||
status.hirq_pos = ((status.hirq_pos & 0x00ff) | (value << 8)) & 0x01ff;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//VTIMEL
|
||||
void bCPU::mmio_w4209(uint8 value) {
|
||||
status.virq_pos = ((status.virq_pos & 0xff00) | value) & 0x01ff;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//VTIMEH
|
||||
void bCPU::mmio_w420a(uint8 value) {
|
||||
status.virq_pos = ((status.virq_pos & 0x00ff) | (value << 8)) & 0x01ff;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
//DMAEN
|
||||
//DMA enable does not disable active HDMA channels
|
||||
void bCPU::mmio_w420b(uint8 value) {
|
||||
if(value != 0x00) {
|
||||
run_state.dma = true;
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].dma_enabled = bool(value & (1 << i));
|
||||
//TODO: clearing read_index may interfere with DMA+HDMA occurring simultaneously
|
||||
if(channel[i].dma_enabled)channel[i].read_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//HDMAEN
|
||||
void bCPU::mmio_w420c(uint8 value) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].hdma_enabled = bool(value & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
//MEMSEL
|
||||
void bCPU::mmio_w420d(uint8 value) {
|
||||
r_mem->set_speed(value & 1);
|
||||
}
|
||||
|
||||
//DMAPx
|
||||
void bCPU::mmio_w43x0(uint8 value, uint8 i) {
|
||||
channel[i].dmap = value;
|
||||
channel[i].direction = bool(value & 0x80);
|
||||
channel[i].hdma_indirect = bool(value & 0x40);
|
||||
channel[i].incmode = (value & 0x10) ? -1 : 1;
|
||||
channel[i].fixedxfer = bool(value & 0x08);
|
||||
channel[i].xfermode = value & 7;
|
||||
}
|
||||
|
||||
//BBADx
|
||||
void bCPU::mmio_w43x1(uint8 value, uint8 i) {
|
||||
channel[i].destaddr = value;
|
||||
}
|
||||
|
||||
//A1TxL
|
||||
void bCPU::mmio_w43x2(uint8 value, uint8 i) {
|
||||
channel[i].srcaddr = (channel[i].srcaddr & 0xff00) | value;
|
||||
}
|
||||
|
||||
//A1TxH
|
||||
void bCPU::mmio_w43x3(uint8 value, uint8 i) {
|
||||
channel[i].srcaddr = (channel[i].srcaddr & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//A1Bx
|
||||
void bCPU::mmio_w43x4(uint8 value, uint8 i) {
|
||||
channel[i].srcbank = value;
|
||||
}
|
||||
|
||||
//DASxL
|
||||
void bCPU::mmio_w43x5(uint8 value, uint8 i) {
|
||||
channel[i].xfersize = (channel[i].xfersize & 0xff00) | value;
|
||||
}
|
||||
|
||||
//DASxH
|
||||
void bCPU::mmio_w43x6(uint8 value, uint8 i) {
|
||||
channel[i].xfersize = (channel[i].xfersize & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//DASBx
|
||||
void bCPU::mmio_w43x7(uint8 value, uint8 i) {
|
||||
channel[i].hdma_ibank = value;
|
||||
}
|
||||
|
||||
//A2AxL
|
||||
void bCPU::mmio_w43x8(uint8 value, uint8 i) {
|
||||
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | value;
|
||||
}
|
||||
|
||||
//A2AxH
|
||||
void bCPU::mmio_w43x9(uint8 value, uint8 i) {
|
||||
channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (value << 8);
|
||||
}
|
||||
|
||||
//NTRLx
|
||||
void bCPU::mmio_w43xa(uint8 value, uint8 i) {
|
||||
channel[i].hdma_line_counter = value;
|
||||
}
|
||||
|
||||
//???
|
||||
void bCPU::mmio_w43xb(uint8 value, uint8 i) {
|
||||
channel[i].hdma_unknown = value;
|
||||
}
|
||||
|
||||
void bCPU::mmio_write(uint16 addr, uint8 data) {
|
||||
//APU
|
||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||
port_write(addr & 3, data);
|
||||
return;
|
||||
}
|
||||
|
||||
//HDMA
|
||||
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
||||
uint i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
case 0x0: mmio_w43x0(data, i); return;
|
||||
case 0x1: mmio_w43x1(data, i); return;
|
||||
case 0x2: mmio_w43x2(data, i); return;
|
||||
case 0x3: mmio_w43x3(data, i); return;
|
||||
case 0x4: mmio_w43x4(data, i); return;
|
||||
case 0x5: mmio_w43x5(data, i); return;
|
||||
case 0x6: mmio_w43x6(data, i); return;
|
||||
case 0x7: mmio_w43x7(data, i); return;
|
||||
case 0x8: mmio_w43x8(data, i); return;
|
||||
case 0x9: mmio_w43x9(data, i); return;
|
||||
case 0xa: mmio_w43xa(data, i); return;
|
||||
case 0xb: mmio_w43xb(data, i); return;
|
||||
case 0xc: return; //unmapped
|
||||
case 0xd: return; //unmapped
|
||||
case 0xe: return; //unmapped
|
||||
case 0xf: mmio_w43xb(data, i); return; //mirror of 43xb
|
||||
}
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x2180: mmio_w2180(data); return; //WMDATA
|
||||
case 0x2181: mmio_w2181(data); return; //WMADDL
|
||||
case 0x2182: mmio_w2182(data); return; //WMADDM
|
||||
case 0x2183: mmio_w2183(data); return; //WMADDH
|
||||
case 0x4016: mmio_w4016(data); return; //JOYSER0
|
||||
case 0x4017: return; //unmapped
|
||||
case 0x4200: mmio_w4200(data); return; //NMITIMEN
|
||||
case 0x4201: mmio_w4201(data); return; //WRIO
|
||||
case 0x4202: mmio_w4202(data); return; //WRMPYA
|
||||
case 0x4203: mmio_w4203(data); return; //WRMPYB
|
||||
case 0x4204: mmio_w4204(data); return; //WRDIVL
|
||||
case 0x4205: mmio_w4205(data); return; //WRDIVH
|
||||
case 0x4206: mmio_w4206(data); return; //WRDIVB
|
||||
case 0x4207: mmio_w4207(data); return; //HTIMEL
|
||||
case 0x4208: mmio_w4208(data); return; //HTIMEH
|
||||
case 0x4209: mmio_w4209(data); return; //VTIMEL
|
||||
case 0x420a: mmio_w420a(data); return; //VTIMEH
|
||||
case 0x420b: mmio_w420b(data); return; //DMAEN
|
||||
case 0x420c: mmio_w420c(data); return; //HDMAEN
|
||||
case 0x420d: mmio_w420d(data); return; //MEMSEL
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#define CLASS_NAME "bCPU"
|
||||
#include "../../../lib/opgen.cpp"
|
||||
|
||||
int main() {
|
||||
fph = fopen("op.h", "wb");
|
||||
fpt = fopen("optable.cpp", "wb");
|
||||
|
||||
generate("op_read.cpp", "op_read.b");
|
||||
generate("op_rmw.cpp", "op_rmw.b");
|
||||
generate("op_write.cpp", "op_write.b");
|
||||
generate("op_pc.cpp", "op_pc.b");
|
||||
generate("op_misc.cpp", "op_misc.b");
|
||||
|
||||
fclose(fph);
|
||||
fclose(fpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
cl /O2 /wd4996 bcpugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
||||
@@ -1 +0,0 @@
|
||||
@del *.exe
|
||||
@@ -1,28 +0,0 @@
|
||||
#include "opfn.cpp"
|
||||
#include "op_read.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
|
||||
void bCPU::cpu_c2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::cpu_c6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
cpu_io();
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::init_op_tables() {
|
||||
#include "optable.cpp"
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/* External functions:
|
||||
* void last_cycle();
|
||||
* void cpu_io();
|
||||
* uint8 mem_read(uint32 addr);
|
||||
* void mem_write(uint32 addr, uint8 value);
|
||||
*/
|
||||
|
||||
void (bCPU::*optbl[256])();
|
||||
|
||||
CPUReg24 aa, rd;
|
||||
uint8 dp, sp;
|
||||
|
||||
//op_read
|
||||
inline void op_adc_b();
|
||||
inline void op_adc_w();
|
||||
inline void op_and_b();
|
||||
inline void op_and_w();
|
||||
inline void op_bit_b();
|
||||
inline void op_bit_w();
|
||||
inline void op_cmp_b();
|
||||
inline void op_cmp_w();
|
||||
inline void op_cpx_b();
|
||||
inline void op_cpx_w();
|
||||
inline void op_cpy_b();
|
||||
inline void op_cpy_w();
|
||||
inline void op_eor_b();
|
||||
inline void op_eor_w();
|
||||
inline void op_lda_b();
|
||||
inline void op_lda_w();
|
||||
inline void op_ldx_b();
|
||||
inline void op_ldx_w();
|
||||
inline void op_ldy_b();
|
||||
inline void op_ldy_w();
|
||||
inline void op_ora_b();
|
||||
inline void op_ora_w();
|
||||
inline void op_sbc_b();
|
||||
inline void op_sbc_w();
|
||||
//op_rmw
|
||||
inline void op_inc_b();
|
||||
inline void op_inc_w();
|
||||
inline void op_dec_b();
|
||||
inline void op_dec_w();
|
||||
inline void op_asl_b();
|
||||
inline void op_asl_w();
|
||||
inline void op_lsr_b();
|
||||
inline void op_lsr_w();
|
||||
inline void op_rol_b();
|
||||
inline void op_rol_w();
|
||||
inline void op_ror_b();
|
||||
inline void op_ror_w();
|
||||
inline void op_trb_b();
|
||||
inline void op_trb_w();
|
||||
inline void op_tsb_b();
|
||||
inline void op_tsb_w();
|
||||
|
||||
inline void cpu_c2();
|
||||
inline void cpu_c4(uint16 x, uint16 y);
|
||||
inline void cpu_c6(uint16 addr);
|
||||
|
||||
inline void init_op_tables();
|
||||
|
||||
#include "op.h"
|
||||
@@ -1,282 +0,0 @@
|
||||
nop(0xea) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
wdm(0x42) {
|
||||
1:last_cycle();
|
||||
op_readpc();
|
||||
}
|
||||
|
||||
xba(0xeb) {
|
||||
1:cpu_io();
|
||||
2:last_cycle();
|
||||
cpu_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
mvn(0x54, ++),
|
||||
mvp(0x44, --) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readpc();
|
||||
3:regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
4:op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
5:cpu_io();
|
||||
if(regs.p.x) { regs.x.l$1; regs.y.l$1; }
|
||||
else { regs.x.w$1; regs.y.w$1; }
|
||||
6:last_cycle();
|
||||
cpu_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
|
||||
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
||||
1:op_readpc();
|
||||
if(regs.e)skip;
|
||||
2:op_writestack(regs.pc.b);
|
||||
3:op_writestack(regs.pc.h);
|
||||
4:op_writestack(regs.pc.l);
|
||||
5:op_writestack(regs.p);
|
||||
6:rd.l = op_readlong((regs.e) ? $1 : $3);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
1:cpu_io();
|
||||
run_state.stp = true;
|
||||
2:last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w--;
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
1:cpu_io();
|
||||
run_state.wai = true;
|
||||
2:last_cycle();
|
||||
cpu_io();
|
||||
//no wakeup delay if last_cycle() cancelled wai
|
||||
if(run_state.wai == false)end;
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
//sleep another i/o cycle
|
||||
//note: this should alert the debugger that wai is continuing...
|
||||
if(run_state.wai == true)status.cycle_pos--;
|
||||
//wai wakeup delay (one i/o cycle)
|
||||
4:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
bool c = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
clc(0x18, regs.p.c = 0),
|
||||
cld(0xd8, regs.p.d = 0),
|
||||
cli(0x58, regs.p.i = 0),
|
||||
clv(0xb8, regs.p.v = 0),
|
||||
sec(0x38, regs.p.c = 1),
|
||||
sed(0xf8, regs.p.d = 1),
|
||||
sei(0x78, regs.p.i = 1) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
$1;
|
||||
}
|
||||
|
||||
rep(0xc2, &=~),
|
||||
sep(0xe2, |=) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
cpu_io();
|
||||
regs.p $1 rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
tax(0xaa, regs.p.x, x, a),
|
||||
tay(0xa8, regs.p.x, y, a),
|
||||
txa(0x8a, regs.p.m, a, x),
|
||||
txy(0x9b, regs.p.x, y, x),
|
||||
tya(0x98, regs.p.m, a, y),
|
||||
tyx(0xbb, regs.p.x, x, y) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if($1) {
|
||||
regs.$2.l = regs.$3.l;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w = regs.$3.w;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tcd(0x5b) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
tcs(0x1b) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
tdc(0x7b) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
tsc(0x3b) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tsx(0xba) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
txs(0x9a) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
}
|
||||
|
||||
pha(0x48, regs.p.m, a),
|
||||
phx(0xda, regs.p.x, x),
|
||||
phy(0x5a, regs.p.x, y),
|
||||
phd(0x0b, 0, d) {
|
||||
1:cpu_io();
|
||||
if($1)skip;
|
||||
2:op_writestack(regs.$2.h);
|
||||
3:last_cycle();
|
||||
op_writestack(regs.$2.l);
|
||||
}
|
||||
|
||||
phb(0x8b, regs.db),
|
||||
phk(0x4b, regs.pc.b),
|
||||
php(0x08, regs.p) {
|
||||
1:cpu_io();
|
||||
2:last_cycle();
|
||||
op_writestack($1);
|
||||
}
|
||||
|
||||
pla(0x68, regs.p.m, a),
|
||||
plx(0xfa, regs.p.x, x),
|
||||
ply(0x7a, regs.p.x, y),
|
||||
pld(0x2b, 0, d) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:if($1)last_cycle();
|
||||
regs.$2.l = op_readstack();
|
||||
if($1) {
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
end;
|
||||
}
|
||||
4:last_cycle();
|
||||
regs.$2.h = op_readstack();
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
|
||||
plb(0xab) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
plp(0x28) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
pea(0xf4) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestack(aa.h);
|
||||
4:last_cycle();
|
||||
op_writestack(aa.l);
|
||||
}
|
||||
|
||||
pei(0xd4) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_writestack(aa.h);
|
||||
6:last_cycle();
|
||||
op_writestack(aa.l);
|
||||
}
|
||||
|
||||
per(0x62) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
4:op_writestack(rd.h);
|
||||
5:last_cycle();
|
||||
op_writestack(rd.l);
|
||||
}
|
||||
@@ -1,864 +0,0 @@
|
||||
void bCPU::op_nop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_wdm() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
op_readpc();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_xba() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_mvn() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
sp = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
} break;
|
||||
case 4: {
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_io();
|
||||
if(regs.p.x) { regs.x.l++; regs.y.l++; }
|
||||
else { regs.x.w++; regs.y.w++; }
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_mvp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
sp = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
} break;
|
||||
case 4: {
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_io();
|
||||
if(regs.p.x) { regs.x.l--; regs.y.l--; }
|
||||
else { regs.x.w--; regs.y.w--; }
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_brk() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
op_readpc();
|
||||
if(regs.e)status.cycle_pos++;
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
case 3: {
|
||||
op_writestack(regs.pc.h);
|
||||
} break;
|
||||
case 4: {
|
||||
op_writestack(regs.pc.l);
|
||||
} break;
|
||||
case 5: {
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
case 6: {
|
||||
rd.l = op_readlong((regs.e) ? 0xfffe : 0xffe6);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_cop() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
op_readpc();
|
||||
if(regs.e)status.cycle_pos++;
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
case 3: {
|
||||
op_writestack(regs.pc.h);
|
||||
} break;
|
||||
case 4: {
|
||||
op_writestack(regs.pc.l);
|
||||
} break;
|
||||
case 5: {
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
case 6: {
|
||||
rd.l = op_readlong((regs.e) ? 0xfff4 : 0xffe4);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
run_state.stp = true;
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w--;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_wai() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
run_state.wai = true;
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
//no wakeup delay if last_cycle() cancelled wai
|
||||
if(run_state.wai == false)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
//sleep another i/o cycle
|
||||
//note: this should alert the debugger that wai is continuing...
|
||||
if(run_state.wai == true)status.cycle_pos--;
|
||||
//wai wakeup delay (one i/o cycle)
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_xce() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
bool c = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_clc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.c = 0;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_cld() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.d = 0;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_cli() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.i = 0;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_clv() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.v = 0;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sec() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.c = 1;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sed() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.d = 1;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sei() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p.i = 1;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rep() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
rd.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p &=~ rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sep() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
rd.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.p |= rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tax() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.a.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tay() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.a.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_txa() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.x.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_txy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.x.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tya() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.y.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tyx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.y.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tcd() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tcs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tdc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tsc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_tsx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_txs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pha() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
if(regs.p.m)status.cycle_pos++;
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs.a.h);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
op_writestack(regs.a.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
if(regs.p.x)status.cycle_pos++;
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs.x.h);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
op_writestack(regs.x.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
if(regs.p.x)status.cycle_pos++;
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs.y.h);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
op_writestack(regs.y.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phd() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
if(0)status.cycle_pos++;
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs. d.h);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
op_writestack(regs. d.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phb() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
op_writestack(regs.db);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_phk() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.b);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_php() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
op_writestack(regs.p);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pla() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
regs.a.l = op_readstack();
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
regs.a.h = op_readstack();
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_plx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.x.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
regs.x.h = op_readstack();
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_ply() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.y.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
regs.y.h = op_readstack();
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pld() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
if(0)last_cycle();
|
||||
regs. d.l = op_readstack();
|
||||
if(0) {
|
||||
regs.p.n = !!(regs. d.l & 0x80);
|
||||
regs.p.z = (regs. d.l == 0);
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
regs. d.h = op_readstack();
|
||||
regs.p.n = !!(regs. d.w & 0x8000);
|
||||
regs.p.z = (regs. d.w == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_plb() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_plp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pea() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
op_writestack(aa.h);
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writestack(aa.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_pei() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_readdp(dp);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readdp(dp + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
op_writestack(aa.h);
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
op_writestack(aa.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_per() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
} break;
|
||||
case 4: {
|
||||
op_writestack(rd.h);
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writestack(rd.l);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
bcc(0x90, !regs.p.c),
|
||||
bcs(0xb0, regs.p.c),
|
||||
bne(0xd0, !regs.p.z),
|
||||
beq(0xf0, regs.p.z),
|
||||
bpl(0x10, !regs.p.n),
|
||||
bmi(0x30, regs.p.n),
|
||||
bvc(0x50, !regs.p.v),
|
||||
bvs(0x70, regs.p.v) {
|
||||
1:if(!$1)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($1) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
end;
|
||||
}
|
||||
2:cpu_c6(aa.w);
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
bra(0x80) {
|
||||
1:rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
2:cpu_c6(aa.w);
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
}
|
||||
|
||||
brl(0x82) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
jmp_addr(0x4c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_long(0x5c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jmp_iaddr(0x6c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x7c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_io();
|
||||
4:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
5:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iladdr(0xdc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:rd.h = op_readaddr(aa.w + 1);
|
||||
5:last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_addr(0x20) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_io();
|
||||
4:regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
5:last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
jsr_long(0x22) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestack(regs.pc.b);
|
||||
4:cpu_io();
|
||||
5:aa.b = op_readpc();
|
||||
6:regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
7:last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:op_writestack(regs.pc.h);
|
||||
3:op_writestack(regs.pc.l);
|
||||
4:aa.h = op_readpc();
|
||||
5:cpu_io();
|
||||
6:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
7:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = op_readstack();
|
||||
5:if(regs.e)last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
}
|
||||
6:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
rts(0x60) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:rd.l = op_readstack();
|
||||
4:rd.h = op_readstack();
|
||||
5:last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
rtl(0x6b) {
|
||||
1:cpu_io();
|
||||
2:cpu_io();
|
||||
3:rd.l = op_readstack();
|
||||
4:rd.h = op_readstack();
|
||||
5:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
}
|
||||
@@ -1,483 +0,0 @@
|
||||
void bCPU::op_bcc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!!regs.p.c)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bcs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!regs.p.c)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bne() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!!regs.p.z)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_beq() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!regs.p.z)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bpl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!!regs.p.n)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bmi() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!regs.p.n)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bvc() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!!regs.p.v)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bvs() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
if(!regs.p.v)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_bra() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c6(aa.w);
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_brl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
rd.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
rd.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
rd.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
rd.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
rd.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iaddr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = op_readaddr(aa.w);
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iaddrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jmp_iladdr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = op_readaddr(aa.w);
|
||||
} break;
|
||||
case 4: {
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
case 4: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 5: {
|
||||
aa.b = op_readpc();
|
||||
} break;
|
||||
case 6: {
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_jsr_iaddrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
op_writestack(regs.pc.h);
|
||||
} break;
|
||||
case 3: {
|
||||
op_writestack(regs.pc.l);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 6: {
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rti() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
case 4: {
|
||||
rd.l = op_readstack();
|
||||
} break;
|
||||
case 5: {
|
||||
if(regs.e)last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
status.cycle_pos = 0;
|
||||
}
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rts() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = op_readstack();
|
||||
} break;
|
||||
case 4: {
|
||||
rd.h = op_readstack();
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
cpu_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_rtl() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
rd.l = op_readstack();
|
||||
} break;
|
||||
case 4: {
|
||||
rd.h = op_readstack();
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
adc_const(0x69, adc, regs.p.m),
|
||||
and_const(0x29, and, regs.p.m),
|
||||
cmp_const(0xc9, cmp, regs.p.m),
|
||||
cpx_const(0xe0, cpx, regs.p.x),
|
||||
cpy_const(0xc0, cpy, regs.p.x),
|
||||
eor_const(0x49, eor, regs.p.m),
|
||||
lda_const(0xa9, lda, regs.p.m),
|
||||
ldx_const(0xa2, ldx, regs.p.x),
|
||||
ldy_const(0xa0, ldy, regs.p.x),
|
||||
ora_const(0x09, ora, regs.p.m),
|
||||
sbc_const(0xe9, sbc, regs.p.m) {
|
||||
1:if($2)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($2) { op_$1_b(); end; }
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addr(0x6d, adc, regs.p.m),
|
||||
and_addr(0x2d, and, regs.p.m),
|
||||
bit_addr(0x2c, bit, regs.p.m),
|
||||
cmp_addr(0xcd, cmp, regs.p.m),
|
||||
cpx_addr(0xec, cpx, regs.p.x),
|
||||
cpy_addr(0xcc, cpy, regs.p.x),
|
||||
eor_addr(0x4d, eor, regs.p.m),
|
||||
lda_addr(0xad, lda, regs.p.m),
|
||||
ldx_addr(0xae, ldx, regs.p.x),
|
||||
ldy_addr(0xac, ldy, regs.p.x),
|
||||
ora_addr(0x0d, ora, regs.p.m),
|
||||
sbc_addr(0xed, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($2)last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addrx(0x7d, adc, regs.p.m),
|
||||
and_addrx(0x3d, and, regs.p.m),
|
||||
bit_addrx(0x3c, bit, regs.p.m),
|
||||
cmp_addrx(0xdd, cmp, regs.p.m),
|
||||
eor_addrx(0x5d, eor, regs.p.m),
|
||||
lda_addrx(0xbd, lda, regs.p.m),
|
||||
ldy_addrx(0xbc, ldy, regs.p.x),
|
||||
ora_addrx(0x1d, ora, regs.p.m),
|
||||
sbc_addrx(0xfd, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
4:if($2)last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addry(0x79, adc, regs.p.m),
|
||||
and_addry(0x39, and, regs.p.m),
|
||||
cmp_addry(0xd9, cmp, regs.p.m),
|
||||
eor_addry(0x59, eor, regs.p.m),
|
||||
lda_addry(0xb9, lda, regs.p.m),
|
||||
ldx_addry(0xbe, ldx, regs.p.x),
|
||||
ora_addry(0x19, ora, regs.p.m),
|
||||
sbc_addry(0xf9, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
4:if($2)last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_long(0x6f, adc, regs.p.m),
|
||||
and_long(0x2f, and, regs.p.m),
|
||||
cmp_long(0xcf, cmp, regs.p.m),
|
||||
eor_long(0x4f, eor, regs.p.m),
|
||||
lda_long(0xaf, lda, regs.p.m),
|
||||
ora_long(0x0f, ora, regs.p.m),
|
||||
sbc_long(0xef, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2)last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_longx(0x7f, adc, regs.p.m),
|
||||
and_longx(0x3f, and, regs.p.m),
|
||||
cmp_longx(0xdf, cmp, regs.p.m),
|
||||
eor_longx(0x5f, eor, regs.p.m),
|
||||
lda_longx(0xbf, lda, regs.p.m),
|
||||
ora_longx(0x1f, ora, regs.p.m),
|
||||
sbc_longx(0xff, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2)last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dp(0x65, adc, regs.p.m),
|
||||
and_dp(0x25, and, regs.p.m),
|
||||
bit_dp(0x24, bit, regs.p.m),
|
||||
cmp_dp(0xc5, cmp, regs.p.m),
|
||||
cpx_dp(0xe4, cpx, regs.p.x),
|
||||
cpy_dp(0xc4, cpy, regs.p.x),
|
||||
eor_dp(0x45, eor, regs.p.m),
|
||||
lda_dp(0xa5, lda, regs.p.m),
|
||||
ldx_dp(0xa6, ldx, regs.p.x),
|
||||
ldy_dp(0xa4, ldy, regs.p.x),
|
||||
ora_dp(0x05, ora, regs.p.m),
|
||||
sbc_dp(0xe5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:if($2)last_cycle();
|
||||
rd.l = op_readdp(dp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dpx(0x75, adc, regs.p.m),
|
||||
and_dpx(0x35, and, regs.p.m),
|
||||
bit_dpx(0x34, bit, regs.p.m),
|
||||
cmp_dpx(0xd5, cmp, regs.p.m),
|
||||
eor_dpx(0x55, eor, regs.p.m),
|
||||
lda_dpx(0xb5, lda, regs.p.m),
|
||||
ldy_dpx(0xb4, ldy, regs.p.x),
|
||||
ora_dpx(0x15, ora, regs.p.m),
|
||||
sbc_dpx(0xf5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:if($2)last_cycle();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
ldx_dpy(0xb6, ldx, regs.p.x) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:if($2)last_cycle();
|
||||
rd.l = op_readdp(dp + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idp(0x72, adc, regs.p.m),
|
||||
and_idp(0x32, and, regs.p.m),
|
||||
cmp_idp(0xd2, cmp, regs.p.m),
|
||||
eor_idp(0x52, eor, regs.p.m),
|
||||
lda_idp(0xb2, lda, regs.p.m),
|
||||
ora_idp(0x12, ora, regs.p.m),
|
||||
sbc_idp(0xf2, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if($2)last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
6:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpx(0x61, adc, regs.p.m),
|
||||
and_idpx(0x21, and, regs.p.m),
|
||||
cmp_idpx(0xc1, cmp, regs.p.m),
|
||||
eor_idpx(0x41, eor, regs.p.m),
|
||||
lda_idpx(0xa1, lda, regs.p.m),
|
||||
ora_idpx(0x01, ora, regs.p.m),
|
||||
sbc_idpx(0xe1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:aa.l = op_readdp(dp + regs.x.w);
|
||||
5:aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:if($2)last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpy(0x71, adc, regs.p.m),
|
||||
and_idpy(0x31, and, regs.p.m),
|
||||
cmp_idpy(0xd1, cmp, regs.p.m),
|
||||
eor_idpy(0x51, eor, regs.p.m),
|
||||
lda_idpy(0xb1, lda, regs.p.m),
|
||||
ora_idpy(0x11, ora, regs.p.m),
|
||||
sbc_idpy(0xf1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
6:if($2)last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildp(0x67, adc, regs.p.m),
|
||||
and_ildp(0x27, and, regs.p.m),
|
||||
cmp_ildp(0xc7, cmp, regs.p.m),
|
||||
eor_ildp(0x47, eor, regs.p.m),
|
||||
lda_ildp(0xa7, lda, regs.p.m),
|
||||
ora_ildp(0x07, ora, regs.p.m),
|
||||
sbc_ildp(0xe7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2)last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildpy(0x77, adc, regs.p.m),
|
||||
and_ildpy(0x37, and, regs.p.m),
|
||||
cmp_ildpy(0xd7, cmp, regs.p.m),
|
||||
eor_ildpy(0x57, eor, regs.p.m),
|
||||
lda_ildpy(0xb7, lda, regs.p.m),
|
||||
ora_ildpy(0x17, ora, regs.p.m),
|
||||
sbc_ildpy(0xf7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2)last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_sr(0x63, adc, regs.p.m),
|
||||
and_sr(0x23, and, regs.p.m),
|
||||
cmp_sr(0xc3, cmp, regs.p.m),
|
||||
eor_sr(0x43, eor, regs.p.m),
|
||||
lda_sr(0xa3, lda, regs.p.m),
|
||||
ora_sr(0x03, ora, regs.p.m),
|
||||
sbc_sr(0xe3, sbc, regs.p.m) {
|
||||
1:sp = op_readpc();
|
||||
2:cpu_io();
|
||||
3:if($2)last_cycle();
|
||||
rd.l = op_readsp(sp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readsp(sp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_isry(0x73, adc),
|
||||
and_isry(0x33, and),
|
||||
cmp_isry(0xd3, cmp),
|
||||
eor_isry(0x53, eor),
|
||||
lda_isry(0xb3, lda),
|
||||
ora_isry(0x13, ora),
|
||||
sbc_isry(0xf3, sbc) {
|
||||
1:sp = op_readpc();
|
||||
2:cpu_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:cpu_io();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if(regs.p.m) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
bit_const(0x89) {
|
||||
1:if(regs.p.m)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.m) {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
end;
|
||||
}
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,185 +0,0 @@
|
||||
inc(0x1a, regs.p.m, a),
|
||||
inx(0xe8, regs.p.x, x),
|
||||
iny(0xc8, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w++;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
dec(0x3a, regs.p.m, a),
|
||||
dex(0xca, regs.p.x, x),
|
||||
dey(0x88, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w--;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
asl(0x0a) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
lsr(0x4a) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
rol(0x2a) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
ror(0x6a) {
|
||||
1:last_cycle();
|
||||
cpu_io();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = (regs.p.c)?0x80:0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
inc_addr(0xee, inc),
|
||||
dec_addr(0xce, dec),
|
||||
asl_addr(0x0e, asl),
|
||||
lsr_addr(0x4e, lsr),
|
||||
rol_addr(0x2e, rol),
|
||||
ror_addr(0x6e, ror),
|
||||
trb_addr(0x1c, trb),
|
||||
tsb_addr(0x0c, tsb) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readdbr(aa.w);
|
||||
if(regs.p.m)skip;
|
||||
4:rd.h = op_readdbr(aa.w + 1);
|
||||
5:cpu_io();
|
||||
if(regs.p.m) { op_$1_b(); skip; }
|
||||
else op_$1_w();
|
||||
6:op_writedbr(aa.w + 1, rd.h);
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
inc_addrx(0xfe, inc),
|
||||
dec_addrx(0xde, dec),
|
||||
asl_addrx(0x1e, asl),
|
||||
lsr_addrx(0x5e, lsr),
|
||||
rol_addrx(0x3e, rol),
|
||||
ror_addrx(0x7e, ror) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_io();
|
||||
4:rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(regs.p.m)skip;
|
||||
5:rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
6:cpu_io();
|
||||
if(regs.p.m) { op_$1_b(); skip; }
|
||||
else op_$1_w();
|
||||
7:op_writedbr(aa.w + regs.x.w + 1, rd.h);
|
||||
8:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
inc_dp(0xe6, inc),
|
||||
dec_dp(0xc6, dec),
|
||||
asl_dp(0x06, asl),
|
||||
lsr_dp(0x46, lsr),
|
||||
rol_dp(0x26, rol),
|
||||
ror_dp(0x66, ror),
|
||||
trb_dp(0x14, trb),
|
||||
tsb_dp(0x04, tsb) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:rd.l = op_readdp(dp);
|
||||
if(regs.p.m)skip;
|
||||
4:rd.h = op_readdp(dp + 1);
|
||||
5:cpu_io();
|
||||
if(regs.p.m) { op_$1_b(); skip; }
|
||||
else op_$1_w();
|
||||
6:op_writedp(dp + 1, rd.h);
|
||||
7:last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
inc_dpx(0xf6, inc),
|
||||
dec_dpx(0xd6, dec),
|
||||
asl_dpx(0x16, asl),
|
||||
lsr_dpx(0x56, lsr),
|
||||
rol_dpx(0x36, rol),
|
||||
ror_dpx(0x76, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:rd.l = op_readdp(dp + regs.x.w);
|
||||
if(regs.p.m)skip;
|
||||
5:rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:cpu_io();
|
||||
if(regs.p.m) { op_$1_b(); skip; }
|
||||
else op_$1_w();
|
||||
7:op_writedp(dp + regs.x.w + 1, rd.h);
|
||||
8:last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,181 +0,0 @@
|
||||
sta_addr(0x8d, regs.p.m, regs.a.w),
|
||||
stx_addr(0x8e, regs.p.x, regs.x.w),
|
||||
sty_addr(0x8c, regs.p.x, regs.y.w),
|
||||
stz_addr(0x9c, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($1)last_cycle();
|
||||
op_writedbr(aa.w, $2);
|
||||
if($1)end;
|
||||
4:last_cycle();
|
||||
op_writedbr(aa.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addrx(0x9d, regs.p.m, regs.a.w),
|
||||
stz_addrx(0x9e, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_io();
|
||||
4:if($1)last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, $2);
|
||||
if($1)end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addry(0x99) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:cpu_io();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_long(0x8f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_longx(0x9f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_dp(0x85, regs.p.m, regs.a.w),
|
||||
stx_dp(0x86, regs.p.x, regs.x.w),
|
||||
sty_dp(0x84, regs.p.x, regs.y.w),
|
||||
stz_dp(0x64, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:if($1)last_cycle();
|
||||
op_writedp(dp, $2);
|
||||
if($1)end;
|
||||
4:last_cycle();
|
||||
op_writedp(dp + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_dpx(0x95, regs.p.m, regs.a.w),
|
||||
sty_dpx(0x94, regs.p.x, regs.y.w),
|
||||
stz_dpx(0x74, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:if($1)last_cycle();
|
||||
op_writedp(dp + regs.x.w, $2);
|
||||
if($1)end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
stx_dpy(0x96) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:if(regs.p.x)last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x)end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
}
|
||||
|
||||
sta_idp(0x92) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
6:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_ildp(0x87) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_idpx(0x81) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:cpu_io();
|
||||
4:aa.l = op_readdp(dp + regs.x.w);
|
||||
5:aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_idpy(0x91) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:cpu_io();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_ildpy(0x97) {
|
||||
1:dp = op_readpc();
|
||||
2:cpu_c2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_sr(0x83) {
|
||||
1:sp = op_readpc();
|
||||
2:cpu_io();
|
||||
3:if(regs.p.m)last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
4:last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_isry(0x93) {
|
||||
1:sp = op_readpc();
|
||||
2:cpu_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:cpu_io();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -1,582 +0,0 @@
|
||||
void bCPU::op_sta_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedbr(aa.w, regs.x.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.x.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedbr(aa.w, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_addr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_addrx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_c4(aa.w, aa.w + regs.x.w);
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_addry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_long() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.b = op_readpc();
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_longx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
aa.l = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
aa.h = op_readpc();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.b = op_readpc();
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp, regs.x.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.x.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_dp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sty_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.y.w);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stz_dpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp + regs.x.w, 0x0000);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_stx_dpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 5: {
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_readdp(dp);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readdp(dp + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 6: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildp() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_readdp(dp);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readdp(dp + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
aa.b = op_readdp(dp + 2);
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpx() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 4: {
|
||||
aa.l = op_readdp(dp + regs.x.w);
|
||||
} break;
|
||||
case 5: {
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_idpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_readdp(dp);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readdp(dp + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_c4(aa.w, aa.w + regs.y.w);
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_ildpy() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
dp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_c2();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_readdp(dp);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readdp(dp + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
aa.b = op_readdp(dp + 2);
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_sr() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
sp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 4: {
|
||||
last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::op_sta_isry() {
|
||||
switch(status.cycle_pos++) {
|
||||
case 1: {
|
||||
sp = op_readpc();
|
||||
} break;
|
||||
case 2: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 3: {
|
||||
aa.l = op_readsp(sp);
|
||||
} break;
|
||||
case 4: {
|
||||
aa.h = op_readsp(sp + 1);
|
||||
} break;
|
||||
case 5: {
|
||||
cpu_io();
|
||||
} break;
|
||||
case 6: {
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)status.cycle_pos = 0;
|
||||
} break;
|
||||
case 7: {
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
status.cycle_pos = 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,377 +0,0 @@
|
||||
//op_read
|
||||
inline void bCPU::op_adc_b() {
|
||||
int32 r = regs.a.l + rd.l + regs.p.c;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||
n0 += ((rd.l) & 15) + regs.p.c;
|
||||
if(n0 > 9) {
|
||||
n0 -= 10;
|
||||
n0 &= 15;
|
||||
n1++;
|
||||
}
|
||||
n1 += ((rd.l >> 4) & 15);
|
||||
if(n1 > 9) {
|
||||
n1 -= 10;
|
||||
n1 &= 15;
|
||||
regs.p.c = 1;
|
||||
} else {
|
||||
regs.p.c = 0;
|
||||
}
|
||||
r = (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.l + rd.l + regs.p.c;
|
||||
regs.p.c = (r > 0xff);
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_adc_w() {
|
||||
int32 r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||
uint8 n2 = (regs.a.w >> 8) & 15;
|
||||
uint8 n3 = (regs.a.w >> 12) & 15;
|
||||
n0 += ((rd.w) & 15) + regs.p.c;
|
||||
if(n0 > 9) {
|
||||
n0 -= 10;
|
||||
n0 &= 15;
|
||||
n1++;
|
||||
}
|
||||
n1 += ((rd.w >> 4) & 15);
|
||||
if(n1 > 9) {
|
||||
n1 -= 10;
|
||||
n1 &= 15;
|
||||
n2++;
|
||||
}
|
||||
n2 += ((rd.w >> 8) & 15);
|
||||
if(n2 > 9) {
|
||||
n2 -= 10;
|
||||
n2 &= 15;
|
||||
n3++;
|
||||
}
|
||||
n3 += ((rd.w >> 12) & 15);
|
||||
if(n3 > 9) {
|
||||
n3 -= 10;
|
||||
n3 &= 15;
|
||||
regs.p.c = 1;
|
||||
} else {
|
||||
regs.p.c = 0;
|
||||
}
|
||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.w + rd.w + regs.p.c;
|
||||
regs.p.c = (r > 0xffff);
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_and_b() {
|
||||
regs.a.l &= rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_and_w() {
|
||||
regs.a.w &= rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_bit_b() {
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.v = !!(rd.l & 0x40);
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_bit_w() {
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.v = !!(rd.w & 0x4000);
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_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);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cmp_w() {
|
||||
int32 r = regs.a.w - rd.w;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_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);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cpx_w() {
|
||||
int32 r = regs.x.w - rd.w;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_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);
|
||||
}
|
||||
|
||||
inline void bCPU::op_cpy_w() {
|
||||
int32 r = regs.y.w - rd.w;
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_eor_b() {
|
||||
regs.a.l ^= rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_eor_w() {
|
||||
regs.a.w ^= rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lda_b() {
|
||||
regs.a.l = rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lda_w() {
|
||||
regs.a.w = rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldx_b() {
|
||||
regs.x.l = rd.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldx_w() {
|
||||
regs.x.w = rd.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldy_b() {
|
||||
regs.y.l = rd.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ldy_w() {
|
||||
regs.y.w = rd.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ora_b() {
|
||||
regs.a.l |= rd.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ora_w() {
|
||||
regs.a.w |= rd.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_sbc_b() {
|
||||
int32 r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||
n0 -= ((rd.l ) & 15) + !regs.p.c;
|
||||
n1 -= ((rd.l >> 4) & 15);
|
||||
if(n0 > 9) {
|
||||
n0 += 10;
|
||||
n1--;
|
||||
}
|
||||
if(n1 > 9) {
|
||||
n1 += 10;
|
||||
regs.p.c = 0;
|
||||
} else {
|
||||
regs.p.c = 1;
|
||||
}
|
||||
r = (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.l - rd.l - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.a.l = r;
|
||||
}
|
||||
|
||||
inline void bCPU::op_sbc_w() {
|
||||
int32 r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||
uint8 n2 = (regs.a.w >> 8) & 15;
|
||||
uint8 n3 = (regs.a.w >> 12) & 15;
|
||||
n0 -= ((rd.w ) & 15) + !regs.p.c;
|
||||
n1 -= ((rd.w >> 4) & 15);
|
||||
n2 -= ((rd.w >> 8) & 15);
|
||||
n3 -= ((rd.w >> 12) & 15);
|
||||
if(n0 > 9) {
|
||||
n0 += 10;
|
||||
n1--;
|
||||
}
|
||||
if(n1 > 9) {
|
||||
n1 += 10;
|
||||
n2--;
|
||||
}
|
||||
if(n2 > 9) {
|
||||
n2 += 10;
|
||||
n3--;
|
||||
}
|
||||
if(n3 > 9) {
|
||||
n3 += 10;
|
||||
regs.p.c = 0;
|
||||
} else {
|
||||
regs.p.c = 1;
|
||||
}
|
||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.w - rd.w - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
//op_rmw
|
||||
inline void bCPU::op_inc_b() {
|
||||
rd.l++;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_inc_w() {
|
||||
rd.w++;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_dec_b() {
|
||||
rd.l--;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_dec_w() {
|
||||
rd.w--;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_asl_b() {
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_asl_w() {
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lsr_b() {
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_lsr_w() {
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_rol_b() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_rol_w() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ror_b() {
|
||||
uint16 c = (regs.p.c)?0x80:0;
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_ror_w() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void bCPU::op_trb_b() {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
rd.l &= ~regs.a.l;
|
||||
}
|
||||
|
||||
inline void bCPU::op_trb_w() {
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
rd.w &= ~regs.a.w;
|
||||
}
|
||||
|
||||
inline void bCPU::op_tsb_b() {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
rd.l |= regs.a.l;
|
||||
}
|
||||
|
||||
inline void bCPU::op_tsb_w() {
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
rd.w |= regs.a.w;
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
optbl[0x69] = &bCPU::op_adc_const;
|
||||
optbl[0x29] = &bCPU::op_and_const;
|
||||
optbl[0xc9] = &bCPU::op_cmp_const;
|
||||
optbl[0xe0] = &bCPU::op_cpx_const;
|
||||
optbl[0xc0] = &bCPU::op_cpy_const;
|
||||
optbl[0x49] = &bCPU::op_eor_const;
|
||||
optbl[0xa9] = &bCPU::op_lda_const;
|
||||
optbl[0xa2] = &bCPU::op_ldx_const;
|
||||
optbl[0xa0] = &bCPU::op_ldy_const;
|
||||
optbl[0x09] = &bCPU::op_ora_const;
|
||||
optbl[0xe9] = &bCPU::op_sbc_const;
|
||||
optbl[0x6d] = &bCPU::op_adc_addr;
|
||||
optbl[0x2d] = &bCPU::op_and_addr;
|
||||
optbl[0x2c] = &bCPU::op_bit_addr;
|
||||
optbl[0xcd] = &bCPU::op_cmp_addr;
|
||||
optbl[0xec] = &bCPU::op_cpx_addr;
|
||||
optbl[0xcc] = &bCPU::op_cpy_addr;
|
||||
optbl[0x4d] = &bCPU::op_eor_addr;
|
||||
optbl[0xad] = &bCPU::op_lda_addr;
|
||||
optbl[0xae] = &bCPU::op_ldx_addr;
|
||||
optbl[0xac] = &bCPU::op_ldy_addr;
|
||||
optbl[0x0d] = &bCPU::op_ora_addr;
|
||||
optbl[0xed] = &bCPU::op_sbc_addr;
|
||||
optbl[0x7d] = &bCPU::op_adc_addrx;
|
||||
optbl[0x3d] = &bCPU::op_and_addrx;
|
||||
optbl[0x3c] = &bCPU::op_bit_addrx;
|
||||
optbl[0xdd] = &bCPU::op_cmp_addrx;
|
||||
optbl[0x5d] = &bCPU::op_eor_addrx;
|
||||
optbl[0xbd] = &bCPU::op_lda_addrx;
|
||||
optbl[0xbc] = &bCPU::op_ldy_addrx;
|
||||
optbl[0x1d] = &bCPU::op_ora_addrx;
|
||||
optbl[0xfd] = &bCPU::op_sbc_addrx;
|
||||
optbl[0x79] = &bCPU::op_adc_addry;
|
||||
optbl[0x39] = &bCPU::op_and_addry;
|
||||
optbl[0xd9] = &bCPU::op_cmp_addry;
|
||||
optbl[0x59] = &bCPU::op_eor_addry;
|
||||
optbl[0xb9] = &bCPU::op_lda_addry;
|
||||
optbl[0xbe] = &bCPU::op_ldx_addry;
|
||||
optbl[0x19] = &bCPU::op_ora_addry;
|
||||
optbl[0xf9] = &bCPU::op_sbc_addry;
|
||||
optbl[0x6f] = &bCPU::op_adc_long;
|
||||
optbl[0x2f] = &bCPU::op_and_long;
|
||||
optbl[0xcf] = &bCPU::op_cmp_long;
|
||||
optbl[0x4f] = &bCPU::op_eor_long;
|
||||
optbl[0xaf] = &bCPU::op_lda_long;
|
||||
optbl[0x0f] = &bCPU::op_ora_long;
|
||||
optbl[0xef] = &bCPU::op_sbc_long;
|
||||
optbl[0x7f] = &bCPU::op_adc_longx;
|
||||
optbl[0x3f] = &bCPU::op_and_longx;
|
||||
optbl[0xdf] = &bCPU::op_cmp_longx;
|
||||
optbl[0x5f] = &bCPU::op_eor_longx;
|
||||
optbl[0xbf] = &bCPU::op_lda_longx;
|
||||
optbl[0x1f] = &bCPU::op_ora_longx;
|
||||
optbl[0xff] = &bCPU::op_sbc_longx;
|
||||
optbl[0x65] = &bCPU::op_adc_dp;
|
||||
optbl[0x25] = &bCPU::op_and_dp;
|
||||
optbl[0x24] = &bCPU::op_bit_dp;
|
||||
optbl[0xc5] = &bCPU::op_cmp_dp;
|
||||
optbl[0xe4] = &bCPU::op_cpx_dp;
|
||||
optbl[0xc4] = &bCPU::op_cpy_dp;
|
||||
optbl[0x45] = &bCPU::op_eor_dp;
|
||||
optbl[0xa5] = &bCPU::op_lda_dp;
|
||||
optbl[0xa6] = &bCPU::op_ldx_dp;
|
||||
optbl[0xa4] = &bCPU::op_ldy_dp;
|
||||
optbl[0x05] = &bCPU::op_ora_dp;
|
||||
optbl[0xe5] = &bCPU::op_sbc_dp;
|
||||
optbl[0x75] = &bCPU::op_adc_dpx;
|
||||
optbl[0x35] = &bCPU::op_and_dpx;
|
||||
optbl[0x34] = &bCPU::op_bit_dpx;
|
||||
optbl[0xd5] = &bCPU::op_cmp_dpx;
|
||||
optbl[0x55] = &bCPU::op_eor_dpx;
|
||||
optbl[0xb5] = &bCPU::op_lda_dpx;
|
||||
optbl[0xb4] = &bCPU::op_ldy_dpx;
|
||||
optbl[0x15] = &bCPU::op_ora_dpx;
|
||||
optbl[0xf5] = &bCPU::op_sbc_dpx;
|
||||
optbl[0xb6] = &bCPU::op_ldx_dpy;
|
||||
optbl[0x72] = &bCPU::op_adc_idp;
|
||||
optbl[0x32] = &bCPU::op_and_idp;
|
||||
optbl[0xd2] = &bCPU::op_cmp_idp;
|
||||
optbl[0x52] = &bCPU::op_eor_idp;
|
||||
optbl[0xb2] = &bCPU::op_lda_idp;
|
||||
optbl[0x12] = &bCPU::op_ora_idp;
|
||||
optbl[0xf2] = &bCPU::op_sbc_idp;
|
||||
optbl[0x61] = &bCPU::op_adc_idpx;
|
||||
optbl[0x21] = &bCPU::op_and_idpx;
|
||||
optbl[0xc1] = &bCPU::op_cmp_idpx;
|
||||
optbl[0x41] = &bCPU::op_eor_idpx;
|
||||
optbl[0xa1] = &bCPU::op_lda_idpx;
|
||||
optbl[0x01] = &bCPU::op_ora_idpx;
|
||||
optbl[0xe1] = &bCPU::op_sbc_idpx;
|
||||
optbl[0x71] = &bCPU::op_adc_idpy;
|
||||
optbl[0x31] = &bCPU::op_and_idpy;
|
||||
optbl[0xd1] = &bCPU::op_cmp_idpy;
|
||||
optbl[0x51] = &bCPU::op_eor_idpy;
|
||||
optbl[0xb1] = &bCPU::op_lda_idpy;
|
||||
optbl[0x11] = &bCPU::op_ora_idpy;
|
||||
optbl[0xf1] = &bCPU::op_sbc_idpy;
|
||||
optbl[0x67] = &bCPU::op_adc_ildp;
|
||||
optbl[0x27] = &bCPU::op_and_ildp;
|
||||
optbl[0xc7] = &bCPU::op_cmp_ildp;
|
||||
optbl[0x47] = &bCPU::op_eor_ildp;
|
||||
optbl[0xa7] = &bCPU::op_lda_ildp;
|
||||
optbl[0x07] = &bCPU::op_ora_ildp;
|
||||
optbl[0xe7] = &bCPU::op_sbc_ildp;
|
||||
optbl[0x77] = &bCPU::op_adc_ildpy;
|
||||
optbl[0x37] = &bCPU::op_and_ildpy;
|
||||
optbl[0xd7] = &bCPU::op_cmp_ildpy;
|
||||
optbl[0x57] = &bCPU::op_eor_ildpy;
|
||||
optbl[0xb7] = &bCPU::op_lda_ildpy;
|
||||
optbl[0x17] = &bCPU::op_ora_ildpy;
|
||||
optbl[0xf7] = &bCPU::op_sbc_ildpy;
|
||||
optbl[0x63] = &bCPU::op_adc_sr;
|
||||
optbl[0x23] = &bCPU::op_and_sr;
|
||||
optbl[0xc3] = &bCPU::op_cmp_sr;
|
||||
optbl[0x43] = &bCPU::op_eor_sr;
|
||||
optbl[0xa3] = &bCPU::op_lda_sr;
|
||||
optbl[0x03] = &bCPU::op_ora_sr;
|
||||
optbl[0xe3] = &bCPU::op_sbc_sr;
|
||||
optbl[0x73] = &bCPU::op_adc_isry;
|
||||
optbl[0x33] = &bCPU::op_and_isry;
|
||||
optbl[0xd3] = &bCPU::op_cmp_isry;
|
||||
optbl[0x53] = &bCPU::op_eor_isry;
|
||||
optbl[0xb3] = &bCPU::op_lda_isry;
|
||||
optbl[0x13] = &bCPU::op_ora_isry;
|
||||
optbl[0xf3] = &bCPU::op_sbc_isry;
|
||||
optbl[0x89] = &bCPU::op_bit_const;
|
||||
optbl[0x1a] = &bCPU::op_inc;
|
||||
optbl[0xe8] = &bCPU::op_inx;
|
||||
optbl[0xc8] = &bCPU::op_iny;
|
||||
optbl[0x3a] = &bCPU::op_dec;
|
||||
optbl[0xca] = &bCPU::op_dex;
|
||||
optbl[0x88] = &bCPU::op_dey;
|
||||
optbl[0x0a] = &bCPU::op_asl;
|
||||
optbl[0x4a] = &bCPU::op_lsr;
|
||||
optbl[0x2a] = &bCPU::op_rol;
|
||||
optbl[0x6a] = &bCPU::op_ror;
|
||||
optbl[0xee] = &bCPU::op_inc_addr;
|
||||
optbl[0xce] = &bCPU::op_dec_addr;
|
||||
optbl[0x0e] = &bCPU::op_asl_addr;
|
||||
optbl[0x4e] = &bCPU::op_lsr_addr;
|
||||
optbl[0x2e] = &bCPU::op_rol_addr;
|
||||
optbl[0x6e] = &bCPU::op_ror_addr;
|
||||
optbl[0x1c] = &bCPU::op_trb_addr;
|
||||
optbl[0x0c] = &bCPU::op_tsb_addr;
|
||||
optbl[0xfe] = &bCPU::op_inc_addrx;
|
||||
optbl[0xde] = &bCPU::op_dec_addrx;
|
||||
optbl[0x1e] = &bCPU::op_asl_addrx;
|
||||
optbl[0x5e] = &bCPU::op_lsr_addrx;
|
||||
optbl[0x3e] = &bCPU::op_rol_addrx;
|
||||
optbl[0x7e] = &bCPU::op_ror_addrx;
|
||||
optbl[0xe6] = &bCPU::op_inc_dp;
|
||||
optbl[0xc6] = &bCPU::op_dec_dp;
|
||||
optbl[0x06] = &bCPU::op_asl_dp;
|
||||
optbl[0x46] = &bCPU::op_lsr_dp;
|
||||
optbl[0x26] = &bCPU::op_rol_dp;
|
||||
optbl[0x66] = &bCPU::op_ror_dp;
|
||||
optbl[0x14] = &bCPU::op_trb_dp;
|
||||
optbl[0x04] = &bCPU::op_tsb_dp;
|
||||
optbl[0xf6] = &bCPU::op_inc_dpx;
|
||||
optbl[0xd6] = &bCPU::op_dec_dpx;
|
||||
optbl[0x16] = &bCPU::op_asl_dpx;
|
||||
optbl[0x56] = &bCPU::op_lsr_dpx;
|
||||
optbl[0x36] = &bCPU::op_rol_dpx;
|
||||
optbl[0x76] = &bCPU::op_ror_dpx;
|
||||
optbl[0x8d] = &bCPU::op_sta_addr;
|
||||
optbl[0x8e] = &bCPU::op_stx_addr;
|
||||
optbl[0x8c] = &bCPU::op_sty_addr;
|
||||
optbl[0x9c] = &bCPU::op_stz_addr;
|
||||
optbl[0x9d] = &bCPU::op_sta_addrx;
|
||||
optbl[0x9e] = &bCPU::op_stz_addrx;
|
||||
optbl[0x99] = &bCPU::op_sta_addry;
|
||||
optbl[0x8f] = &bCPU::op_sta_long;
|
||||
optbl[0x9f] = &bCPU::op_sta_longx;
|
||||
optbl[0x85] = &bCPU::op_sta_dp;
|
||||
optbl[0x86] = &bCPU::op_stx_dp;
|
||||
optbl[0x84] = &bCPU::op_sty_dp;
|
||||
optbl[0x64] = &bCPU::op_stz_dp;
|
||||
optbl[0x95] = &bCPU::op_sta_dpx;
|
||||
optbl[0x94] = &bCPU::op_sty_dpx;
|
||||
optbl[0x74] = &bCPU::op_stz_dpx;
|
||||
optbl[0x96] = &bCPU::op_stx_dpy;
|
||||
optbl[0x92] = &bCPU::op_sta_idp;
|
||||
optbl[0x87] = &bCPU::op_sta_ildp;
|
||||
optbl[0x81] = &bCPU::op_sta_idpx;
|
||||
optbl[0x91] = &bCPU::op_sta_idpy;
|
||||
optbl[0x97] = &bCPU::op_sta_ildpy;
|
||||
optbl[0x83] = &bCPU::op_sta_sr;
|
||||
optbl[0x93] = &bCPU::op_sta_isry;
|
||||
optbl[0x90] = &bCPU::op_bcc;
|
||||
optbl[0xb0] = &bCPU::op_bcs;
|
||||
optbl[0xd0] = &bCPU::op_bne;
|
||||
optbl[0xf0] = &bCPU::op_beq;
|
||||
optbl[0x10] = &bCPU::op_bpl;
|
||||
optbl[0x30] = &bCPU::op_bmi;
|
||||
optbl[0x50] = &bCPU::op_bvc;
|
||||
optbl[0x70] = &bCPU::op_bvs;
|
||||
optbl[0x80] = &bCPU::op_bra;
|
||||
optbl[0x82] = &bCPU::op_brl;
|
||||
optbl[0x4c] = &bCPU::op_jmp_addr;
|
||||
optbl[0x5c] = &bCPU::op_jmp_long;
|
||||
optbl[0x6c] = &bCPU::op_jmp_iaddr;
|
||||
optbl[0x7c] = &bCPU::op_jmp_iaddrx;
|
||||
optbl[0xdc] = &bCPU::op_jmp_iladdr;
|
||||
optbl[0x20] = &bCPU::op_jsr_addr;
|
||||
optbl[0x22] = &bCPU::op_jsr_long;
|
||||
optbl[0xfc] = &bCPU::op_jsr_iaddrx;
|
||||
optbl[0x40] = &bCPU::op_rti;
|
||||
optbl[0x60] = &bCPU::op_rts;
|
||||
optbl[0x6b] = &bCPU::op_rtl;
|
||||
optbl[0xea] = &bCPU::op_nop;
|
||||
optbl[0x42] = &bCPU::op_wdm;
|
||||
optbl[0xeb] = &bCPU::op_xba;
|
||||
optbl[0x54] = &bCPU::op_mvn;
|
||||
optbl[0x44] = &bCPU::op_mvp;
|
||||
optbl[0x00] = &bCPU::op_brk;
|
||||
optbl[0x02] = &bCPU::op_cop;
|
||||
optbl[0xdb] = &bCPU::op_stp;
|
||||
optbl[0xcb] = &bCPU::op_wai;
|
||||
optbl[0xfb] = &bCPU::op_xce;
|
||||
optbl[0x18] = &bCPU::op_clc;
|
||||
optbl[0xd8] = &bCPU::op_cld;
|
||||
optbl[0x58] = &bCPU::op_cli;
|
||||
optbl[0xb8] = &bCPU::op_clv;
|
||||
optbl[0x38] = &bCPU::op_sec;
|
||||
optbl[0xf8] = &bCPU::op_sed;
|
||||
optbl[0x78] = &bCPU::op_sei;
|
||||
optbl[0xc2] = &bCPU::op_rep;
|
||||
optbl[0xe2] = &bCPU::op_sep;
|
||||
optbl[0xaa] = &bCPU::op_tax;
|
||||
optbl[0xa8] = &bCPU::op_tay;
|
||||
optbl[0x8a] = &bCPU::op_txa;
|
||||
optbl[0x9b] = &bCPU::op_txy;
|
||||
optbl[0x98] = &bCPU::op_tya;
|
||||
optbl[0xbb] = &bCPU::op_tyx;
|
||||
optbl[0x5b] = &bCPU::op_tcd;
|
||||
optbl[0x1b] = &bCPU::op_tcs;
|
||||
optbl[0x7b] = &bCPU::op_tdc;
|
||||
optbl[0x3b] = &bCPU::op_tsc;
|
||||
optbl[0xba] = &bCPU::op_tsx;
|
||||
optbl[0x9a] = &bCPU::op_txs;
|
||||
optbl[0x48] = &bCPU::op_pha;
|
||||
optbl[0xda] = &bCPU::op_phx;
|
||||
optbl[0x5a] = &bCPU::op_phy;
|
||||
optbl[0x0b] = &bCPU::op_phd;
|
||||
optbl[0x8b] = &bCPU::op_phb;
|
||||
optbl[0x4b] = &bCPU::op_phk;
|
||||
optbl[0x08] = &bCPU::op_php;
|
||||
optbl[0x68] = &bCPU::op_pla;
|
||||
optbl[0xfa] = &bCPU::op_plx;
|
||||
optbl[0x7a] = &bCPU::op_ply;
|
||||
optbl[0x2b] = &bCPU::op_pld;
|
||||
optbl[0xab] = &bCPU::op_plb;
|
||||
optbl[0x28] = &bCPU::op_plp;
|
||||
optbl[0xf4] = &bCPU::op_pea;
|
||||
optbl[0xd4] = &bCPU::op_pei;
|
||||
optbl[0x62] = &bCPU::op_per;
|
||||
@@ -1,260 +0,0 @@
|
||||
/* used by both DMA and HDMA
|
||||
* prevents transfer across same bus (a->a or b->b)
|
||||
*/
|
||||
void bCPU::dma_transfer_byte(bool direction, uint8 bbus, uint32 abus) {
|
||||
uint8 r;
|
||||
if(direction == 0) {
|
||||
//read from address bus a, write to address bus b
|
||||
|
||||
//DMA address bus a cannot read from or write to the following addresses:
|
||||
//$[00-3f|80-bf]:21[00-ff] <address bus b>
|
||||
//$[00-3f|80-bf]:43[00-7f] <DMA control registers>
|
||||
//$[00-3f|80-bf]:420b <DMA enable register>
|
||||
//$[00-3f|80-bf]:420c <HDMA enable register>
|
||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
||||
//these invalid reads will return open bus
|
||||
r = r_cpu->regs.mdr;
|
||||
} else {
|
||||
r = r_mem->read(abus);
|
||||
}
|
||||
|
||||
r_mem->write(0x2100 | bbus, r);
|
||||
} else {
|
||||
//read from address bus b, write to address bus a
|
||||
|
||||
//block invalid writes, see comments above
|
||||
r = r_mem->read(0x2100 | bbus);
|
||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
|
||||
r_mem->write(abus, r);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bCPU::dma_bbus(uint8 i, uint8 index) {
|
||||
switch(channel[i].xfermode) {
|
||||
default:
|
||||
case 0: return (channel[i].destaddr); break; //0
|
||||
case 1: return (channel[i].destaddr + (index & 1)); break; //0,1
|
||||
case 2: return (channel[i].destaddr); break; //0,0
|
||||
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1
|
||||
case 4: return (channel[i].destaddr + (index & 3)); break; //0,1,2,3
|
||||
case 5: return (channel[i].destaddr + (index & 1)); break; //0,1,0,1
|
||||
case 6: return (channel[i].destaddr); break; //0,0 [2]
|
||||
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); break; //0,0,1,1 [3]
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_add_cycles(uint32 cycles) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
void bCPU::hdma_add_cycles(uint32 cycles) {
|
||||
if(run_state.dma) {
|
||||
status.dma_cycle_count += cycles;
|
||||
}
|
||||
status.hdma_cycle_count += cycles;
|
||||
}
|
||||
|
||||
uint32 bCPU::dma_addr(uint8 i) {
|
||||
uint32 r;
|
||||
r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||
|
||||
if(channel[i].fixedxfer == false) {
|
||||
channel[i].srcaddr += channel[i].incmode;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::dma_cputommio(uint8 i, uint8 bbus) {
|
||||
if(cartridge.info.sdd1 == true && sdd1->dma_active() == true) {
|
||||
r_mem->write(0x2100 | bbus, sdd1->dma_read());
|
||||
} else {
|
||||
dma_transfer_byte(0, bbus, dma_addr(i));
|
||||
}
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_mmiotocpu(uint8 i, uint8 bbus) {
|
||||
dma_transfer_byte(1, bbus, dma_addr(i));
|
||||
|
||||
add_cycles(8);
|
||||
channel[i].xfersize--;
|
||||
}
|
||||
|
||||
void bCPU::dma_write(uint8 i, uint8 index) {
|
||||
if(channel[i].direction == 0) {
|
||||
dma_cputommio(i, index);
|
||||
} else {
|
||||
dma_mmiotocpu(i, index);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_run() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].dma_enabled == false)continue;
|
||||
|
||||
//first byte transferred?
|
||||
if(cartridge.info.sdd1 == true && channel[i].read_index == 0) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
channel[i].xfersize);
|
||||
}
|
||||
|
||||
dma_write(i, dma_bbus(i, channel[i].read_index++));
|
||||
dma_add_cycles(8);
|
||||
|
||||
if(channel[i].xfersize == 0) {
|
||||
channel[i].dma_enabled = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_addr(uint8 i) {
|
||||
return (channel[i].srcbank << 16) | (channel[i].hdma_addr++);
|
||||
}
|
||||
|
||||
uint32 bCPU::hdma_iaddr(uint8 i) {
|
||||
return (channel[i].hdma_ibank << 16) | (channel[i].hdma_iaddr++);
|
||||
}
|
||||
|
||||
void bCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
|
||||
if(channel[i].hdma_line_counter == 0) {
|
||||
channel[i].hdma_completed = true;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
return;
|
||||
}
|
||||
|
||||
channel[i].hdma_do_transfer = true;
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_run() {
|
||||
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(!channel[i].hdma_enabled || channel[i].hdma_completed)continue;
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
for(channel[i].read_index = 0; channel[i].read_index < xferlen; channel[i].read_index++) {
|
||||
if(bool(config::cpu.hdma_enable) == true) {
|
||||
dma_transfer_byte(channel[i].direction, dma_bbus(i, channel[i].read_index),
|
||||
channel[i].hdma_indirect ? hdma_iaddr(i) : hdma_addr(i));
|
||||
}
|
||||
add_cycles(8);
|
||||
hdma_add_cycles(8);
|
||||
}
|
||||
}
|
||||
|
||||
channel[i].hdma_line_counter--;
|
||||
channel[i].hdma_do_transfer = bool(channel[i].hdma_line_counter & 0x80);
|
||||
if((channel[i].hdma_line_counter & 0x7f) == 0) {
|
||||
hdma_update(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_init() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(!channel[i].hdma_enabled)continue;
|
||||
|
||||
channel[i].hdma_addr = channel[i].srcaddr;
|
||||
hdma_update(i);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_enabled_channels() {
|
||||
int r = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].hdma_enabled)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 bCPU::hdma_active_channels() {
|
||||
int r = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].hdma_enabled && !channel[i].hdma_completed)r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* hdmainit_activate()
|
||||
* hdma_activate()
|
||||
*
|
||||
* Functions are called by CPU timing routine
|
||||
* when an HDMA event (init or run) occurs.
|
||||
*/
|
||||
|
||||
void bCPU::hdmainit_activate() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].hdma_completed = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
|
||||
if(hdma_enabled_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_IDMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::hdma_activate() {
|
||||
if(hdma_active_channels() != 0) {
|
||||
status.hdma_state = HDMASTATE_DMASYNC;
|
||||
run_state.hdma = true;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::dma_reset() {
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
status.hdma_state = HDMASTATE_CPUSYNC;
|
||||
status.dma_cycle_count = 0;
|
||||
status.hdma_cycle_count = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].read_index = 0;
|
||||
channel[i].dma_enabled = false;
|
||||
channel[i].hdma_enabled = false;
|
||||
channel[i].dmap = 0xff;
|
||||
channel[i].direction = 1;
|
||||
channel[i].hdma_indirect = 1;
|
||||
channel[i].incmode = -1;
|
||||
channel[i].fixedxfer = 1;
|
||||
channel[i].xfermode = 7;
|
||||
channel[i].destaddr = 0xff;
|
||||
channel[i].srcaddr = 0xffff;
|
||||
channel[i].srcbank = 0xff;
|
||||
channel[i].xfersize = 0xffff;
|
||||
//xfersize and hdma_iaddr are of union { uint16 };
|
||||
//channel[i].hdma_iaddr = 0xffff;
|
||||
channel[i].hdma_ibank = 0xff;
|
||||
channel[i].hdma_addr = 0xffff;
|
||||
channel[i].hdma_line_counter = 0xff;
|
||||
channel[i].hdma_unknown = 0xff;
|
||||
|
||||
channel[i].hdma_completed = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
struct {
|
||||
uint32 read_index; //set to 0 at beginning of DMA/HDMA
|
||||
|
||||
//$420b
|
||||
bool dma_enabled;
|
||||
//$420c
|
||||
bool hdma_enabled;
|
||||
//$43x0
|
||||
uint8 dmap;
|
||||
bool direction;
|
||||
bool hdma_indirect;
|
||||
int8 incmode;
|
||||
bool fixedxfer;
|
||||
uint8 xfermode;
|
||||
//$43x1
|
||||
uint8 destaddr;
|
||||
//$43x2-$43x3
|
||||
uint16 srcaddr;
|
||||
//$43x4
|
||||
uint8 srcbank;
|
||||
//$43x5-$43x6
|
||||
union {
|
||||
uint16 xfersize;
|
||||
uint16 hdma_iaddr;
|
||||
};
|
||||
//$43x7
|
||||
uint8 hdma_ibank;
|
||||
//$43x8-$43x9
|
||||
uint16 hdma_addr;
|
||||
//$43xa
|
||||
uint8 hdma_line_counter;
|
||||
//$43xb/$43xf
|
||||
uint8 hdma_unknown;
|
||||
|
||||
//hdma-specific
|
||||
bool hdma_completed; //for this frame
|
||||
bool hdma_do_transfer;
|
||||
|
||||
uint8 hdma_current_channel;
|
||||
uint8 hdma_current_pos;
|
||||
} channel[8];
|
||||
|
||||
inline void dma_transfer_byte(bool direction, uint8 bbus, uint32 abus);
|
||||
inline uint8 dma_bbus(uint8 i, uint8 index);
|
||||
inline void dma_add_cycles(uint32 cycles);
|
||||
inline void hdma_add_cycles(uint32 cycles);
|
||||
inline void dma_run();
|
||||
inline void hdma_run();
|
||||
inline void hdma_init();
|
||||
inline void hdma_update(uint8 i);
|
||||
inline uint8 hdma_enabled_channels();
|
||||
inline uint8 hdma_active_channels();
|
||||
inline void hdmainit_activate();
|
||||
inline void hdma_activate();
|
||||
inline void dma_cputommio(uint8 i, uint8 index);
|
||||
inline void dma_mmiotocpu(uint8 i, uint8 index);
|
||||
inline void dma_write(uint8 i, uint8 index);
|
||||
inline uint32 dma_addr(uint8 i);
|
||||
inline uint32 hdma_addr(uint8 i);
|
||||
inline uint32 hdma_iaddr(uint8 i);
|
||||
inline void dma_reset();
|
||||
@@ -1,40 +0,0 @@
|
||||
uint8 bCPU::port_read(uint8 port) {
|
||||
return apu_port[port & 3];
|
||||
}
|
||||
|
||||
void bCPU::port_write(uint8 port, uint8 value) {
|
||||
apu_port[port & 3] = value;
|
||||
}
|
||||
|
||||
/* The next 3 functions control bus timing for the CPU.
|
||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||
* mem_read / mem_write indicate memory access bus cycle,
|
||||
* they are either 6, 8, or 12 bus cycles long, depending
|
||||
* both on location and the $420d.d0 FastROM enable bit.
|
||||
*/
|
||||
|
||||
void bCPU::cpu_io() {
|
||||
status.cycle_count = 6;
|
||||
pre_exec_cycle();
|
||||
add_cycles(6);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
uint8 bCPU::mem_read(uint32 addr) {
|
||||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count - 4);
|
||||
regs.mdr = r_mem->read(addr);
|
||||
add_cycles(4);
|
||||
cycle_edge();
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void bCPU::mem_write(uint32 addr, uint8 value) {
|
||||
status.cycle_count = r_mem->speed(addr);
|
||||
pre_exec_cycle();
|
||||
add_cycles(status.cycle_count);
|
||||
regs.mdr = value;
|
||||
r_mem->write(addr, value);
|
||||
cycle_edge();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
uint8 apu_port[4];
|
||||
inline uint8 port_read (uint8 port);
|
||||
inline void port_write(uint8 port, uint8 value);
|
||||
|
||||
inline void cpu_io();
|
||||
inline uint8 mem_read(uint32 addr);
|
||||
inline void mem_write(uint32 addr, uint8 value);
|
||||
|
||||
/*****
|
||||
* helper memory addressing functions used by CPU core
|
||||
*****/
|
||||
uint8 op_readpc () { return mem_read((regs.pc.b << 16) + regs.pc.w++); }
|
||||
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return mem_read(regs.s.w); }
|
||||
uint8 op_readaddr (uint32 addr) { return mem_read(uclip<16>(addr)); }
|
||||
uint8 op_readlong (uint32 addr) { return mem_read(uclip<24>(addr)); }
|
||||
uint8 op_readdbr (uint32 addr) { return mem_read(uclip<24>((regs.db << 16) + addr)); }
|
||||
uint8 op_readpbr (uint32 addr) { return mem_read((regs.pc.b << 16) + uclip<16>(addr)); }
|
||||
uint8 op_readdp (uint32 addr) { return mem_read(uclip<16>(regs.d + uclip<16>(addr))); }
|
||||
uint8 op_readsp (uint32 addr) { return mem_read(uclip<16>(regs.s + uclip<16>(addr))); }
|
||||
|
||||
void op_writestack(uint8 data) { mem_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; }
|
||||
void op_writeaddr (uint32 addr, uint8 data) { mem_write(uclip<16>(addr), data); }
|
||||
void op_writelong (uint32 addr, uint8 data) { mem_write(uclip<24>(addr), data); }
|
||||
void op_writedbr (uint32 addr, uint8 data) { mem_write(uclip<24>((regs.db << 16) + addr), data); }
|
||||
void op_writepbr (uint32 addr, uint8 data) { mem_write((regs.pc.b << 16) + uclip<16>(addr), data); }
|
||||
void op_writedp (uint32 addr, uint8 data) { mem_write(uclip<16>(regs.d + uclip<16>(addr)), data); }
|
||||
void op_writesp (uint32 addr, uint8 data) { mem_write(uclip<16>(regs.s + uclip<16>(addr)), data); }
|
||||
@@ -1,338 +0,0 @@
|
||||
/* Notes about PAL timing:
|
||||
* As I do not have PAL hardware to run timing tests on, I've
|
||||
* had to guess on a lot of things. Below is how I've arrived
|
||||
* at various calculations:
|
||||
*
|
||||
* NTSC timing crystal: ~21477272hz
|
||||
* PAL timing crystal: ~21281370hz
|
||||
* NTSC ~60fps, PAL ~50fps
|
||||
* NTSC ~262 lines/frame, PAL ~312 lines/frame
|
||||
* NTSC 21477272 / (262 * 60) = ~1366 cycles/line
|
||||
* PAL 21281370 / (312 * 50) = ~1364 cycles/line
|
||||
*
|
||||
* As the cycles/line are very close between the two systems,
|
||||
* I have left the known NTSC anomalies intact for PAL timing.
|
||||
* In reality, some of these may not exist, and some may be
|
||||
* slightly different.
|
||||
*
|
||||
* [known]
|
||||
* - DRAM refresh occurs at about the same time every
|
||||
* scanline on PAL units (per Overload).
|
||||
* [unknown]
|
||||
* - Are dots 323/327 still 2 cycles longer than the
|
||||
* other dots?
|
||||
* - Is scanline 240 on non-interlace odd frames still
|
||||
* 4 cycles short?
|
||||
*/
|
||||
|
||||
uint16 bCPU::vcounter() { return time.v; }
|
||||
uint16 bCPU::hclock() { return time.hc; }
|
||||
|
||||
bool bCPU::interlace() { return time.interlace; }
|
||||
bool bCPU::interlace_field() { return time.interlace_field; }
|
||||
bool bCPU::overscan() { return time.overscan; }
|
||||
uint16 bCPU::region_scanlines() { return time.region_scanlines; }
|
||||
|
||||
void bCPU::set_interlace(bool r) { time.interlace = r; update_interrupts(); }
|
||||
void bCPU::set_overscan (bool r) { time.overscan = r; update_interrupts(); }
|
||||
|
||||
uint8 bCPU::dma_counter() { return (time.dma_counter + time.hc) & 6; }
|
||||
|
||||
uint16 bCPU::hcounter() {
|
||||
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
|
||||
return time.hc >> 2;
|
||||
}
|
||||
return (time.hc - ((time.hc > 1292) << 1) - ((time.hc > 1310) << 1)) >> 2;
|
||||
}
|
||||
|
||||
bool bCPU::nmi_trigger_pos_match(uint32 offset) {
|
||||
uint16 v = overscan() ? 240 : 225;
|
||||
uint16 hc = 2 + offset;
|
||||
return (time.v == v && time.hc == hc);
|
||||
}
|
||||
|
||||
bool bCPU::irq_trigger_pos_match(uint32 offset) {
|
||||
uint16 v = status.virq_pos;
|
||||
uint16 hc = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||
uint16 vlimit = region_scanlines() >> 1;
|
||||
|
||||
//positions that can never be latched
|
||||
//region_scanlines() = 525/NTSC, 625/PAL
|
||||
//PAL results are unverified on hardware
|
||||
if(v == 240 && hc == 339 && interlace() == false && interlace_field() == 1)return false;
|
||||
if(v == (vlimit - 1) && hc == 339 && interlace() == false)return false;
|
||||
if(v == vlimit && interlace() == false)return false;
|
||||
if(v == vlimit && hc == 339)return false;
|
||||
if(v > vlimit)return false;
|
||||
if(hc > 339)return false;
|
||||
|
||||
hc = (hc != 0) ? ((hc << 2) + 14) : 10;
|
||||
hc += offset;
|
||||
if(hc >= time.line_cycles) {
|
||||
hc -= time.line_cycles;
|
||||
if(++v >= time.frame_lines) {
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((status.virq_enabled == true && time.v == v) || status.virq_enabled == false) {
|
||||
return (time.hc == hc);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void bCPU::update_nmi() {
|
||||
if(time.v == (overscan() ? 240 : 225)) {
|
||||
time.nmi_read_trigger_pos = 2;
|
||||
time.nmi_line_trigger_pos = 6;
|
||||
} else {
|
||||
time.nmi_read_trigger_pos = -64;
|
||||
time.nmi_line_trigger_pos = -64;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::update_irq() {
|
||||
int vpos = status.virq_pos;
|
||||
int hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||
int vlimit = region_scanlines() >> 1;
|
||||
|
||||
//positions that can never be latched
|
||||
//region_scanlines() = 262/NTSC, 312/PAL
|
||||
//PAL results are unverified on hardware
|
||||
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)goto _nolatch;
|
||||
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)goto _nolatch;
|
||||
if(vpos == vlimit && interlace() == false)goto _nolatch;
|
||||
if(vpos == vlimit && hpos == 339)goto _nolatch;
|
||||
if(vpos > vlimit)goto _nolatch;
|
||||
if(hpos > 339)goto _nolatch;
|
||||
|
||||
hpos = (hpos != 0) ? ((hpos << 2) + 14) : 10;
|
||||
if(hpos >= time.line_cycles) {
|
||||
hpos -= time.line_cycles;
|
||||
if(++vpos >= time.frame_lines) {
|
||||
vpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
|
||||
time.irq_read_trigger_pos = hpos;
|
||||
} else {
|
||||
time.irq_read_trigger_pos = -64;
|
||||
}
|
||||
|
||||
hpos += 4;
|
||||
if(hpos >= time.line_cycles) {
|
||||
hpos -= time.line_cycles;
|
||||
if(++vpos >= time.frame_lines) {
|
||||
vpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((status.virq_enabled == true && time.v == vpos) || status.virq_enabled == false) {
|
||||
time.irq_line_trigger_pos = hpos;
|
||||
} else {
|
||||
time.irq_line_trigger_pos = -64;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_nolatch:
|
||||
time.irq_read_trigger_pos = -64;
|
||||
time.irq_line_trigger_pos = -64;
|
||||
}
|
||||
|
||||
void bCPU::update_interrupts() {
|
||||
update_nmi();
|
||||
update_irq();
|
||||
}
|
||||
|
||||
void bCPU::poll_interrupts(int cycles) {
|
||||
int16 hc, hc_end;
|
||||
if(time.hc == 0) {
|
||||
hc = -1;
|
||||
hc_end = cycles;
|
||||
} else {
|
||||
hc = time.hc;
|
||||
hc_end = time.hc + cycles;
|
||||
}
|
||||
|
||||
if(hc < time.nmi_read_trigger_pos && time.nmi_read_trigger_pos <= hc_end) {
|
||||
//nmi_read can go low even with NMI interrupts disabled in $4200.d7
|
||||
time.nmi_read = 0;
|
||||
}
|
||||
|
||||
if(hc < time.nmi_line_trigger_pos && time.nmi_line_trigger_pos <= hc_end) {
|
||||
if(status.nmi_enabled == true) {
|
||||
if(time.nmi_line == 1) {
|
||||
time.nmi_transition = 1;
|
||||
}
|
||||
time.nmi_line = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(hc < time.irq_read_trigger_pos && time.irq_read_trigger_pos <= hc_end) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) {
|
||||
time.irq_read = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(hc < time.irq_line_trigger_pos && time.irq_line_trigger_pos <= hc_end) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) {
|
||||
time.irq_line = 0;
|
||||
time.irq_transition = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 bCPU::clocks_executed() {
|
||||
uint32 r = status.cycles_executed;
|
||||
status.cycles_executed = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
void bCPU::cycle_edge() {
|
||||
if(time.line_rendered == false) {
|
||||
if(time.hc >= 192) {
|
||||
time.line_rendered = true;
|
||||
r_ppu->render_scanline();
|
||||
}
|
||||
}
|
||||
|
||||
if(time.hdmainit_triggered == false) {
|
||||
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
|
||||
time.hdmainit_triggered = true;
|
||||
hdmainit_activate();
|
||||
}
|
||||
}
|
||||
|
||||
if(time.hdma_triggered == false) {
|
||||
//hdma_triggered only set to false for v <= (overscan ? 239 : 224)
|
||||
if(time.hc >= 1106) {
|
||||
time.hdma_triggered = true;
|
||||
hdma_activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::add_cycles(int cycles) {
|
||||
status.cycles_executed += cycles;
|
||||
poll_interrupts(cycles);
|
||||
|
||||
if(time.hc + cycles >= time.line_cycles) {
|
||||
cycles = (time.hc + cycles) - time.line_cycles;
|
||||
time.hc = 0;
|
||||
scanline();
|
||||
poll_interrupts(cycles);
|
||||
}
|
||||
|
||||
time.hc += cycles;
|
||||
|
||||
if(time.dram_refreshed == false) {
|
||||
if(time.hc >= time.dram_refresh_pos) {
|
||||
time.dram_refreshed = true;
|
||||
add_cycles(40);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::scanline() {
|
||||
if(++time.v >= time.frame_lines) {
|
||||
frame();
|
||||
}
|
||||
|
||||
time.dma_counter += time.line_cycles;
|
||||
if(time.v == 240 && time.interlace == false && time.interlace_field == 1) {
|
||||
time.line_cycles = 1360;
|
||||
} else {
|
||||
time.line_cycles = 1364;
|
||||
}
|
||||
time.dram_refreshed = false;
|
||||
|
||||
time.line_rendered =
|
||||
time.hdma_triggered = (time.v <= (!overscan() ? 224 : 239)) ? false : true;
|
||||
|
||||
r_ppu->scanline();
|
||||
snes->scanline();
|
||||
|
||||
update_interrupts();
|
||||
|
||||
if(vcounter() == (!overscan() ? 227 : 242) && 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;
|
||||
status.joypad2_read_pos = 16;
|
||||
}
|
||||
}
|
||||
|
||||
void bCPU::frame() {
|
||||
time.nmi_read = 1;
|
||||
time.nmi_line = 1;
|
||||
time.nmi_transition = 0;
|
||||
|
||||
time.v = 0;
|
||||
time.interlace_field ^= 1;
|
||||
if(interlace() == true && interlace_field() == 0) {
|
||||
time.frame_lines = (time.region_scanlines >> 1) + 1;
|
||||
} else {
|
||||
time.frame_lines = (time.region_scanlines >> 1);
|
||||
}
|
||||
|
||||
if(cpu_version == 2) {
|
||||
time.hdmainit_trigger_pos = 12 + dma_counter();
|
||||
} else {
|
||||
time.hdmainit_trigger_pos = 12 + 8 - dma_counter();
|
||||
}
|
||||
time.hdmainit_triggered = false;
|
||||
|
||||
r_ppu->frame();
|
||||
snes->frame();
|
||||
}
|
||||
|
||||
void bCPU::time_reset() {
|
||||
time.v = 0;
|
||||
time.hc = 0;
|
||||
|
||||
//upon SNES reset, start at scanline 0 non-interlace
|
||||
time.interlace = 0;
|
||||
time.interlace_field = 0;
|
||||
time.overscan = false;
|
||||
time.line_cycles = 1364;
|
||||
|
||||
time.dram_refreshed = false;
|
||||
time.dram_refresh_pos = (cpu_version == 2) ? 538 : 530;
|
||||
|
||||
time.dma_counter = 0;
|
||||
|
||||
//set at V=0,H=0
|
||||
time.hdmainit_trigger_pos = 0;
|
||||
time.hdmainit_triggered = true;
|
||||
|
||||
time.hdma_triggered = false;
|
||||
|
||||
time.nmi_pending = false;
|
||||
time.irq_pending = false;
|
||||
time.nmi_line = time.nmi_read = 1;
|
||||
time.irq_line = time.irq_read = 1;
|
||||
|
||||
time.nmi_transition = 0;
|
||||
time.irq_transition = 0;
|
||||
|
||||
update_interrupts();
|
||||
|
||||
switch(region) {
|
||||
case NTSC:
|
||||
time.region_scanlines = 525;
|
||||
break;
|
||||
case PAL:
|
||||
time.region_scanlines = 625;
|
||||
break;
|
||||
}
|
||||
|
||||
time.frame_lines = time.region_scanlines >> 1;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
struct {
|
||||
uint16 v, hc;
|
||||
|
||||
bool interlace, interlace_field, overscan;
|
||||
uint16 line_cycles, frame_lines;
|
||||
|
||||
bool line_rendered;
|
||||
|
||||
bool dram_refreshed;
|
||||
uint16 dram_refresh_pos;
|
||||
|
||||
uint8 dma_counter;
|
||||
|
||||
uint16 hdmainit_trigger_pos;
|
||||
bool hdmainit_triggered;
|
||||
|
||||
bool hdma_triggered;
|
||||
|
||||
uint16 region_scanlines;
|
||||
|
||||
//nmi_pending, irq_pending are used by last_cycle()
|
||||
//nmi_line = /NMI, nmi_read = $4210.7
|
||||
//irq_line = /IRQ, irq_read = $4211.7
|
||||
bool nmi_pending, nmi_line, nmi_read;
|
||||
bool irq_pending, irq_line, irq_read;
|
||||
|
||||
//NMI is edge-sensitive, meaning it triggers when /NMI
|
||||
//transitions from high to low. This value is set to 1
|
||||
//when that happens, and cleared after the nmi_test()
|
||||
//routine acknowledges it and invokes the NMI interrupt
|
||||
bool nmi_transition;
|
||||
|
||||
//IRQ is level-sensitive, so it does not need to keep
|
||||
//track of transitions from high to low. IRQs will
|
||||
//continue to fire as long as /IRQ stays low.
|
||||
//However, if a write to $4200 forces IRQs high at the
|
||||
//exact same clock cycle that /IRQ goes low, the /IRQ
|
||||
//will still occur. Hence the need for this variable.
|
||||
bool irq_transition;
|
||||
|
||||
//position is relative to time.hc, set at start of each scanline
|
||||
//-64 means no trigger point on this scanline
|
||||
//$4210/$4211 status bits get set before /NMI and /IRQ go low,
|
||||
//hence the need for two variables for each.
|
||||
int32 nmi_read_trigger_pos, nmi_line_trigger_pos;
|
||||
int32 irq_read_trigger_pos, irq_line_trigger_pos;
|
||||
} time;
|
||||
|
||||
inline uint16 vcounter();
|
||||
inline uint16 hcounter();
|
||||
inline uint16 hclock();
|
||||
inline bool interlace();
|
||||
inline bool interlace_field();
|
||||
inline bool overscan();
|
||||
inline uint16 region_scanlines();
|
||||
|
||||
inline bool nmi_trigger_pos_match(uint32 offset);
|
||||
inline bool irq_trigger_pos_match(uint32 offset);
|
||||
|
||||
inline void update_nmi();
|
||||
inline void update_irq();
|
||||
inline void update_interrupts();
|
||||
inline void poll_interrupts(int cycles);
|
||||
|
||||
inline void set_interlace(bool r);
|
||||
inline void set_overscan (bool r);
|
||||
|
||||
inline uint8 dma_counter();
|
||||
|
||||
inline void cycle_edge();
|
||||
inline void add_cycles(int cycles);
|
||||
inline void scanline();
|
||||
inline void frame();
|
||||
inline void time_reset();
|
||||
+3
-3
@@ -1,6 +1,9 @@
|
||||
#include "cpuregs.h"
|
||||
|
||||
class CPU : public MMIO {
|
||||
public:
|
||||
virtual void enter() = 0;
|
||||
|
||||
public:
|
||||
//CPU version number
|
||||
//* 1 and 2 are known
|
||||
@@ -30,9 +33,6 @@ CPURegs regs;
|
||||
FLAG_Z = 0x02, FLAG_C = 0x01
|
||||
};
|
||||
virtual uint8 pio_status() = 0;
|
||||
virtual void main() {}
|
||||
virtual void run() = 0;
|
||||
virtual uint32 clocks_executed() = 0;
|
||||
virtual void scanline() = 0;
|
||||
virtual void frame() = 0;
|
||||
virtual void power() = 0;
|
||||
|
||||
+2
-3
@@ -3,7 +3,7 @@ public:
|
||||
union {
|
||||
uint8 data;
|
||||
struct {
|
||||
uint8 order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
|
||||
bool order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -71,6 +71,5 @@ CPURegFlags p;
|
||||
uint8 db;
|
||||
uint8 mdr;
|
||||
bool e;
|
||||
bool acc_8b, idx_8b;
|
||||
CPURegs() : db(0), mdr(0x00), e(false), acc_8b(true), idx_8b(true) {}
|
||||
CPURegs() : db(0), mdr(0x00), e(false) {}
|
||||
};
|
||||
+24
-30
@@ -1,37 +1,31 @@
|
||||
#include "opfn.cpp"
|
||||
|
||||
void sCPU::main() {
|
||||
for(;;) {
|
||||
if(event.irq) {
|
||||
event.irq = false;
|
||||
if(status.nmi_pending == true) {
|
||||
status.nmi_pending = false;
|
||||
event.irq_vector = (regs.e == false) ? 0xffea : 0xfffa;
|
||||
} else if(status.irq_pending == true) {
|
||||
status.irq_pending = false;
|
||||
event.irq_vector = (regs.e == false) ? 0xffee : 0xfffe;
|
||||
}
|
||||
op_irq();
|
||||
#include "op_read.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
|
||||
void sCPU::enter() { loop:
|
||||
if(event.irq) {
|
||||
event.irq = false;
|
||||
if(status.nmi_pending == true) {
|
||||
status.nmi_pending = false;
|
||||
event.irq_vector = (regs.e == false) ? 0xffea : 0xfffa;
|
||||
} else if(status.irq_pending == true) {
|
||||
status.irq_pending = false;
|
||||
event.irq_vector = (regs.e == false) ? 0xffee : 0xfffe;
|
||||
}
|
||||
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
|
||||
switch(op_readpc()) {
|
||||
#include "op_read.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
}
|
||||
|
||||
status.in_opcode = false;
|
||||
|
||||
#ifdef FAVOR_SPEED
|
||||
co_return();
|
||||
#endif
|
||||
op_irq();
|
||||
}
|
||||
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
(this->*optbl[op_readpc()])();
|
||||
status.in_opcode = false;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void sCPU::op_irq() {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
//void (sCPU::*optbl[256])();
|
||||
void (sCPU::*optbl[256])();
|
||||
|
||||
CPUReg24 aa, rd;
|
||||
uint8 dp, sp;
|
||||
|
||||
inline void main();
|
||||
inline void op_irq();
|
||||
void op_irq();
|
||||
|
||||
inline bool in_opcode() { return status.in_opcode; }
|
||||
inline bool in_opcode() { return status.in_opcode; }
|
||||
|
||||
//op_read
|
||||
void op_adc_b();
|
||||
@@ -55,4 +54,4 @@ uint8 dp, sp;
|
||||
void op_io_cond4(uint16 x, uint16 y);
|
||||
void op_io_cond6(uint16 addr);
|
||||
|
||||
//#include "op.h"
|
||||
#include "op.h"
|
||||
@@ -124,6 +124,30 @@ void op_lda_isry();
|
||||
void op_ora_isry();
|
||||
void op_sbc_isry();
|
||||
void op_bit_const();
|
||||
void op_sta_addr();
|
||||
void op_stx_addr();
|
||||
void op_sty_addr();
|
||||
void op_stz_addr();
|
||||
void op_sta_addrx();
|
||||
void op_stz_addrx();
|
||||
void op_sta_addry();
|
||||
void op_sta_long();
|
||||
void op_sta_longx();
|
||||
void op_sta_dp();
|
||||
void op_stx_dp();
|
||||
void op_sty_dp();
|
||||
void op_stz_dp();
|
||||
void op_sta_dpx();
|
||||
void op_sty_dpx();
|
||||
void op_stz_dpx();
|
||||
void op_stx_dpy();
|
||||
void op_sta_idp();
|
||||
void op_sta_ildp();
|
||||
void op_sta_idpx();
|
||||
void op_sta_idpy();
|
||||
void op_sta_ildpy();
|
||||
void op_sta_sr();
|
||||
void op_sta_isry();
|
||||
void op_inc();
|
||||
void op_inx();
|
||||
void op_iny();
|
||||
@@ -162,30 +186,6 @@ void op_asl_dpx();
|
||||
void op_lsr_dpx();
|
||||
void op_rol_dpx();
|
||||
void op_ror_dpx();
|
||||
void op_sta_addr();
|
||||
void op_stx_addr();
|
||||
void op_sty_addr();
|
||||
void op_stz_addr();
|
||||
void op_sta_addrx();
|
||||
void op_stz_addrx();
|
||||
void op_sta_addry();
|
||||
void op_sta_long();
|
||||
void op_sta_longx();
|
||||
void op_sta_dp();
|
||||
void op_stx_dp();
|
||||
void op_sty_dp();
|
||||
void op_stz_dp();
|
||||
void op_sta_dpx();
|
||||
void op_sty_dpx();
|
||||
void op_stz_dpx();
|
||||
void op_stx_dpy();
|
||||
void op_sta_idp();
|
||||
void op_sta_ildp();
|
||||
void op_sta_idpx();
|
||||
void op_sta_idpy();
|
||||
void op_sta_ildpy();
|
||||
void op_sta_sr();
|
||||
void op_sta_isry();
|
||||
void op_bcc();
|
||||
void op_bcs();
|
||||
void op_bne();
|
||||
+75
-58
@@ -15,7 +15,7 @@ xba(0xeb) {
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
@@ -27,10 +27,12 @@ mvp(0x44, --) {
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
4:op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
5:op_io();
|
||||
if(regs.idx_8b) {
|
||||
regs.x.l $1; regs.y.l $1;
|
||||
if(regs.p.x) {
|
||||
regs.x.l $1;
|
||||
regs.y.l $1;
|
||||
} else {
|
||||
regs.x.w $1; regs.y.w $1;
|
||||
regs.x.w $1;
|
||||
regs.y.w $1;
|
||||
}
|
||||
6:last_cycle();
|
||||
op_io();
|
||||
@@ -56,34 +58,31 @@ cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
||||
stp(0xdb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
while(1) {
|
||||
op_io();
|
||||
co_return();
|
||||
}
|
||||
while(1) { op_io(); }
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
1:op_io();
|
||||
event.wai = true;
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
3:while(event.wai) {
|
||||
//last_cycle() will set event.wai to false
|
||||
//once an NMI / IRQ edge is reached
|
||||
1:event.wai = true;
|
||||
while(event.wai) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
co_return();
|
||||
}
|
||||
2:op_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
bool c = regs.p.c;
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
@@ -107,29 +106,28 @@ sep(0xe2, |=) {
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.p $1 rd.l;
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
tax(0xaa, regs.idx_8b, x, a),
|
||||
tay(0xa8, regs.idx_8b, y, a),
|
||||
txa(0x8a, regs.acc_8b, a, x),
|
||||
txy(0x9b, regs.idx_8b, y, x),
|
||||
tya(0x98, regs.acc_8b, a, y),
|
||||
tyx(0xbb, regs.idx_8b, x, y) {
|
||||
tax(0xaa, regs.p.x, x, a),
|
||||
tay(0xa8, regs.p.x, y, a),
|
||||
txa(0x8a, regs.p.m, a, x),
|
||||
txy(0x9b, regs.p.x, y, x),
|
||||
tya(0x98, regs.p.m, a, y),
|
||||
tyx(0xbb, regs.p.x, x, y) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
if($1) {
|
||||
regs.$2.l = regs.$3.l;
|
||||
regs.p.n = bool(regs.$2.l & 0x80);
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w = regs.$3.w;
|
||||
regs.p.n = bool(regs.$2.w & 0x8000);
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -138,7 +136,7 @@ tcd(0x5b) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = bool(regs.d.w & 0x8000);
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
@@ -153,7 +151,7 @@ tdc(0x7b) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
@@ -162,10 +160,10 @@ tsc(0x3b) {
|
||||
op_io();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -173,13 +171,13 @@ tsc(0x3b) {
|
||||
tsx(0xba) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -194,16 +192,23 @@ txs(0x9a) {
|
||||
}
|
||||
}
|
||||
|
||||
pha(0x48, regs.acc_8b, a),
|
||||
phx(0xda, regs.idx_8b, x),
|
||||
phy(0x5a, regs.idx_8b, y),
|
||||
phd(0x0b, 0, d) {
|
||||
pha(0x48, regs.p.m, a),
|
||||
phx(0xda, regs.p.x, x),
|
||||
phy(0x5a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:if(!$1)op_writestack(regs.$2.h);
|
||||
3:last_cycle();
|
||||
op_writestack(regs.$2.l);
|
||||
}
|
||||
|
||||
phd(0x0b) {
|
||||
1:op_io();
|
||||
2:op_writestackn(regs.d.h);
|
||||
3:last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
phb(0x8b, regs.db),
|
||||
phk(0x4b, regs.pc.b),
|
||||
php(0x08, regs.p) {
|
||||
@@ -212,31 +217,41 @@ php(0x08, regs.p) {
|
||||
op_writestack($1);
|
||||
}
|
||||
|
||||
pla(0x68, regs.acc_8b, a),
|
||||
plx(0xfa, regs.idx_8b, x),
|
||||
ply(0x7a, regs.idx_8b, y),
|
||||
pld(0x2b, 0, d) {
|
||||
pla(0x68, regs.p.m, a),
|
||||
plx(0xfa, regs.p.x, x),
|
||||
ply(0x7a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:if($1)last_cycle();
|
||||
regs.$2.l = op_readstack();
|
||||
if($1) {
|
||||
regs.p.n = bool(regs.$2.l & 0x80);
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
end;
|
||||
}
|
||||
4:last_cycle();
|
||||
regs.$2.h = op_readstack();
|
||||
regs.p.n = bool(regs.$2.w & 0x8000);
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
|
||||
pld(0x2b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.d.l = op_readstackn();
|
||||
4:last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
plb(0xab) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = bool(regs.db & 0x80);
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
@@ -245,9 +260,8 @@ plp(0x28) {
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.p = op_readstack();
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
@@ -256,9 +270,10 @@ plp(0x28) {
|
||||
pea(0xf4) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestack(aa.h);
|
||||
3:op_writestackn(aa.h);
|
||||
4:last_cycle();
|
||||
op_writestack(aa.l);
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
pei(0xd4) {
|
||||
@@ -266,9 +281,10 @@ pei(0xd4) {
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_writestack(aa.h);
|
||||
5:op_writestackn(aa.h);
|
||||
6:last_cycle();
|
||||
op_writestack(aa.l);
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
per(0x62) {
|
||||
@@ -276,7 +292,8 @@ per(0x62) {
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
4:op_writestack(rd.h);
|
||||
4:op_writestackn(rd.h);
|
||||
5:last_cycle();
|
||||
op_writestack(rd.l);
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
+183
-233
@@ -1,65 +1,63 @@
|
||||
//nop
|
||||
case 0xea: {
|
||||
void sCPU::op_nop() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//wdm
|
||||
case 0x42: {
|
||||
void sCPU::op_wdm() {
|
||||
last_cycle();
|
||||
op_readpc();
|
||||
} break;
|
||||
}
|
||||
|
||||
//xba
|
||||
case 0xeb: {
|
||||
void sCPU::op_xba() {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//mvn
|
||||
case 0x54: {
|
||||
void sCPU::op_mvn() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
regs.x.l ++; regs.y.l ++;
|
||||
if(regs.p.x) {
|
||||
regs.x.l ++;
|
||||
regs.y.l ++;
|
||||
} else {
|
||||
regs.x.w ++; regs.y.w ++;
|
||||
regs.x.w ++;
|
||||
regs.y.w ++;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
} break;
|
||||
}
|
||||
|
||||
//mvp
|
||||
case 0x44: {
|
||||
void sCPU::op_mvp() {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
regs.x.l --; regs.y.l --;
|
||||
if(regs.p.x) {
|
||||
regs.x.l --;
|
||||
regs.y.l --;
|
||||
} else {
|
||||
regs.x.w --; regs.y.w --;
|
||||
regs.x.w --;
|
||||
regs.y.w --;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
} break;
|
||||
}
|
||||
|
||||
//brk
|
||||
case 0x00: {
|
||||
void sCPU::op_brk() {
|
||||
op_readpc();
|
||||
if(!regs.e)op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
@@ -72,10 +70,9 @@ case 0x00: {
|
||||
last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//cop
|
||||
case 0x02: {
|
||||
void sCPU::op_cop() {
|
||||
op_readpc();
|
||||
if(!regs.e)op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
@@ -88,271 +85,242 @@ case 0x02: {
|
||||
last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//stp
|
||||
case 0xdb: {
|
||||
void sCPU::op_stp() {
|
||||
op_io();
|
||||
last_cycle();
|
||||
while(1) {
|
||||
op_io();
|
||||
co_return();
|
||||
}
|
||||
} break;
|
||||
while(1) { op_io(); }
|
||||
}
|
||||
|
||||
//wai
|
||||
case 0xcb: {
|
||||
op_io();
|
||||
void sCPU::op_wai() {
|
||||
//last_cycle() will set event.wai to false
|
||||
//once an NMI / IRQ edge is reached
|
||||
event.wai = true;
|
||||
last_cycle();
|
||||
op_io();
|
||||
while(event.wai) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
co_return();
|
||||
}
|
||||
} break;
|
||||
op_io();
|
||||
}
|
||||
|
||||
//xce
|
||||
case 0xfb: {
|
||||
void sCPU::op_xce() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
bool c = regs.p.c;
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//clc
|
||||
case 0x18: {
|
||||
void sCPU::op_clc() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.c = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
//cld
|
||||
case 0xd8: {
|
||||
void sCPU::op_cld() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
//cli
|
||||
case 0x58: {
|
||||
void sCPU::op_cli() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.i = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
//clv
|
||||
case 0xb8: {
|
||||
void sCPU::op_clv() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.v = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
//sec
|
||||
case 0x38: {
|
||||
void sCPU::op_sec() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.c = 1;
|
||||
} break;
|
||||
}
|
||||
|
||||
//sed
|
||||
case 0xf8: {
|
||||
void sCPU::op_sed() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.d = 1;
|
||||
} break;
|
||||
}
|
||||
|
||||
//sei
|
||||
case 0x78: {
|
||||
void sCPU::op_sei() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p.i = 1;
|
||||
} break;
|
||||
}
|
||||
|
||||
//rep
|
||||
case 0xc2: {
|
||||
void sCPU::op_rep() {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p &=~ rd.l;
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//sep
|
||||
case 0xe2: {
|
||||
void sCPU::op_sep() {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p |= rd.l;
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//tax
|
||||
case 0xaa: {
|
||||
void sCPU::op_tax() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.a.w;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//tay
|
||||
case 0xa8: {
|
||||
void sCPU::op_tay() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.a.w;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//txa
|
||||
case 0x8a: {
|
||||
void sCPU::op_txa() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.x.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//txy
|
||||
case 0x9b: {
|
||||
void sCPU::op_txy() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.x.w;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//tya
|
||||
case 0x98: {
|
||||
void sCPU::op_tya() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.y.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//tyx
|
||||
case 0xbb: {
|
||||
void sCPU::op_tyx() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.y.w;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//tcd
|
||||
case 0x5b: {
|
||||
void sCPU::op_tcd() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = bool(regs.d.w & 0x8000);
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//tcs
|
||||
case 0x1b: {
|
||||
void sCPU::op_tcs() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
} break;
|
||||
}
|
||||
|
||||
//tdc
|
||||
case 0x7b: {
|
||||
void sCPU::op_tdc() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//tsc
|
||||
case 0x3b: {
|
||||
void sCPU::op_tsc() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//tsx
|
||||
case 0xba: {
|
||||
void sCPU::op_tsx() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//txs
|
||||
case 0x9a: {
|
||||
void sCPU::op_txs() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.e) {
|
||||
@@ -360,181 +328,163 @@ case 0x9a: {
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//pha
|
||||
case 0x48: {
|
||||
void sCPU::op_pha() {
|
||||
op_io();
|
||||
if(!regs.acc_8b)op_writestack(regs.a.h);
|
||||
if(!regs.p.m)op_writestack(regs.a.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.a.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//phx
|
||||
case 0xda: {
|
||||
void sCPU::op_phx() {
|
||||
op_io();
|
||||
if(!regs.idx_8b)op_writestack(regs.x.h);
|
||||
if(!regs.p.x)op_writestack(regs.x.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.x.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//phy
|
||||
case 0x5a: {
|
||||
void sCPU::op_phy() {
|
||||
op_io();
|
||||
if(!regs.idx_8b)op_writestack(regs.y.h);
|
||||
if(!regs.p.x)op_writestack(regs.y.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.y.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//phd
|
||||
case 0x0b: {
|
||||
void sCPU::op_phd() {
|
||||
op_io();
|
||||
if(!0)op_writestack(regs. d.h);
|
||||
op_writestackn(regs.d.h);
|
||||
last_cycle();
|
||||
op_writestack(regs. d.l);
|
||||
} break;
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
//phb
|
||||
case 0x8b: {
|
||||
void sCPU::op_phb() {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.db);
|
||||
} break;
|
||||
}
|
||||
|
||||
//phk
|
||||
case 0x4b: {
|
||||
void sCPU::op_phk() {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
}
|
||||
|
||||
//php
|
||||
case 0x08: {
|
||||
void sCPU::op_php() {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
}
|
||||
|
||||
//pla
|
||||
case 0x68: {
|
||||
void sCPU::op_pla() {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
regs.a.l = op_readstack();
|
||||
if(regs.acc_8b) {
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
last_cycle();
|
||||
regs.a.h = op_readstack();
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//plx
|
||||
case 0xfa: {
|
||||
void sCPU::op_plx() {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.x.l = op_readstack();
|
||||
if(regs.idx_8b) {
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
last_cycle();
|
||||
regs.x.h = op_readstack();
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//ply
|
||||
case 0x7a: {
|
||||
void sCPU::op_ply() {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.y.l = op_readstack();
|
||||
if(regs.idx_8b) {
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
last_cycle();
|
||||
regs.y.h = op_readstack();
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//pld
|
||||
case 0x2b: {
|
||||
void sCPU::op_pld() {
|
||||
op_io();
|
||||
op_io();
|
||||
if(0)last_cycle();
|
||||
regs. d.l = op_readstack();
|
||||
if(0) {
|
||||
regs.p.n = bool(regs. d.l & 0x80);
|
||||
regs.p.z = (regs. d.l == 0);
|
||||
break;
|
||||
}
|
||||
regs.d.l = op_readstackn();
|
||||
last_cycle();
|
||||
regs. d.h = op_readstack();
|
||||
regs.p.n = bool(regs. d.w & 0x8000);
|
||||
regs.p.z = (regs. d.w == 0);
|
||||
} break;
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
//plb
|
||||
case 0xab: {
|
||||
void sCPU::op_plb() {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = bool(regs.db & 0x80);
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
//plp
|
||||
case 0x28: {
|
||||
void sCPU::op_plp() {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.p = op_readstack();
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//pea
|
||||
case 0xf4: {
|
||||
void sCPU::op_pea() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestack(aa.h);
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestack(aa.l);
|
||||
} break;
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
//pei
|
||||
case 0xd4: {
|
||||
void sCPU::op_pei() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestack(aa.h);
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestack(aa.l);
|
||||
} break;
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
//per
|
||||
case 0x62: {
|
||||
void sCPU::op_per() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
op_writestack(rd.h);
|
||||
op_writestackn(rd.h);
|
||||
last_cycle();
|
||||
op_writestack(rd.l);
|
||||
} break;
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
+18
-16
@@ -48,7 +48,7 @@ jmp_long(0x5c) {
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jmp_iaddr(0x6c) {
|
||||
@@ -77,7 +77,7 @@ jmp_iladdr(0xdc) {
|
||||
4:rd.h = op_readaddr(aa.w + 1);
|
||||
5:last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_addr(0x20) {
|
||||
@@ -94,35 +94,36 @@ jsr_addr(0x20) {
|
||||
jsr_long(0x22) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestack(regs.pc.b);
|
||||
3:op_writestackn(regs.pc.b);
|
||||
4:op_io();
|
||||
5:aa.b = op_readpc();
|
||||
6:regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestackn(regs.pc.h);
|
||||
7:last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.d = uclip<24>(aa.d);
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:op_writestack(regs.pc.h);
|
||||
3:op_writestack(regs.pc.l);
|
||||
2:op_writestackn(regs.pc.h);
|
||||
3:op_writestackn(regs.pc.l);
|
||||
4:aa.h = op_readpc();
|
||||
5:op_io();
|
||||
6:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
7:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.p = op_readstack();
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
@@ -135,7 +136,7 @@ rti(0x40) {
|
||||
}
|
||||
6:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
rts(0x60) {
|
||||
@@ -152,10 +153,11 @@ rts(0x60) {
|
||||
rtl(0x6b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstack();
|
||||
4:rd.h = op_readstack();
|
||||
3:rd.l = op_readstackn();
|
||||
4:rd.h = op_readstackn();
|
||||
5:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
+69
-88
@@ -1,171 +1,157 @@
|
||||
//bcc
|
||||
case 0x90: {
|
||||
void sCPU::op_bcc() {
|
||||
if(!!regs.p.c)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bcs
|
||||
case 0xb0: {
|
||||
void sCPU::op_bcs() {
|
||||
if(!regs.p.c)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.c) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bne
|
||||
case 0xd0: {
|
||||
void sCPU::op_bne() {
|
||||
if(!!regs.p.z)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//beq
|
||||
case 0xf0: {
|
||||
void sCPU::op_beq() {
|
||||
if(!regs.p.z)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.z) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bpl
|
||||
case 0x10: {
|
||||
void sCPU::op_bpl() {
|
||||
if(!!regs.p.n)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bmi
|
||||
case 0x30: {
|
||||
void sCPU::op_bmi() {
|
||||
if(!regs.p.n)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.n) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bvc
|
||||
case 0x50: {
|
||||
void sCPU::op_bvc() {
|
||||
if(!!regs.p.v)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(!regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bvs
|
||||
case 0x70: {
|
||||
void sCPU::op_bvs() {
|
||||
if(!regs.p.v)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.v) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//bra
|
||||
case 0x80: {
|
||||
void sCPU::op_bra() {
|
||||
rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
}
|
||||
|
||||
//brl
|
||||
case 0x82: {
|
||||
void sCPU::op_brl() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//jmp_addr
|
||||
case 0x4c: {
|
||||
void sCPU::op_jmp_addr() {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//jmp_long
|
||||
case 0x5c: {
|
||||
void sCPU::op_jmp_long() {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
} break;
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
//jmp_iaddr
|
||||
case 0x6c: {
|
||||
void sCPU::op_jmp_iaddr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//jmp_iaddrx
|
||||
case 0x7c: {
|
||||
void sCPU::op_jmp_iaddrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
@@ -173,21 +159,19 @@ case 0x7c: {
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//jmp_iladdr
|
||||
case 0xdc: {
|
||||
void sCPU::op_jmp_iladdr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
} break;
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
//jsr_addr
|
||||
case 0x20: {
|
||||
void sCPU::op_jsr_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
@@ -196,43 +180,41 @@ case 0x20: {
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
} break;
|
||||
}
|
||||
|
||||
//jsr_long
|
||||
case 0x22: {
|
||||
void sCPU::op_jsr_long() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestack(regs.pc.b);
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestackn(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.d = uclip<24>(aa.d);
|
||||
} break;
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
//jsr_iaddrx
|
||||
case 0xfc: {
|
||||
void sCPU::op_jsr_iaddrx() {
|
||||
aa.l = op_readpc();
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
//rti
|
||||
case 0x40: {
|
||||
void sCPU::op_rti() {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
regs.acc_8b = (regs.e || regs.p.m);
|
||||
regs.idx_8b = (regs.e || regs.p.x);
|
||||
if(regs.idx_8b) {
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
@@ -241,15 +223,14 @@ case 0x40: {
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
} break;
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
//rts
|
||||
case 0x60: {
|
||||
void sCPU::op_rts() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
@@ -258,17 +239,17 @@ case 0x60: {
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
} break;
|
||||
}
|
||||
|
||||
//rtl
|
||||
case 0x6b: {
|
||||
void sCPU::op_rtl() {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = uclip<24>(rd.d);
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
} break;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
+122
-122
@@ -1,14 +1,14 @@
|
||||
adc_const(0x69, adc, regs.acc_8b),
|
||||
and_const(0x29, and, regs.acc_8b),
|
||||
cmp_const(0xc9, cmp, regs.acc_8b),
|
||||
cpx_const(0xe0, cpx, regs.idx_8b),
|
||||
cpy_const(0xc0, cpy, regs.idx_8b),
|
||||
eor_const(0x49, eor, regs.acc_8b),
|
||||
lda_const(0xa9, lda, regs.acc_8b),
|
||||
ldx_const(0xa2, ldx, regs.idx_8b),
|
||||
ldy_const(0xa0, ldy, regs.idx_8b),
|
||||
ora_const(0x09, ora, regs.acc_8b),
|
||||
sbc_const(0xe9, sbc, regs.acc_8b) {
|
||||
adc_const(0x69, adc, regs.p.m),
|
||||
and_const(0x29, and, regs.p.m),
|
||||
cmp_const(0xc9, cmp, regs.p.m),
|
||||
cpx_const(0xe0, cpx, regs.p.x),
|
||||
cpy_const(0xc0, cpy, regs.p.x),
|
||||
eor_const(0x49, eor, regs.p.m),
|
||||
lda_const(0xa9, lda, regs.p.m),
|
||||
ldx_const(0xa2, ldx, regs.p.x),
|
||||
ldy_const(0xa0, ldy, regs.p.x),
|
||||
ora_const(0x09, ora, regs.p.m),
|
||||
sbc_const(0xe9, sbc, regs.p.m) {
|
||||
1:if($2)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($2) { op_$1_b(); end; }
|
||||
@@ -17,18 +17,18 @@ sbc_const(0xe9, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addr(0x6d, adc, regs.acc_8b),
|
||||
and_addr(0x2d, and, regs.acc_8b),
|
||||
bit_addr(0x2c, bit, regs.acc_8b),
|
||||
cmp_addr(0xcd, cmp, regs.acc_8b),
|
||||
cpx_addr(0xec, cpx, regs.idx_8b),
|
||||
cpy_addr(0xcc, cpy, regs.idx_8b),
|
||||
eor_addr(0x4d, eor, regs.acc_8b),
|
||||
lda_addr(0xad, lda, regs.acc_8b),
|
||||
ldx_addr(0xae, ldx, regs.idx_8b),
|
||||
ldy_addr(0xac, ldy, regs.idx_8b),
|
||||
ora_addr(0x0d, ora, regs.acc_8b),
|
||||
sbc_addr(0xed, sbc, regs.acc_8b) {
|
||||
adc_addr(0x6d, adc, regs.p.m),
|
||||
and_addr(0x2d, and, regs.p.m),
|
||||
bit_addr(0x2c, bit, regs.p.m),
|
||||
cmp_addr(0xcd, cmp, regs.p.m),
|
||||
cpx_addr(0xec, cpx, regs.p.x),
|
||||
cpy_addr(0xcc, cpy, regs.p.x),
|
||||
eor_addr(0x4d, eor, regs.p.m),
|
||||
lda_addr(0xad, lda, regs.p.m),
|
||||
ldx_addr(0xae, ldx, regs.p.x),
|
||||
ldy_addr(0xac, ldy, regs.p.x),
|
||||
ora_addr(0x0d, ora, regs.p.m),
|
||||
sbc_addr(0xed, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($2)last_cycle();
|
||||
@@ -39,15 +39,15 @@ sbc_addr(0xed, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addrx(0x7d, adc, regs.acc_8b),
|
||||
and_addrx(0x3d, and, regs.acc_8b),
|
||||
bit_addrx(0x3c, bit, regs.acc_8b),
|
||||
cmp_addrx(0xdd, cmp, regs.acc_8b),
|
||||
eor_addrx(0x5d, eor, regs.acc_8b),
|
||||
lda_addrx(0xbd, lda, regs.acc_8b),
|
||||
ldy_addrx(0xbc, ldy, regs.idx_8b),
|
||||
ora_addrx(0x1d, ora, regs.acc_8b),
|
||||
sbc_addrx(0xfd, sbc, regs.acc_8b) {
|
||||
adc_addrx(0x7d, adc, regs.p.m),
|
||||
and_addrx(0x3d, and, regs.p.m),
|
||||
bit_addrx(0x3c, bit, regs.p.m),
|
||||
cmp_addrx(0xdd, cmp, regs.p.m),
|
||||
eor_addrx(0x5d, eor, regs.p.m),
|
||||
lda_addrx(0xbd, lda, regs.p.m),
|
||||
ldy_addrx(0xbc, ldy, regs.p.x),
|
||||
ora_addrx(0x1d, ora, regs.p.m),
|
||||
sbc_addrx(0xfd, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
@@ -59,14 +59,14 @@ sbc_addrx(0xfd, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addry(0x79, adc, regs.acc_8b),
|
||||
and_addry(0x39, and, regs.acc_8b),
|
||||
cmp_addry(0xd9, cmp, regs.acc_8b),
|
||||
eor_addry(0x59, eor, regs.acc_8b),
|
||||
lda_addry(0xb9, lda, regs.acc_8b),
|
||||
ldx_addry(0xbe, ldx, regs.idx_8b),
|
||||
ora_addry(0x19, ora, regs.acc_8b),
|
||||
sbc_addry(0xf9, sbc, regs.acc_8b) {
|
||||
adc_addry(0x79, adc, regs.p.m),
|
||||
and_addry(0x39, and, regs.p.m),
|
||||
cmp_addry(0xd9, cmp, regs.p.m),
|
||||
eor_addry(0x59, eor, regs.p.m),
|
||||
lda_addry(0xb9, lda, regs.p.m),
|
||||
ldx_addry(0xbe, ldx, regs.p.x),
|
||||
ora_addry(0x19, ora, regs.p.m),
|
||||
sbc_addry(0xf9, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
@@ -78,13 +78,13 @@ sbc_addry(0xf9, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_long(0x6f, adc, regs.acc_8b),
|
||||
and_long(0x2f, and, regs.acc_8b),
|
||||
cmp_long(0xcf, cmp, regs.acc_8b),
|
||||
eor_long(0x4f, eor, regs.acc_8b),
|
||||
lda_long(0xaf, lda, regs.acc_8b),
|
||||
ora_long(0x0f, ora, regs.acc_8b),
|
||||
sbc_long(0xef, sbc, regs.acc_8b) {
|
||||
adc_long(0x6f, adc, regs.p.m),
|
||||
and_long(0x2f, and, regs.p.m),
|
||||
cmp_long(0xcf, cmp, regs.p.m),
|
||||
eor_long(0x4f, eor, regs.p.m),
|
||||
lda_long(0xaf, lda, regs.p.m),
|
||||
ora_long(0x0f, ora, regs.p.m),
|
||||
sbc_long(0xef, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
@@ -96,13 +96,13 @@ sbc_long(0xef, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_longx(0x7f, adc, regs.acc_8b),
|
||||
and_longx(0x3f, and, regs.acc_8b),
|
||||
cmp_longx(0xdf, cmp, regs.acc_8b),
|
||||
eor_longx(0x5f, eor, regs.acc_8b),
|
||||
lda_longx(0xbf, lda, regs.acc_8b),
|
||||
ora_longx(0x1f, ora, regs.acc_8b),
|
||||
sbc_longx(0xff, sbc, regs.acc_8b) {
|
||||
adc_longx(0x7f, adc, regs.p.m),
|
||||
and_longx(0x3f, and, regs.p.m),
|
||||
cmp_longx(0xdf, cmp, regs.p.m),
|
||||
eor_longx(0x5f, eor, regs.p.m),
|
||||
lda_longx(0xbf, lda, regs.p.m),
|
||||
ora_longx(0x1f, ora, regs.p.m),
|
||||
sbc_longx(0xff, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
@@ -114,18 +114,18 @@ sbc_longx(0xff, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dp(0x65, adc, regs.acc_8b),
|
||||
and_dp(0x25, and, regs.acc_8b),
|
||||
bit_dp(0x24, bit, regs.acc_8b),
|
||||
cmp_dp(0xc5, cmp, regs.acc_8b),
|
||||
cpx_dp(0xe4, cpx, regs.idx_8b),
|
||||
cpy_dp(0xc4, cpy, regs.idx_8b),
|
||||
eor_dp(0x45, eor, regs.acc_8b),
|
||||
lda_dp(0xa5, lda, regs.acc_8b),
|
||||
ldx_dp(0xa6, ldx, regs.idx_8b),
|
||||
ldy_dp(0xa4, ldy, regs.idx_8b),
|
||||
ora_dp(0x05, ora, regs.acc_8b),
|
||||
sbc_dp(0xe5, sbc, regs.acc_8b) {
|
||||
adc_dp(0x65, adc, regs.p.m),
|
||||
and_dp(0x25, and, regs.p.m),
|
||||
bit_dp(0x24, bit, regs.p.m),
|
||||
cmp_dp(0xc5, cmp, regs.p.m),
|
||||
cpx_dp(0xe4, cpx, regs.p.x),
|
||||
cpy_dp(0xc4, cpy, regs.p.x),
|
||||
eor_dp(0x45, eor, regs.p.m),
|
||||
lda_dp(0xa5, lda, regs.p.m),
|
||||
ldx_dp(0xa6, ldx, regs.p.x),
|
||||
ldy_dp(0xa4, ldy, regs.p.x),
|
||||
ora_dp(0x05, ora, regs.p.m),
|
||||
sbc_dp(0xe5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($2)last_cycle();
|
||||
@@ -136,15 +136,15 @@ sbc_dp(0xe5, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dpx(0x75, adc, regs.acc_8b),
|
||||
and_dpx(0x35, and, regs.acc_8b),
|
||||
bit_dpx(0x34, bit, regs.acc_8b),
|
||||
cmp_dpx(0xd5, cmp, regs.acc_8b),
|
||||
eor_dpx(0x55, eor, regs.acc_8b),
|
||||
lda_dpx(0xb5, lda, regs.acc_8b),
|
||||
ldy_dpx(0xb4, ldy, regs.idx_8b),
|
||||
ora_dpx(0x15, ora, regs.acc_8b),
|
||||
sbc_dpx(0xf5, sbc, regs.acc_8b) {
|
||||
adc_dpx(0x75, adc, regs.p.m),
|
||||
and_dpx(0x35, and, regs.p.m),
|
||||
bit_dpx(0x34, bit, regs.p.m),
|
||||
cmp_dpx(0xd5, cmp, regs.p.m),
|
||||
eor_dpx(0x55, eor, regs.p.m),
|
||||
lda_dpx(0xb5, lda, regs.p.m),
|
||||
ldy_dpx(0xb4, ldy, regs.p.x),
|
||||
ora_dpx(0x15, ora, regs.p.m),
|
||||
sbc_dpx(0xf5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
@@ -156,7 +156,7 @@ sbc_dpx(0xf5, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
ldx_dpy(0xb6, ldx, regs.idx_8b) {
|
||||
ldx_dpy(0xb6, ldx, regs.p.x) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
@@ -168,13 +168,13 @@ ldx_dpy(0xb6, ldx, regs.idx_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idp(0x72, adc, regs.acc_8b),
|
||||
and_idp(0x32, and, regs.acc_8b),
|
||||
cmp_idp(0xd2, cmp, regs.acc_8b),
|
||||
eor_idp(0x52, eor, regs.acc_8b),
|
||||
lda_idp(0xb2, lda, regs.acc_8b),
|
||||
ora_idp(0x12, ora, regs.acc_8b),
|
||||
sbc_idp(0xf2, sbc, regs.acc_8b) {
|
||||
adc_idp(0x72, adc, regs.p.m),
|
||||
and_idp(0x32, and, regs.p.m),
|
||||
cmp_idp(0xd2, cmp, regs.p.m),
|
||||
eor_idp(0x52, eor, regs.p.m),
|
||||
lda_idp(0xb2, lda, regs.p.m),
|
||||
ora_idp(0x12, ora, regs.p.m),
|
||||
sbc_idp(0xf2, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
@@ -187,13 +187,13 @@ sbc_idp(0xf2, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpx(0x61, adc, regs.acc_8b),
|
||||
and_idpx(0x21, and, regs.acc_8b),
|
||||
cmp_idpx(0xc1, cmp, regs.acc_8b),
|
||||
eor_idpx(0x41, eor, regs.acc_8b),
|
||||
lda_idpx(0xa1, lda, regs.acc_8b),
|
||||
ora_idpx(0x01, ora, regs.acc_8b),
|
||||
sbc_idpx(0xe1, sbc, regs.acc_8b) {
|
||||
adc_idpx(0x61, adc, regs.p.m),
|
||||
and_idpx(0x21, and, regs.p.m),
|
||||
cmp_idpx(0xc1, cmp, regs.p.m),
|
||||
eor_idpx(0x41, eor, regs.p.m),
|
||||
lda_idpx(0xa1, lda, regs.p.m),
|
||||
ora_idpx(0x01, ora, regs.p.m),
|
||||
sbc_idpx(0xe1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
@@ -207,13 +207,13 @@ sbc_idpx(0xe1, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpy(0x71, adc, regs.acc_8b),
|
||||
and_idpy(0x31, and, regs.acc_8b),
|
||||
cmp_idpy(0xd1, cmp, regs.acc_8b),
|
||||
eor_idpy(0x51, eor, regs.acc_8b),
|
||||
lda_idpy(0xb1, lda, regs.acc_8b),
|
||||
ora_idpy(0x11, ora, regs.acc_8b),
|
||||
sbc_idpy(0xf1, sbc, regs.acc_8b) {
|
||||
adc_idpy(0x71, adc, regs.p.m),
|
||||
and_idpy(0x31, and, regs.p.m),
|
||||
cmp_idpy(0xd1, cmp, regs.p.m),
|
||||
eor_idpy(0x51, eor, regs.p.m),
|
||||
lda_idpy(0xb1, lda, regs.p.m),
|
||||
ora_idpy(0x11, ora, regs.p.m),
|
||||
sbc_idpy(0xf1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
@@ -227,13 +227,13 @@ sbc_idpy(0xf1, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildp(0x67, adc, regs.acc_8b),
|
||||
and_ildp(0x27, and, regs.acc_8b),
|
||||
cmp_ildp(0xc7, cmp, regs.acc_8b),
|
||||
eor_ildp(0x47, eor, regs.acc_8b),
|
||||
lda_ildp(0xa7, lda, regs.acc_8b),
|
||||
ora_ildp(0x07, ora, regs.acc_8b),
|
||||
sbc_ildp(0xe7, sbc, regs.acc_8b) {
|
||||
adc_ildp(0x67, adc, regs.p.m),
|
||||
and_ildp(0x27, and, regs.p.m),
|
||||
cmp_ildp(0xc7, cmp, regs.p.m),
|
||||
eor_ildp(0x47, eor, regs.p.m),
|
||||
lda_ildp(0xa7, lda, regs.p.m),
|
||||
ora_ildp(0x07, ora, regs.p.m),
|
||||
sbc_ildp(0xe7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
@@ -247,13 +247,13 @@ sbc_ildp(0xe7, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildpy(0x77, adc, regs.acc_8b),
|
||||
and_ildpy(0x37, and, regs.acc_8b),
|
||||
cmp_ildpy(0xd7, cmp, regs.acc_8b),
|
||||
eor_ildpy(0x57, eor, regs.acc_8b),
|
||||
lda_ildpy(0xb7, lda, regs.acc_8b),
|
||||
ora_ildpy(0x17, ora, regs.acc_8b),
|
||||
sbc_ildpy(0xf7, sbc, regs.acc_8b) {
|
||||
adc_ildpy(0x77, adc, regs.p.m),
|
||||
and_ildpy(0x37, and, regs.p.m),
|
||||
cmp_ildpy(0xd7, cmp, regs.p.m),
|
||||
eor_ildpy(0x57, eor, regs.p.m),
|
||||
lda_ildpy(0xb7, lda, regs.p.m),
|
||||
ora_ildpy(0x17, ora, regs.p.m),
|
||||
sbc_ildpy(0xf7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
@@ -267,13 +267,13 @@ sbc_ildpy(0xf7, sbc, regs.acc_8b) {
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_sr(0x63, adc, regs.acc_8b),
|
||||
and_sr(0x23, and, regs.acc_8b),
|
||||
cmp_sr(0xc3, cmp, regs.acc_8b),
|
||||
eor_sr(0x43, eor, regs.acc_8b),
|
||||
lda_sr(0xa3, lda, regs.acc_8b),
|
||||
ora_sr(0x03, ora, regs.acc_8b),
|
||||
sbc_sr(0xe3, sbc, regs.acc_8b) {
|
||||
adc_sr(0x63, adc, regs.p.m),
|
||||
and_sr(0x23, and, regs.p.m),
|
||||
cmp_sr(0xc3, cmp, regs.p.m),
|
||||
eor_sr(0x43, eor, regs.p.m),
|
||||
lda_sr(0xa3, lda, regs.p.m),
|
||||
ora_sr(0x03, ora, regs.p.m),
|
||||
sbc_sr(0xe3, sbc, regs.p.m) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if($2)last_cycle();
|
||||
@@ -296,18 +296,18 @@ sbc_isry(0xf3, sbc) {
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.acc_8b)last_cycle();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if(regs.acc_8b) { op_$1_b(); end; }
|
||||
if(regs.p.m) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
bit_const(0x89) {
|
||||
1:if(regs.acc_8b)last_cycle();
|
||||
1:if(regs.p.m)last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
end;
|
||||
}
|
||||
|
||||
+505
-631
File diff suppressed because it is too large.
Load diff
+34
-34
@@ -1,31 +1,31 @@
|
||||
inc(0x1a, regs.acc_8b, a),
|
||||
inx(0xe8, regs.idx_8b, x),
|
||||
iny(0xc8, regs.idx_8b, y) {
|
||||
inc(0x1a, regs.p.m, a),
|
||||
inx(0xe8, regs.p.x, x),
|
||||
iny(0xc8, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = bool(regs.$2.l & 0x80);
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w++;
|
||||
regs.p.n = bool(regs.$2.w & 0x8000);
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
dec(0x3a, regs.acc_8b, a),
|
||||
dex(0xca, regs.idx_8b, x),
|
||||
dey(0x88, regs.idx_8b, y) {
|
||||
dec(0x3a, regs.p.m, a),
|
||||
dex(0xca, regs.p.x, x),
|
||||
dey(0x88, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = bool(regs.$2.l & 0x80);
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w--;
|
||||
regs.p.n = bool(regs.$2.w & 0x8000);
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -33,15 +33,15 @@ dey(0x88, regs.idx_8b, y) {
|
||||
asl(0x0a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -49,15 +49,15 @@ asl(0x0a) {
|
||||
lsr(0x4a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -66,17 +66,17 @@ rol(0x2a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.acc_8b) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -85,19 +85,19 @@ ror(0x6a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
uint16 c;
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
c = (regs.p.c)?0x80:0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
@@ -113,9 +113,9 @@ tsb_addr(0x0c, tsb) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readdbr(aa.w);
|
||||
4:if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
4:if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
5:op_io();
|
||||
if(regs.acc_8b) { op_$1_b(); }
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
6:op_writedbr(aa.w + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
@@ -132,9 +132,9 @@ ror_addrx(0x7e, ror) {
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
5:if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
5:if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
6:op_io();
|
||||
if(regs.acc_8b) { op_$1_b(); }
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
@@ -152,9 +152,9 @@ tsb_dp(0x04, tsb) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:rd.l = op_readdp(dp);
|
||||
4:if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
4:if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
if(regs.acc_8b) { op_$1_b(); }
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
6:op_writedp(dp + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
@@ -171,9 +171,9 @@ ror_dpx(0x76, ror) {
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdp(dp + regs.x.w);
|
||||
5:if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
5:if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:op_io();
|
||||
if(regs.acc_8b) { op_$1_b(); }
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
|
||||
+166
-204
@@ -1,570 +1,532 @@
|
||||
//inc
|
||||
case 0x1a: {
|
||||
void sCPU::op_inc() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.a.l++;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w++;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//inx
|
||||
case 0xe8: {
|
||||
void sCPU::op_inx() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.x.l++;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w++;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//iny
|
||||
case 0xc8: {
|
||||
void sCPU::op_iny() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.y.l++;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w++;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//dec
|
||||
case 0x3a: {
|
||||
void sCPU::op_dec() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.a.l--;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w--;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//dex
|
||||
case 0xca: {
|
||||
void sCPU::op_dex() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.x.l--;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w--;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//dey
|
||||
case 0x88: {
|
||||
void sCPU::op_dey() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.idx_8b) {
|
||||
if(regs.p.x) {
|
||||
regs.y.l--;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w--;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//asl
|
||||
case 0x0a: {
|
||||
void sCPU::op_asl() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//lsr
|
||||
case 0x4a: {
|
||||
void sCPU::op_lsr() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//rol
|
||||
case 0x2a: {
|
||||
void sCPU::op_rol() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.acc_8b) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//ror
|
||||
case 0x6a: {
|
||||
void sCPU::op_ror() {
|
||||
last_cycle();
|
||||
op_io();
|
||||
uint16 c;
|
||||
if(regs.acc_8b) {
|
||||
if(regs.p.m) {
|
||||
c = (regs.p.c)?0x80:0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
//inc_addr
|
||||
case 0xee: {
|
||||
void sCPU::op_inc_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_inc_b(); }
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//dec_addr
|
||||
case 0xce: {
|
||||
void sCPU::op_dec_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_dec_b(); }
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//asl_addr
|
||||
case 0x0e: {
|
||||
void sCPU::op_asl_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_asl_b(); }
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//lsr_addr
|
||||
case 0x4e: {
|
||||
void sCPU::op_lsr_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_lsr_b(); }
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//rol_addr
|
||||
case 0x2e: {
|
||||
void sCPU::op_rol_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_rol_b(); }
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//ror_addr
|
||||
case 0x6e: {
|
||||
void sCPU::op_ror_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_ror_b(); }
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//trb_addr
|
||||
case 0x1c: {
|
||||
void sCPU::op_trb_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_trb_b(); }
|
||||
if(regs.p.m) { op_trb_b(); }
|
||||
else { op_trb_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//tsb_addr
|
||||
case 0x0c: {
|
||||
void sCPU::op_tsb_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_tsb_b(); }
|
||||
if(regs.p.m) { op_tsb_b(); }
|
||||
else { op_tsb_w();
|
||||
op_writedbr(aa.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//inc_addrx
|
||||
case 0xfe: {
|
||||
void sCPU::op_inc_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_inc_b(); }
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//dec_addrx
|
||||
case 0xde: {
|
||||
void sCPU::op_dec_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_dec_b(); }
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//asl_addrx
|
||||
case 0x1e: {
|
||||
void sCPU::op_asl_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_asl_b(); }
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//lsr_addrx
|
||||
case 0x5e: {
|
||||
void sCPU::op_lsr_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_lsr_b(); }
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//rol_addrx
|
||||
case 0x3e: {
|
||||
void sCPU::op_rol_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_rol_b(); }
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//ror_addrx
|
||||
case 0x7e: {
|
||||
void sCPU::op_ror_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_ror_b(); }
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//inc_dp
|
||||
case 0xe6: {
|
||||
void sCPU::op_inc_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_inc_b(); }
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//dec_dp
|
||||
case 0xc6: {
|
||||
void sCPU::op_dec_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_dec_b(); }
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//asl_dp
|
||||
case 0x06: {
|
||||
void sCPU::op_asl_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_asl_b(); }
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//lsr_dp
|
||||
case 0x46: {
|
||||
void sCPU::op_lsr_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_lsr_b(); }
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//rol_dp
|
||||
case 0x26: {
|
||||
void sCPU::op_rol_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_rol_b(); }
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//ror_dp
|
||||
case 0x66: {
|
||||
void sCPU::op_ror_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_ror_b(); }
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//trb_dp
|
||||
case 0x14: {
|
||||
void sCPU::op_trb_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_trb_b(); }
|
||||
if(regs.p.m) { op_trb_b(); }
|
||||
else { op_trb_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//tsb_dp
|
||||
case 0x04: {
|
||||
void sCPU::op_tsb_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_tsb_b(); }
|
||||
if(regs.p.m) { op_tsb_b(); }
|
||||
else { op_tsb_w();
|
||||
op_writedp(dp + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//inc_dpx
|
||||
case 0xf6: {
|
||||
void sCPU::op_inc_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_inc_b(); }
|
||||
if(regs.p.m) { op_inc_b(); }
|
||||
else { op_inc_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//dec_dpx
|
||||
case 0xd6: {
|
||||
void sCPU::op_dec_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_dec_b(); }
|
||||
if(regs.p.m) { op_dec_b(); }
|
||||
else { op_dec_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//asl_dpx
|
||||
case 0x16: {
|
||||
void sCPU::op_asl_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_asl_b(); }
|
||||
if(regs.p.m) { op_asl_b(); }
|
||||
else { op_asl_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//lsr_dpx
|
||||
case 0x56: {
|
||||
void sCPU::op_lsr_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_lsr_b(); }
|
||||
if(regs.p.m) { op_lsr_b(); }
|
||||
else { op_lsr_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//rol_dpx
|
||||
case 0x36: {
|
||||
void sCPU::op_rol_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_rol_b(); }
|
||||
if(regs.p.m) { op_rol_b(); }
|
||||
else { op_rol_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
//ror_dpx
|
||||
case 0x76: {
|
||||
void sCPU::op_ror_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.acc_8b)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b) { op_ror_b(); }
|
||||
if(regs.p.m) { op_ror_b(); }
|
||||
else { op_ror_w();
|
||||
op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
} break;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
sta_addr(0x8d, regs.acc_8b, regs.a.w),
|
||||
stx_addr(0x8e, regs.idx_8b, regs.x.w),
|
||||
sty_addr(0x8c, regs.idx_8b, regs.y.w),
|
||||
stz_addr(0x9c, regs.acc_8b, 0x0000) {
|
||||
sta_addr(0x8d, regs.p.m, regs.a.w),
|
||||
stx_addr(0x8e, regs.p.x, regs.x.w),
|
||||
sty_addr(0x8c, regs.p.x, regs.y.w),
|
||||
stz_addr(0x9c, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($1)last_cycle();
|
||||
@@ -11,8 +11,8 @@ stz_addr(0x9c, regs.acc_8b, 0x0000) {
|
||||
op_writedbr(aa.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addrx(0x9d, regs.acc_8b, regs.a.w),
|
||||
stz_addrx(0x9e, regs.acc_8b, 0x0000) {
|
||||
sta_addrx(0x9d, regs.p.m, regs.a.w),
|
||||
stz_addrx(0x9e, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
@@ -27,9 +27,9 @@ sta_addry(0x99) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if(regs.acc_8b)last_cycle();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -38,9 +38,9 @@ sta_long(0x8f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.acc_8b)last_cycle();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
@@ -49,17 +49,17 @@ sta_longx(0x9f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.acc_8b)last_cycle();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_dp(0x85, regs.acc_8b, regs.a.w),
|
||||
stx_dp(0x86, regs.idx_8b, regs.x.w),
|
||||
sty_dp(0x84, regs.idx_8b, regs.y.w),
|
||||
stz_dp(0x64, regs.acc_8b, 0x0000) {
|
||||
sta_dp(0x85, regs.p.m, regs.a.w),
|
||||
stx_dp(0x86, regs.p.x, regs.x.w),
|
||||
sty_dp(0x84, regs.p.x, regs.y.w),
|
||||
stz_dp(0x64, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($1)last_cycle();
|
||||
@@ -69,9 +69,9 @@ stz_dp(0x64, regs.acc_8b, 0x0000) {
|
||||
op_writedp(dp + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_dpx(0x95, regs.acc_8b, regs.a.w),
|
||||
sty_dpx(0x94, regs.idx_8b, regs.y.w),
|
||||
stz_dpx(0x74, regs.acc_8b, 0x0000) {
|
||||
sta_dpx(0x95, regs.p.m, regs.a.w),
|
||||
sty_dpx(0x94, regs.p.x, regs.y.w),
|
||||
stz_dpx(0x74, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
@@ -86,9 +86,9 @@ stx_dpy(0x96) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if(regs.idx_8b)last_cycle();
|
||||
4:if(regs.p.x)last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.idx_8b)end;
|
||||
if(regs.p.x)end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
}
|
||||
@@ -98,9 +98,9 @@ sta_idp(0x92) {
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if(regs.acc_8b)last_cycle();
|
||||
5:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
6:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -111,9 +111,9 @@ sta_ildp(0x87) {
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.acc_8b)last_cycle();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
@@ -124,9 +124,9 @@ sta_idpx(0x81) {
|
||||
3:op_io();
|
||||
4:aa.l = op_readdp(dp + regs.x.w);
|
||||
5:aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
6:if(regs.acc_8b)last_cycle();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -137,9 +137,9 @@ sta_idpy(0x91) {
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.acc_8b)last_cycle();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -150,9 +150,9 @@ sta_ildpy(0x97) {
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.acc_8b)last_cycle();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -160,9 +160,9 @@ sta_ildpy(0x97) {
|
||||
sta_sr(0x83) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if(regs.acc_8b)last_cycle();
|
||||
3:if(regs.p.m)last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
4:last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
@@ -173,9 +173,9 @@ sta_isry(0x93) {
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.acc_8b)last_cycle();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)end;
|
||||
if(regs.p.m)end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
+96
-120
@@ -1,290 +1,266 @@
|
||||
//sta_addr
|
||||
case 0x8d: {
|
||||
void sCPU::op_sta_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.w);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stx_addr
|
||||
case 0x8e: {
|
||||
void sCPU::op_stx_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedbr(aa.w, regs.x.w);
|
||||
if(regs.idx_8b)break;
|
||||
if(regs.p.x)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.x.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sty_addr
|
||||
case 0x8c: {
|
||||
void sCPU::op_sty_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedbr(aa.w, regs.y.w);
|
||||
if(regs.idx_8b)break;
|
||||
if(regs.p.x)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stz_addr
|
||||
case 0x9c: {
|
||||
void sCPU::op_stz_addr() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, 0x0000);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_addrx
|
||||
case 0x9d: {
|
||||
void sCPU::op_sta_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stz_addrx
|
||||
case 0x9e: {
|
||||
void sCPU::op_stz_addrx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, 0x0000);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_addry
|
||||
case 0x99: {
|
||||
void sCPU::op_sta_addry() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_long
|
||||
case 0x8f: {
|
||||
void sCPU::op_sta_long() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_longx
|
||||
case 0x9f: {
|
||||
void sCPU::op_sta_longx() {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_dp
|
||||
case 0x85: {
|
||||
void sCPU::op_sta_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp, regs.a.w);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stx_dp
|
||||
case 0x86: {
|
||||
void sCPU::op_stx_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp, regs.x.w);
|
||||
if(regs.idx_8b)break;
|
||||
if(regs.p.x)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.x.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sty_dp
|
||||
case 0x84: {
|
||||
void sCPU::op_sty_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp, regs.y.w);
|
||||
if(regs.idx_8b)break;
|
||||
if(regs.p.x)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stz_dp
|
||||
case 0x64: {
|
||||
void sCPU::op_stz_dp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp, 0x0000);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_dpx
|
||||
case 0x95: {
|
||||
void sCPU::op_sta_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.a.w);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sty_dpx
|
||||
case 0x94: {
|
||||
void sCPU::op_sty_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.y.w);
|
||||
if(regs.idx_8b)break;
|
||||
if(regs.p.x)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stz_dpx
|
||||
case 0x74: {
|
||||
void sCPU::op_stz_dpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedp(dp + regs.x.w, 0x0000);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
}
|
||||
|
||||
//stx_dpy
|
||||
case 0x96: {
|
||||
void sCPU::op_stx_dpy() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.idx_8b)last_cycle();
|
||||
if(regs.p.x)last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.idx_8b)break;
|
||||
if(regs.p.x)return;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_idp
|
||||
case 0x92: {
|
||||
void sCPU::op_sta_idp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_ildp
|
||||
case 0x87: {
|
||||
void sCPU::op_sta_ildp() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_idpx
|
||||
case 0x81: {
|
||||
void sCPU::op_sta_idpx() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
aa.l = op_readdp(dp + regs.x.w);
|
||||
aa.h = op_readdp(dp + regs.x.w + 1);
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_idpy
|
||||
case 0x91: {
|
||||
void sCPU::op_sta_idpy() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_ildpy
|
||||
case 0x97: {
|
||||
void sCPU::op_sta_ildpy() {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
aa.b = op_readdp(dp + 2);
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_sr
|
||||
case 0x83: {
|
||||
void sCPU::op_sta_sr() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
//sta_isry
|
||||
case 0x93: {
|
||||
void sCPU::op_sta_isry() {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
if(regs.acc_8b)last_cycle();
|
||||
if(regs.p.m)last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.acc_8b)break;
|
||||
if(regs.p.m)return;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
}
|
||||
|
||||
+54
-58
@@ -23,8 +23,8 @@ int32 r = regs.a.l + rd.l + regs.p.c;
|
||||
r = regs.a.l + rd.l + regs.p.c;
|
||||
regs.p.c = (r > 0xff);
|
||||
}
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.v = bool(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.a.l = r;
|
||||
}
|
||||
@@ -67,135 +67,135 @@ int32 r;
|
||||
r = regs.a.w + rd.w + regs.p.c;
|
||||
regs.p.c = (r > 0xffff);
|
||||
}
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.v = bool(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.a.w = r;
|
||||
}
|
||||
|
||||
inline void sCPU::op_and_b() {
|
||||
regs.a.l &= rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_and_w() {
|
||||
regs.a.w &= rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_b() {
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.v = bool(rd.l & 0x40);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.v = !!(rd.l & 0x40);
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_w() {
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.v = bool(rd.w & 0x4000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.v = !!(rd.w & 0x4000);
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cmp_b() {
|
||||
int32 r = regs.a.l - rd.l;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cmp_w() {
|
||||
int32 r = regs.a.w - rd.w;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpx_b() {
|
||||
int32 r = regs.x.l - rd.l;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpx_w() {
|
||||
int32 r = regs.x.w - rd.w;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpy_b() {
|
||||
int32 r = regs.y.l - rd.l;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpy_w() {
|
||||
int32 r = regs.y.w - rd.w;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_eor_b() {
|
||||
regs.a.l ^= rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_eor_w() {
|
||||
regs.a.w ^= rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lda_b() {
|
||||
regs.a.l = rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lda_w() {
|
||||
regs.a.w = rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldx_b() {
|
||||
regs.x.l = rd.l;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldx_w() {
|
||||
regs.x.w = rd.w;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldy_b() {
|
||||
regs.y.l = rd.l;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldy_w() {
|
||||
regs.y.w = rd.w;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ora_b() {
|
||||
regs.a.l |= rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ora_w() {
|
||||
regs.a.w |= rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
@@ -221,8 +221,8 @@ int32 r;
|
||||
r = regs.a.l - rd.l - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.v = bool((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.a.l = r;
|
||||
}
|
||||
@@ -261,8 +261,8 @@ int32 r;
|
||||
r = regs.a.w - rd.w - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.v = bool((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.a.w = r;
|
||||
}
|
||||
@@ -270,89 +270,85 @@ int32 r;
|
||||
//op_rmw
|
||||
inline void sCPU::op_inc_b() {
|
||||
rd.l++;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_inc_w() {
|
||||
rd.w++;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_b() {
|
||||
rd.l--;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_w() {
|
||||
rd.w--;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_b() {
|
||||
regs.p.c = bool(rd.l & 0x80);
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_w() {
|
||||
regs.p.c = bool(rd.w & 0x8000);
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lsr_b() {
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lsr_w() {
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_b() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = bool(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
uint16 carry = (uint16)regs.p.c;
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l = (rd.l << 1) | carry;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_w() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = bool(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
uint16 carry = (uint16)regs.p.c;
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w = (rd.w << 1) | carry;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_b() {
|
||||
uint16 c = (regs.p.c)?0x80:0;
|
||||
uint16 carry = (uint16)regs.p.c << 7;
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
rd.l = carry | (rd.l >> 1);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_w() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
uint16 carry = (uint16)regs.p.c << 15;
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
rd.w = carry | (rd.w >> 1);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
optbl[0x69] = &sCPU::op_adc_const;
|
||||
optbl[0x29] = &sCPU::op_and_const;
|
||||
optbl[0xc9] = &sCPU::op_cmp_const;
|
||||
optbl[0xe0] = &sCPU::op_cpx_const;
|
||||
optbl[0xc0] = &sCPU::op_cpy_const;
|
||||
optbl[0x49] = &sCPU::op_eor_const;
|
||||
optbl[0xa9] = &sCPU::op_lda_const;
|
||||
optbl[0xa2] = &sCPU::op_ldx_const;
|
||||
optbl[0xa0] = &sCPU::op_ldy_const;
|
||||
optbl[0x09] = &sCPU::op_ora_const;
|
||||
optbl[0xe9] = &sCPU::op_sbc_const;
|
||||
optbl[0x6d] = &sCPU::op_adc_addr;
|
||||
optbl[0x2d] = &sCPU::op_and_addr;
|
||||
optbl[0x2c] = &sCPU::op_bit_addr;
|
||||
optbl[0xcd] = &sCPU::op_cmp_addr;
|
||||
optbl[0xec] = &sCPU::op_cpx_addr;
|
||||
optbl[0xcc] = &sCPU::op_cpy_addr;
|
||||
optbl[0x4d] = &sCPU::op_eor_addr;
|
||||
optbl[0xad] = &sCPU::op_lda_addr;
|
||||
optbl[0xae] = &sCPU::op_ldx_addr;
|
||||
optbl[0xac] = &sCPU::op_ldy_addr;
|
||||
optbl[0x0d] = &sCPU::op_ora_addr;
|
||||
optbl[0xed] = &sCPU::op_sbc_addr;
|
||||
optbl[0x7d] = &sCPU::op_adc_addrx;
|
||||
optbl[0x3d] = &sCPU::op_and_addrx;
|
||||
optbl[0x3c] = &sCPU::op_bit_addrx;
|
||||
optbl[0xdd] = &sCPU::op_cmp_addrx;
|
||||
optbl[0x5d] = &sCPU::op_eor_addrx;
|
||||
optbl[0xbd] = &sCPU::op_lda_addrx;
|
||||
optbl[0xbc] = &sCPU::op_ldy_addrx;
|
||||
optbl[0x1d] = &sCPU::op_ora_addrx;
|
||||
optbl[0xfd] = &sCPU::op_sbc_addrx;
|
||||
optbl[0x79] = &sCPU::op_adc_addry;
|
||||
optbl[0x39] = &sCPU::op_and_addry;
|
||||
optbl[0xd9] = &sCPU::op_cmp_addry;
|
||||
optbl[0x59] = &sCPU::op_eor_addry;
|
||||
optbl[0xb9] = &sCPU::op_lda_addry;
|
||||
optbl[0xbe] = &sCPU::op_ldx_addry;
|
||||
optbl[0x19] = &sCPU::op_ora_addry;
|
||||
optbl[0xf9] = &sCPU::op_sbc_addry;
|
||||
optbl[0x6f] = &sCPU::op_adc_long;
|
||||
optbl[0x2f] = &sCPU::op_and_long;
|
||||
optbl[0xcf] = &sCPU::op_cmp_long;
|
||||
optbl[0x4f] = &sCPU::op_eor_long;
|
||||
optbl[0xaf] = &sCPU::op_lda_long;
|
||||
optbl[0x0f] = &sCPU::op_ora_long;
|
||||
optbl[0xef] = &sCPU::op_sbc_long;
|
||||
optbl[0x7f] = &sCPU::op_adc_longx;
|
||||
optbl[0x3f] = &sCPU::op_and_longx;
|
||||
optbl[0xdf] = &sCPU::op_cmp_longx;
|
||||
optbl[0x5f] = &sCPU::op_eor_longx;
|
||||
optbl[0xbf] = &sCPU::op_lda_longx;
|
||||
optbl[0x1f] = &sCPU::op_ora_longx;
|
||||
optbl[0xff] = &sCPU::op_sbc_longx;
|
||||
optbl[0x65] = &sCPU::op_adc_dp;
|
||||
optbl[0x25] = &sCPU::op_and_dp;
|
||||
optbl[0x24] = &sCPU::op_bit_dp;
|
||||
optbl[0xc5] = &sCPU::op_cmp_dp;
|
||||
optbl[0xe4] = &sCPU::op_cpx_dp;
|
||||
optbl[0xc4] = &sCPU::op_cpy_dp;
|
||||
optbl[0x45] = &sCPU::op_eor_dp;
|
||||
optbl[0xa5] = &sCPU::op_lda_dp;
|
||||
optbl[0xa6] = &sCPU::op_ldx_dp;
|
||||
optbl[0xa4] = &sCPU::op_ldy_dp;
|
||||
optbl[0x05] = &sCPU::op_ora_dp;
|
||||
optbl[0xe5] = &sCPU::op_sbc_dp;
|
||||
optbl[0x75] = &sCPU::op_adc_dpx;
|
||||
optbl[0x35] = &sCPU::op_and_dpx;
|
||||
optbl[0x34] = &sCPU::op_bit_dpx;
|
||||
optbl[0xd5] = &sCPU::op_cmp_dpx;
|
||||
optbl[0x55] = &sCPU::op_eor_dpx;
|
||||
optbl[0xb5] = &sCPU::op_lda_dpx;
|
||||
optbl[0xb4] = &sCPU::op_ldy_dpx;
|
||||
optbl[0x15] = &sCPU::op_ora_dpx;
|
||||
optbl[0xf5] = &sCPU::op_sbc_dpx;
|
||||
optbl[0xb6] = &sCPU::op_ldx_dpy;
|
||||
optbl[0x72] = &sCPU::op_adc_idp;
|
||||
optbl[0x32] = &sCPU::op_and_idp;
|
||||
optbl[0xd2] = &sCPU::op_cmp_idp;
|
||||
optbl[0x52] = &sCPU::op_eor_idp;
|
||||
optbl[0xb2] = &sCPU::op_lda_idp;
|
||||
optbl[0x12] = &sCPU::op_ora_idp;
|
||||
optbl[0xf2] = &sCPU::op_sbc_idp;
|
||||
optbl[0x61] = &sCPU::op_adc_idpx;
|
||||
optbl[0x21] = &sCPU::op_and_idpx;
|
||||
optbl[0xc1] = &sCPU::op_cmp_idpx;
|
||||
optbl[0x41] = &sCPU::op_eor_idpx;
|
||||
optbl[0xa1] = &sCPU::op_lda_idpx;
|
||||
optbl[0x01] = &sCPU::op_ora_idpx;
|
||||
optbl[0xe1] = &sCPU::op_sbc_idpx;
|
||||
optbl[0x71] = &sCPU::op_adc_idpy;
|
||||
optbl[0x31] = &sCPU::op_and_idpy;
|
||||
optbl[0xd1] = &sCPU::op_cmp_idpy;
|
||||
optbl[0x51] = &sCPU::op_eor_idpy;
|
||||
optbl[0xb1] = &sCPU::op_lda_idpy;
|
||||
optbl[0x11] = &sCPU::op_ora_idpy;
|
||||
optbl[0xf1] = &sCPU::op_sbc_idpy;
|
||||
optbl[0x67] = &sCPU::op_adc_ildp;
|
||||
optbl[0x27] = &sCPU::op_and_ildp;
|
||||
optbl[0xc7] = &sCPU::op_cmp_ildp;
|
||||
optbl[0x47] = &sCPU::op_eor_ildp;
|
||||
optbl[0xa7] = &sCPU::op_lda_ildp;
|
||||
optbl[0x07] = &sCPU::op_ora_ildp;
|
||||
optbl[0xe7] = &sCPU::op_sbc_ildp;
|
||||
optbl[0x77] = &sCPU::op_adc_ildpy;
|
||||
optbl[0x37] = &sCPU::op_and_ildpy;
|
||||
optbl[0xd7] = &sCPU::op_cmp_ildpy;
|
||||
optbl[0x57] = &sCPU::op_eor_ildpy;
|
||||
optbl[0xb7] = &sCPU::op_lda_ildpy;
|
||||
optbl[0x17] = &sCPU::op_ora_ildpy;
|
||||
optbl[0xf7] = &sCPU::op_sbc_ildpy;
|
||||
optbl[0x63] = &sCPU::op_adc_sr;
|
||||
optbl[0x23] = &sCPU::op_and_sr;
|
||||
optbl[0xc3] = &sCPU::op_cmp_sr;
|
||||
optbl[0x43] = &sCPU::op_eor_sr;
|
||||
optbl[0xa3] = &sCPU::op_lda_sr;
|
||||
optbl[0x03] = &sCPU::op_ora_sr;
|
||||
optbl[0xe3] = &sCPU::op_sbc_sr;
|
||||
optbl[0x73] = &sCPU::op_adc_isry;
|
||||
optbl[0x33] = &sCPU::op_and_isry;
|
||||
optbl[0xd3] = &sCPU::op_cmp_isry;
|
||||
optbl[0x53] = &sCPU::op_eor_isry;
|
||||
optbl[0xb3] = &sCPU::op_lda_isry;
|
||||
optbl[0x13] = &sCPU::op_ora_isry;
|
||||
optbl[0xf3] = &sCPU::op_sbc_isry;
|
||||
optbl[0x89] = &sCPU::op_bit_const;
|
||||
optbl[0x8d] = &sCPU::op_sta_addr;
|
||||
optbl[0x8e] = &sCPU::op_stx_addr;
|
||||
optbl[0x8c] = &sCPU::op_sty_addr;
|
||||
optbl[0x9c] = &sCPU::op_stz_addr;
|
||||
optbl[0x9d] = &sCPU::op_sta_addrx;
|
||||
optbl[0x9e] = &sCPU::op_stz_addrx;
|
||||
optbl[0x99] = &sCPU::op_sta_addry;
|
||||
optbl[0x8f] = &sCPU::op_sta_long;
|
||||
optbl[0x9f] = &sCPU::op_sta_longx;
|
||||
optbl[0x85] = &sCPU::op_sta_dp;
|
||||
optbl[0x86] = &sCPU::op_stx_dp;
|
||||
optbl[0x84] = &sCPU::op_sty_dp;
|
||||
optbl[0x64] = &sCPU::op_stz_dp;
|
||||
optbl[0x95] = &sCPU::op_sta_dpx;
|
||||
optbl[0x94] = &sCPU::op_sty_dpx;
|
||||
optbl[0x74] = &sCPU::op_stz_dpx;
|
||||
optbl[0x96] = &sCPU::op_stx_dpy;
|
||||
optbl[0x92] = &sCPU::op_sta_idp;
|
||||
optbl[0x87] = &sCPU::op_sta_ildp;
|
||||
optbl[0x81] = &sCPU::op_sta_idpx;
|
||||
optbl[0x91] = &sCPU::op_sta_idpy;
|
||||
optbl[0x97] = &sCPU::op_sta_ildpy;
|
||||
optbl[0x83] = &sCPU::op_sta_sr;
|
||||
optbl[0x93] = &sCPU::op_sta_isry;
|
||||
optbl[0x1a] = &sCPU::op_inc;
|
||||
optbl[0xe8] = &sCPU::op_inx;
|
||||
optbl[0xc8] = &sCPU::op_iny;
|
||||
optbl[0x3a] = &sCPU::op_dec;
|
||||
optbl[0xca] = &sCPU::op_dex;
|
||||
optbl[0x88] = &sCPU::op_dey;
|
||||
optbl[0x0a] = &sCPU::op_asl;
|
||||
optbl[0x4a] = &sCPU::op_lsr;
|
||||
optbl[0x2a] = &sCPU::op_rol;
|
||||
optbl[0x6a] = &sCPU::op_ror;
|
||||
optbl[0xee] = &sCPU::op_inc_addr;
|
||||
optbl[0xce] = &sCPU::op_dec_addr;
|
||||
optbl[0x0e] = &sCPU::op_asl_addr;
|
||||
optbl[0x4e] = &sCPU::op_lsr_addr;
|
||||
optbl[0x2e] = &sCPU::op_rol_addr;
|
||||
optbl[0x6e] = &sCPU::op_ror_addr;
|
||||
optbl[0x1c] = &sCPU::op_trb_addr;
|
||||
optbl[0x0c] = &sCPU::op_tsb_addr;
|
||||
optbl[0xfe] = &sCPU::op_inc_addrx;
|
||||
optbl[0xde] = &sCPU::op_dec_addrx;
|
||||
optbl[0x1e] = &sCPU::op_asl_addrx;
|
||||
optbl[0x5e] = &sCPU::op_lsr_addrx;
|
||||
optbl[0x3e] = &sCPU::op_rol_addrx;
|
||||
optbl[0x7e] = &sCPU::op_ror_addrx;
|
||||
optbl[0xe6] = &sCPU::op_inc_dp;
|
||||
optbl[0xc6] = &sCPU::op_dec_dp;
|
||||
optbl[0x06] = &sCPU::op_asl_dp;
|
||||
optbl[0x46] = &sCPU::op_lsr_dp;
|
||||
optbl[0x26] = &sCPU::op_rol_dp;
|
||||
optbl[0x66] = &sCPU::op_ror_dp;
|
||||
optbl[0x14] = &sCPU::op_trb_dp;
|
||||
optbl[0x04] = &sCPU::op_tsb_dp;
|
||||
optbl[0xf6] = &sCPU::op_inc_dpx;
|
||||
optbl[0xd6] = &sCPU::op_dec_dpx;
|
||||
optbl[0x16] = &sCPU::op_asl_dpx;
|
||||
optbl[0x56] = &sCPU::op_lsr_dpx;
|
||||
optbl[0x36] = &sCPU::op_rol_dpx;
|
||||
optbl[0x76] = &sCPU::op_ror_dpx;
|
||||
optbl[0x90] = &sCPU::op_bcc;
|
||||
optbl[0xb0] = &sCPU::op_bcs;
|
||||
optbl[0xd0] = &sCPU::op_bne;
|
||||
optbl[0xf0] = &sCPU::op_beq;
|
||||
optbl[0x10] = &sCPU::op_bpl;
|
||||
optbl[0x30] = &sCPU::op_bmi;
|
||||
optbl[0x50] = &sCPU::op_bvc;
|
||||
optbl[0x70] = &sCPU::op_bvs;
|
||||
optbl[0x80] = &sCPU::op_bra;
|
||||
optbl[0x82] = &sCPU::op_brl;
|
||||
optbl[0x4c] = &sCPU::op_jmp_addr;
|
||||
optbl[0x5c] = &sCPU::op_jmp_long;
|
||||
optbl[0x6c] = &sCPU::op_jmp_iaddr;
|
||||
optbl[0x7c] = &sCPU::op_jmp_iaddrx;
|
||||
optbl[0xdc] = &sCPU::op_jmp_iladdr;
|
||||
optbl[0x20] = &sCPU::op_jsr_addr;
|
||||
optbl[0x22] = &sCPU::op_jsr_long;
|
||||
optbl[0xfc] = &sCPU::op_jsr_iaddrx;
|
||||
optbl[0x40] = &sCPU::op_rti;
|
||||
optbl[0x60] = &sCPU::op_rts;
|
||||
optbl[0x6b] = &sCPU::op_rtl;
|
||||
optbl[0xea] = &sCPU::op_nop;
|
||||
optbl[0x42] = &sCPU::op_wdm;
|
||||
optbl[0xeb] = &sCPU::op_xba;
|
||||
optbl[0x54] = &sCPU::op_mvn;
|
||||
optbl[0x44] = &sCPU::op_mvp;
|
||||
optbl[0x00] = &sCPU::op_brk;
|
||||
optbl[0x02] = &sCPU::op_cop;
|
||||
optbl[0xdb] = &sCPU::op_stp;
|
||||
optbl[0xcb] = &sCPU::op_wai;
|
||||
optbl[0xfb] = &sCPU::op_xce;
|
||||
optbl[0x18] = &sCPU::op_clc;
|
||||
optbl[0xd8] = &sCPU::op_cld;
|
||||
optbl[0x58] = &sCPU::op_cli;
|
||||
optbl[0xb8] = &sCPU::op_clv;
|
||||
optbl[0x38] = &sCPU::op_sec;
|
||||
optbl[0xf8] = &sCPU::op_sed;
|
||||
optbl[0x78] = &sCPU::op_sei;
|
||||
optbl[0xc2] = &sCPU::op_rep;
|
||||
optbl[0xe2] = &sCPU::op_sep;
|
||||
optbl[0xaa] = &sCPU::op_tax;
|
||||
optbl[0xa8] = &sCPU::op_tay;
|
||||
optbl[0x8a] = &sCPU::op_txa;
|
||||
optbl[0x9b] = &sCPU::op_txy;
|
||||
optbl[0x98] = &sCPU::op_tya;
|
||||
optbl[0xbb] = &sCPU::op_tyx;
|
||||
optbl[0x5b] = &sCPU::op_tcd;
|
||||
optbl[0x1b] = &sCPU::op_tcs;
|
||||
optbl[0x7b] = &sCPU::op_tdc;
|
||||
optbl[0x3b] = &sCPU::op_tsc;
|
||||
optbl[0xba] = &sCPU::op_tsx;
|
||||
optbl[0x9a] = &sCPU::op_txs;
|
||||
optbl[0x48] = &sCPU::op_pha;
|
||||
optbl[0xda] = &sCPU::op_phx;
|
||||
optbl[0x5a] = &sCPU::op_phy;
|
||||
optbl[0x0b] = &sCPU::op_phd;
|
||||
optbl[0x8b] = &sCPU::op_phb;
|
||||
optbl[0x4b] = &sCPU::op_phk;
|
||||
optbl[0x08] = &sCPU::op_php;
|
||||
optbl[0x68] = &sCPU::op_pla;
|
||||
optbl[0xfa] = &sCPU::op_plx;
|
||||
optbl[0x7a] = &sCPU::op_ply;
|
||||
optbl[0x2b] = &sCPU::op_pld;
|
||||
optbl[0xab] = &sCPU::op_plb;
|
||||
optbl[0x28] = &sCPU::op_plp;
|
||||
optbl[0xf4] = &sCPU::op_pea;
|
||||
optbl[0xd4] = &sCPU::op_pei;
|
||||
optbl[0x62] = &sCPU::op_per;
|
||||
@@ -1,9 +1,9 @@
|
||||
#define CLASS_NAME "sCPU"
|
||||
#include "../../../lib/opgen_s.cpp"
|
||||
#include "../../../lib/opgen_so.cpp"
|
||||
|
||||
int main() {
|
||||
//fph = fopen("op.h", "wb");
|
||||
//fpt = fopen("optable.cpp", "wb");
|
||||
fph = fopen("op.h", "wb");
|
||||
fpt = fopen("optable.cpp", "wb");
|
||||
|
||||
generate("op_read.cpp", "op_read.b");
|
||||
generate("op_write.cpp", "op_write.b");
|
||||
@@ -11,8 +11,8 @@ int main() {
|
||||
generate("op_pc.cpp", "op_pc.b");
|
||||
generate("op_misc.cpp", "op_misc.b");
|
||||
|
||||
//fclose(fph);
|
||||
//fclose(fpt);
|
||||
fclose(fph);
|
||||
fclose(fpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+15
-14
@@ -1,3 +1,8 @@
|
||||
void sCPU::dma_add_clocks(uint clocks) {
|
||||
status.dma_clocks += clocks;
|
||||
add_clocks(clocks);
|
||||
}
|
||||
|
||||
/*****
|
||||
* used by both DMA and HDMA
|
||||
*
|
||||
@@ -29,9 +34,7 @@ uint8 r;
|
||||
r_mem->write(abus, r);
|
||||
}
|
||||
|
||||
status.dma_clocks += 8;
|
||||
add_clocks(8);
|
||||
co_return();
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
@@ -105,8 +108,7 @@ inline void sCPU::dma_write(uint8 i, uint8 index) {
|
||||
void sCPU::dma_run() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].dma_enabled == false)continue;
|
||||
status.dma_clocks += 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(cartridge.info.sdd1 == true) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
@@ -130,7 +132,7 @@ void sCPU::dma_run() {
|
||||
channel[i].dma_enabled = false;
|
||||
}
|
||||
|
||||
counter_set(counter.irq_delay, 24);
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
/*****
|
||||
@@ -167,19 +169,19 @@ uint8 r = 0;
|
||||
|
||||
void sCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
|
||||
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +191,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(hdma_active(i) == false)continue;
|
||||
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
@@ -198,8 +200,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
dma_transfer(channel[i].direction, dma_bbus(i, index),
|
||||
!channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i));
|
||||
} else {
|
||||
add_clocks(8);
|
||||
co_return();
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
}
|
||||
}
|
||||
@@ -212,7 +213,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
}
|
||||
}
|
||||
|
||||
counter_set(counter.irq_delay, 24);
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
void sCPU::hdma_init_reset() {
|
||||
@@ -231,7 +232,7 @@ void sCPU::hdma_init() {
|
||||
hdma_update(i);
|
||||
}
|
||||
|
||||
counter_set(counter.irq_delay, 24);
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
/*****
|
||||
|
||||
@@ -45,6 +45,7 @@ struct {
|
||||
bool hdma_do_transfer;
|
||||
} channel[8];
|
||||
|
||||
void dma_add_clocks(uint clocks);
|
||||
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
||||
|
||||
uint8 dma_bbus(uint8 i, uint8 index);
|
||||
|
||||
@@ -10,7 +10,6 @@ void sCPU::op_io() {
|
||||
status.clock_count = 6;
|
||||
precycle_edge();
|
||||
add_clocks(6);
|
||||
//co_return();
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
@@ -18,9 +17,6 @@ uint8 sCPU::op_read(uint32 addr) {
|
||||
status.clock_count = r_mem->speed(addr);
|
||||
precycle_edge();
|
||||
add_clocks(status.clock_count - 4);
|
||||
#ifdef FAVOR_ACCURACY
|
||||
co_return();
|
||||
#endif
|
||||
regs.mdr = r_mem->read(addr);
|
||||
add_clocks(4);
|
||||
cycle_edge();
|
||||
@@ -31,10 +27,95 @@ void sCPU::op_write(uint32 addr, uint8 data) {
|
||||
status.clock_count = r_mem->speed(addr);
|
||||
precycle_edge();
|
||||
add_clocks(status.clock_count);
|
||||
#ifdef FAVOR_ACCURACY
|
||||
co_return();
|
||||
#endif
|
||||
regs.mdr = data;
|
||||
r_mem->write(addr, regs.mdr);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline uint8 sCPU::op_readpc() {
|
||||
return op_read((regs.pc.b << 16) + regs.pc.w++);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readstack() {
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
}
|
||||
return op_read(regs.s.w);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readstackn() {
|
||||
return op_read(++regs.s.w);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readaddr(uint32 addr) {
|
||||
return op_read(addr & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readlong(uint32 addr) {
|
||||
return op_read(addr & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readdbr(uint32 addr) {
|
||||
return op_read(((regs.db << 16) + addr) & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readpbr(uint32 addr) {
|
||||
return op_read((regs.pc.b << 16) + (addr & 0xffff));
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readdp(uint32 addr) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
|
||||
} else {
|
||||
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readsp(uint32 addr) {
|
||||
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writestack(uint8 data) {
|
||||
op_write(regs.s.w, data);
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writestackn(uint8 data) {
|
||||
op_write(regs.s.w--, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writeaddr(uint32 addr, uint8 data) {
|
||||
op_write(addr & 0xffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writelong(uint32 addr, uint8 data) {
|
||||
op_write(addr & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writedbr(uint32 addr, uint8 data) {
|
||||
op_write(((regs.db << 16) + addr) & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writepbr(uint32 addr, uint8 data) {
|
||||
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
|
||||
} else {
|
||||
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
|
||||
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
@@ -15,19 +15,21 @@ uint8 apu_port[4];
|
||||
/*****
|
||||
* helper memory addressing functions used by CPU core
|
||||
*****/
|
||||
uint8 op_readpc () { return op_read((regs.pc.b << 16) + regs.pc.w++); }
|
||||
uint8 op_readstack() { (regs.e) ? regs.s.l++ : regs.s.w++; return op_read(regs.s.w); }
|
||||
uint8 op_readaddr (uint32 addr) { return op_read(addr & 0xffff); }
|
||||
uint8 op_readlong (uint32 addr) { return op_read(addr & 0xffffff); }
|
||||
uint8 op_readdbr (uint32 addr) { return op_read(((regs.db << 16) + addr) & 0xffffff); }
|
||||
uint8 op_readpbr (uint32 addr) { return op_read((regs.pc.b << 16) + (addr & 0xffff)); }
|
||||
uint8 op_readdp (uint32 addr) { return op_read((regs.d + (addr & 0xffff)) & 0xffff); }
|
||||
uint8 op_readsp (uint32 addr) { return op_read((regs.s + (addr & 0xffff)) & 0xffff); }
|
||||
uint8 op_readpc ();
|
||||
uint8 op_readstack ();
|
||||
uint8 op_readstackn();
|
||||
uint8 op_readaddr (uint32 addr);
|
||||
uint8 op_readlong (uint32 addr);
|
||||
uint8 op_readdbr (uint32 addr);
|
||||
uint8 op_readpbr (uint32 addr);
|
||||
uint8 op_readdp (uint32 addr);
|
||||
uint8 op_readsp (uint32 addr);
|
||||
|
||||
void op_writestack(uint8 data) { op_write(regs.s.w, data); (regs.e) ? regs.s.l-- : regs.s.w--; }
|
||||
void op_writeaddr (uint32 addr, uint8 data) { op_write(addr & 0xffff, data); }
|
||||
void op_writelong (uint32 addr, uint8 data) { op_write(addr & 0xffffff, data); }
|
||||
void op_writedbr (uint32 addr, uint8 data) { op_write(((regs.db << 16) + addr) & 0xffffff, data); }
|
||||
void op_writepbr (uint32 addr, uint8 data) { op_write((regs.pc.b << 16) + (addr & 0xffff), data); }
|
||||
void op_writedp (uint32 addr, uint8 data) { op_write((regs.d + (addr & 0xffff)) & 0xffff, data); }
|
||||
void op_writesp (uint32 addr, uint8 data) { op_write((regs.s + (addr & 0xffff)) & 0xffff, data); }
|
||||
void op_writestack (uint8 data);
|
||||
void op_writestackn(uint8 data);
|
||||
void op_writeaddr (uint32 addr, uint8 data);
|
||||
void op_writelong (uint32 addr, uint8 data);
|
||||
void op_writedbr (uint32 addr, uint8 data);
|
||||
void op_writepbr (uint32 addr, uint8 data);
|
||||
void op_writedp (uint32 addr, uint8 data);
|
||||
void op_writesp (uint32 addr, uint8 data);
|
||||
+14
-75
@@ -41,7 +41,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
||||
status.joypad_strobe_latch = !!(data & 1);
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
snes->poll_input();
|
||||
snes.poll_input();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
||||
//realtime or buffered status of joypadN.b
|
||||
uint8 sCPU::mmio_r4016() {
|
||||
uint8 r = regs.mdr & 0xfc;
|
||||
r |= (uint8)snes->port_read(0);
|
||||
r |= (uint8)snes.port_read(0);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -63,43 +63,14 @@ uint8 r = regs.mdr & 0xfc;
|
||||
//1-0 = Joypad serial data
|
||||
uint8 sCPU::mmio_r4017() {
|
||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||
r |= (uint8)snes->port_read(1);
|
||||
r |= (uint8)snes.port_read(1);
|
||||
return r;
|
||||
}
|
||||
|
||||
//NMITIMEN
|
||||
void sCPU::mmio_w4200(uint8 data) {
|
||||
status.nmi_enabled = !!(data & 0x80);
|
||||
status.virq_enabled = !!(data & 0x20);
|
||||
status.hirq_enabled = !!(data & 0x10);
|
||||
status.auto_joypad_poll = !!(data & 0x01);
|
||||
|
||||
if(status.nmi_read == 0) {
|
||||
if(status.nmi_line == 1 && status.nmi_enabled == 1) {
|
||||
status.nmi_transition = 1;
|
||||
}
|
||||
status.nmi_line = !status.nmi_enabled;
|
||||
}
|
||||
|
||||
if(status.irq_read == 0) {
|
||||
if(status.irq_line == 1 && (status.virq_enabled || status.hirq_enabled)) {
|
||||
status.irq_transition = 1;
|
||||
}
|
||||
status.irq_line = !(status.virq_enabled || status.hirq_enabled);
|
||||
}
|
||||
|
||||
if(status.virq_enabled == true && status.hirq_enabled == false) {
|
||||
status.irq_lock = false;
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
status.irq_line = 1;
|
||||
status.irq_read = 1;
|
||||
status.irq_transition = 0;
|
||||
}
|
||||
|
||||
update_interrupts();
|
||||
counter_set(counter.irq_delay, 2);
|
||||
nmitimen_update(data);
|
||||
}
|
||||
|
||||
//WRIO
|
||||
@@ -119,7 +90,7 @@ void sCPU::mmio_w4202(uint8 data) {
|
||||
void sCPU::mmio_w4203(uint8 data) {
|
||||
status.mul_b = data;
|
||||
status.r4216 = status.mul_a * status.mul_b;
|
||||
//counter_set(counter.hw_math, 48);
|
||||
//counter.set(counter.hw_math, 48);
|
||||
}
|
||||
|
||||
//WRDIVL
|
||||
@@ -137,51 +108,35 @@ void sCPU::mmio_w4206(uint8 data) {
|
||||
status.div_b = data;
|
||||
status.r4214 = (status.div_b) ? status.div_a / status.div_b : 0xffff;
|
||||
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
|
||||
//counter_set(counter.hw_math, 96);
|
||||
//counter.set(counter.hw_math, 96);
|
||||
}
|
||||
|
||||
//HTIMEL
|
||||
void sCPU::mmio_w4207(uint8 data) {
|
||||
status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
|
||||
status.hirq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
|
||||
hvtime_update(0x4207);
|
||||
}
|
||||
|
||||
//HTIMEH
|
||||
void sCPU::mmio_w4208(uint8 data) {
|
||||
status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
|
||||
status.hirq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
|
||||
hvtime_update(0x4208);
|
||||
}
|
||||
|
||||
//VTIMEL
|
||||
void sCPU::mmio_w4209(uint8 data) {
|
||||
status.virq_pos = (status.virq_pos & ~0xff) | (data);
|
||||
status.virq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
|
||||
hvtime_update(0x4209);
|
||||
}
|
||||
|
||||
//VTIMEH
|
||||
void sCPU::mmio_w420a(uint8 data) {
|
||||
status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
|
||||
status.virq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
|
||||
hvtime_update(0x420a);
|
||||
}
|
||||
|
||||
//DMAEN
|
||||
@@ -213,12 +168,7 @@ void sCPU::mmio_w420d(uint8 data) {
|
||||
//3-0 = CPU (5a22) version
|
||||
uint8 sCPU::mmio_r4210() {
|
||||
uint8 r = (regs.mdr & 0x70);
|
||||
r |= (uint8)(!status.nmi_read) << 7;
|
||||
|
||||
if(!counter.nmi_fire) {
|
||||
status.nmi_read = 1;
|
||||
}
|
||||
|
||||
r |= (uint8)(rdnmi()) << 7;
|
||||
r |= (cpu_version & 0x0f);
|
||||
return r;
|
||||
}
|
||||
@@ -228,14 +178,7 @@ uint8 r = (regs.mdr & 0x70);
|
||||
//6-0 = MDR
|
||||
uint8 sCPU::mmio_r4211() {
|
||||
uint8 r = (regs.mdr & 0x7f);
|
||||
r |= (uint8)(!status.irq_read) << 7;
|
||||
|
||||
if(!counter.irq_fire) {
|
||||
status.irq_read = 1;
|
||||
status.irq_line = 1;
|
||||
status.irq_transition = 0;
|
||||
}
|
||||
|
||||
r |= (uint8)(timeup()) << 7;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -479,9 +422,7 @@ void sCPU::mmio_reset() {
|
||||
uint8 sCPU::mmio_read(uint16 addr) {
|
||||
//APU
|
||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||
#ifdef FAVOR_SPEED
|
||||
co_return();
|
||||
#endif
|
||||
scheduler.sync_cpusmp();
|
||||
return r_smp->port_read(addr & 3);
|
||||
}
|
||||
|
||||
@@ -536,9 +477,7 @@ uint8 sCPU::mmio_read(uint16 addr) {
|
||||
void sCPU::mmio_write(uint16 addr, uint8 data) {
|
||||
//APU
|
||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||
#ifdef FAVOR_SPEED
|
||||
co_return();
|
||||
#endif
|
||||
scheduler.sync_cpusmp();
|
||||
port_write(addr & 3, data);
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-18
@@ -6,16 +6,8 @@
|
||||
#include "mmio/mmio.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
void scpu_entry_point() {
|
||||
r_cpu->main();
|
||||
}
|
||||
|
||||
void sCPU::run() {
|
||||
co_call(thread);
|
||||
}
|
||||
|
||||
void sCPU::power() {
|
||||
status.region = bool(snes->region());
|
||||
status.region = (bool)snes.region();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
@@ -28,16 +20,10 @@ void sCPU::power() {
|
||||
}
|
||||
|
||||
void sCPU::reset() {
|
||||
if(thread)co_delete(thread);
|
||||
thread = co_create(scpu_entry_point, 65536);
|
||||
|
||||
regs.pc.d = 0x000000;
|
||||
regs.pc.l = r_mem->read(0xfffc);
|
||||
regs.pc.h = r_mem->read(0xfffd);
|
||||
|
||||
regs.acc_8b = true;
|
||||
regs.idx_8b = true;
|
||||
|
||||
//note: some registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
@@ -63,10 +49,8 @@ void sCPU::reset() {
|
||||
}
|
||||
|
||||
sCPU::sCPU() {
|
||||
//#include "core/optable.cpp"
|
||||
thread = 0;
|
||||
#include "core/optable.cpp"
|
||||
}
|
||||
|
||||
sCPU::~sCPU() {
|
||||
if(thread)co_delete(thread);
|
||||
}
|
||||
+29
-11
@@ -1,4 +1,7 @@
|
||||
class sCPU : public CPU {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
public:
|
||||
#include "core/core.h"
|
||||
#include "dma/dma.h"
|
||||
@@ -6,8 +9,6 @@ public:
|
||||
#include "mmio/mmio.h"
|
||||
#include "timing/timing.h"
|
||||
|
||||
thread_t thread;
|
||||
|
||||
struct {
|
||||
bool wai;
|
||||
bool irq;
|
||||
@@ -15,11 +16,25 @@ struct {
|
||||
} event;
|
||||
|
||||
struct {
|
||||
bool enabled;
|
||||
uint irq_delay;
|
||||
uint irq_fire;
|
||||
uint nmi_hold;
|
||||
uint irq_hold;
|
||||
|
||||
uint nmi_fire;
|
||||
uint irq_fire;
|
||||
uint irq_delay;
|
||||
uint hw_math;
|
||||
|
||||
alwaysinline void set(uint &ctr, uint clocks) {
|
||||
if(clocks >= ctr) { ctr = clocks; }
|
||||
}
|
||||
|
||||
alwaysinline void sub(uint &ctr, uint clocks) {
|
||||
if(ctr >= clocks) {
|
||||
ctr -= clocks;
|
||||
} else {
|
||||
ctr = 0;
|
||||
}
|
||||
}
|
||||
} counter;
|
||||
|
||||
enum {
|
||||
@@ -35,7 +50,6 @@ struct {
|
||||
bool in_opcode;
|
||||
|
||||
uint clock_count;
|
||||
uint clocks_executed;
|
||||
|
||||
//timing
|
||||
bool region;
|
||||
@@ -44,6 +58,7 @@ struct {
|
||||
bool interlace, interlace_field;
|
||||
bool overscan;
|
||||
uint16 field_lines, line_clocks;
|
||||
uint16 prev_field_lines, prev_line_clocks;
|
||||
uint16 vblstart;
|
||||
|
||||
bool line_rendered;
|
||||
@@ -59,13 +74,17 @@ struct {
|
||||
|
||||
uint16 irq_delay;
|
||||
|
||||
uint16 nmi_trigger_pos;
|
||||
bool nmi_read, nmi_line, nmi_transition;
|
||||
uint16 vnmi_trigger_pos;
|
||||
bool nmi_valid;
|
||||
bool nmi_line;
|
||||
bool nmi_transition;
|
||||
bool nmi_pending;
|
||||
|
||||
uint16 virq_trigger_pos, hirq_trigger_pos;
|
||||
bool irq_read, irq_line, irq_transition;
|
||||
bool irq_lock, irq_pending;
|
||||
bool irq_valid;
|
||||
bool irq_line;
|
||||
bool irq_transition;
|
||||
bool irq_pending;
|
||||
|
||||
//dma
|
||||
uint dma_counter;
|
||||
@@ -114,7 +133,6 @@ struct {
|
||||
uint8 joy4l, joy4h;
|
||||
} status;
|
||||
|
||||
void run();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
|
||||
+17
-63
@@ -1,61 +1,4 @@
|
||||
void sCPU::update_interrupts() {
|
||||
status.nmi_trigger_pos = (status.vcounter == status.vblstart) ? 2 : IRQ_TRIGGER_NEVER;
|
||||
|
||||
if(irq_pos_valid() == true) {
|
||||
status.virq_trigger_pos = status.virq_pos;
|
||||
status.hirq_trigger_pos = (status.hirq_enabled) ? ((status.hirq_pos + 1) * 4) : 0;
|
||||
} else {
|
||||
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::nmi_tick() {
|
||||
counter.nmi_fire -= 2;
|
||||
if(counter.nmi_fire != 0) { return; }
|
||||
|
||||
if(status.nmi_enabled == true && status.nmi_line == 1) {
|
||||
status.nmi_line = 0;
|
||||
status.nmi_transition = 1;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::irq_tick() {
|
||||
counter.irq_fire -= 2;
|
||||
if(counter.irq_fire != 0) { return; }
|
||||
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) {
|
||||
status.irq_line = 0;
|
||||
status.irq_transition = 1;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::poll_interrupts() {
|
||||
if(status.hclock == status.nmi_trigger_pos) {
|
||||
status.nmi_read = 0;
|
||||
counter.nmi_fire = 4;
|
||||
}
|
||||
|
||||
if(status.hclock == 10) { status.irq_lock = false; }
|
||||
|
||||
if(status.hirq_trigger_pos == IRQ_TRIGGER_NEVER)return;
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false)return;
|
||||
if(status.irq_lock == true)return;
|
||||
|
||||
uint vpos = status.vcounter;
|
||||
uint hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
|
||||
bool trigger_irq = true;
|
||||
if(status.virq_enabled == true && vpos != status.virq_trigger_pos)trigger_irq = false;
|
||||
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos)trigger_irq = false;
|
||||
|
||||
if(trigger_irq == true) {
|
||||
status.irq_lock = true;
|
||||
status.irq_read = 0;
|
||||
counter.irq_fire = 4;
|
||||
}
|
||||
}
|
||||
#include "irqtiming.cpp"
|
||||
|
||||
bool sCPU::irq_pos_valid() {
|
||||
uint vpos = status.virq_pos;
|
||||
@@ -74,19 +17,29 @@ uint vlimit = region_scanlines() >> 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
alwaysinline bool sCPU::nmi_test() {
|
||||
if(status.nmi_transition == 0)return false;
|
||||
alwaysinline
|
||||
bool sCPU::nmi_test() {
|
||||
if(status.nmi_transition == false) { return false; }
|
||||
status.nmi_transition = false;
|
||||
|
||||
status.nmi_transition = 0;
|
||||
event.wai = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
alwaysinline bool sCPU::irq_test() {
|
||||
alwaysinline
|
||||
bool sCPU::irq_test() {
|
||||
if(status.irq_transition == false) { return false; }
|
||||
status.irq_transition = false;
|
||||
|
||||
event.wai = false;
|
||||
return (regs.p.i) ? false : true;
|
||||
}
|
||||
|
||||
/*
|
||||
if(status.irq_transition == 1)goto irq_trigger;
|
||||
|
||||
if(status.irq_read == 0) {
|
||||
if(status.irq_line == 1 && counter.irq_fire) {
|
||||
if(status.irq_line == 1 && irq_edge()) {
|
||||
return false;
|
||||
}
|
||||
goto irq_trigger;
|
||||
@@ -104,3 +57,4 @@ irq_trigger:
|
||||
event.wai = false;
|
||||
return (regs.p.i) ? false : true;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,105 @@
|
||||
void sCPU::update_interrupts() {
|
||||
status.vnmi_trigger_pos = status.vblstart;
|
||||
|
||||
if(irq_pos_valid() == true) {
|
||||
status.virq_trigger_pos = status.virq_pos;
|
||||
status.hirq_trigger_pos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
|
||||
} else {
|
||||
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sCPU::poll_interrupts() {
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
|
||||
//NMI test
|
||||
timeshift_backward(2, vpos, hpos);
|
||||
bool nmi_valid = (vpos >= status.vnmi_trigger_pos);
|
||||
if(status.nmi_valid == false && nmi_valid == true) {
|
||||
//0->1 edge sensitive transition
|
||||
status.nmi_line = true;
|
||||
counter.nmi_hold = 6;
|
||||
} else if(status.nmi_valid == true && nmi_valid == false) {
|
||||
//1->0 edge sensitive transition
|
||||
status.nmi_line = false;
|
||||
}
|
||||
status.nmi_valid = nmi_valid;
|
||||
|
||||
//NMI hold
|
||||
if(counter.nmi_hold) {
|
||||
counter.nmi_hold -= 2;
|
||||
if(counter.nmi_hold == 0) {
|
||||
if(status.nmi_enabled == true) { status.nmi_transition = true; }
|
||||
}
|
||||
}
|
||||
|
||||
//IRQ test
|
||||
timeshift_backward(8, vpos, hpos);
|
||||
bool irq_valid = (status.virq_enabled == true || status.hirq_enabled == true);
|
||||
if(irq_valid == true) {
|
||||
if(status.virq_enabled == true && vpos != status.virq_trigger_pos) { irq_valid = false; }
|
||||
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos) { irq_valid = false; }
|
||||
}
|
||||
if(status.irq_valid == false && irq_valid == true) {
|
||||
//0->1 edge sensitive transition
|
||||
status.irq_line = true;
|
||||
counter.irq_hold = 6;
|
||||
}
|
||||
status.irq_valid = irq_valid;
|
||||
|
||||
//IRQ hold
|
||||
if(counter.irq_hold) { counter.irq_hold -= 2; }
|
||||
if(status.irq_line == true && counter.irq_hold == 0) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) { status.irq_transition = true; }
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::nmitimen_update(uint8 data) {
|
||||
bool nmi_enabled = status.nmi_enabled;
|
||||
bool virq_enabled = status.virq_enabled;
|
||||
bool hirq_enabled = status.hirq_enabled;
|
||||
status.nmi_enabled = !!(data & 0x80);
|
||||
status.virq_enabled = !!(data & 0x20);
|
||||
status.hirq_enabled = !!(data & 0x10);
|
||||
|
||||
//0->1 edge sensitive transition
|
||||
if(nmi_enabled == false && status.nmi_enabled == true && status.nmi_line == true) {
|
||||
status.nmi_transition = true;
|
||||
}
|
||||
|
||||
//?->1 level sensitive transition
|
||||
if(status.virq_enabled == true && status.hirq_enabled == false && status.irq_line == true) {
|
||||
status.irq_transition = true;
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
}
|
||||
|
||||
update_interrupts();
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
void sCPU::hvtime_update(uint16 addr) {
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
bool sCPU::rdnmi() {
|
||||
bool result = status.nmi_line;
|
||||
if(counter.nmi_hold == 0) {
|
||||
status.nmi_line = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool sCPU::timeup() {
|
||||
bool result = status.irq_line;
|
||||
if(counter.irq_hold == 0) {
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
void sCPU::run_auto_joypad_poll() {
|
||||
uint16 joy1 = 0, joy2 = 0;
|
||||
for(int i = 0; i < 16; i++) {
|
||||
joy1 |= (uint16)snes->port_read(0) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (uint16)snes->port_read(1) ? (0x8000 >> i) : 0;
|
||||
joy1 |= (uint16)snes.port_read(0) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (uint16)snes.port_read(1) ? (0x8000 >> i) : 0;
|
||||
}
|
||||
|
||||
status.joy1l = joy1;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) {
|
||||
htime += clocks;
|
||||
|
||||
if(htime >= status.line_clocks) {
|
||||
htime -= status.line_clocks;
|
||||
if(++vtime >= status.field_lines) {
|
||||
@@ -13,14 +12,11 @@ alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime
|
||||
if(htime >= clocks) {
|
||||
htime -= clocks;
|
||||
} else {
|
||||
htime += 1364 - clocks;
|
||||
if(status.region == SNES::NTSC && status.vcounter == 241 &&
|
||||
status.interlace == false && status.interlace_field == 1)htime -= 4;
|
||||
htime += status.prev_line_clocks - clocks;
|
||||
if(vtime > 0) {
|
||||
vtime--;
|
||||
} else {
|
||||
vtime = status.region_scanlines;
|
||||
if(status.interlace == true && status.interlace_field == 1)vtime++;
|
||||
vtime = status.prev_field_lines - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,35 +45,22 @@ uint16 sCPU::hcounter() {
|
||||
}
|
||||
|
||||
void sCPU::add_clocks(uint clocks) {
|
||||
status.clocks_executed += clocks;
|
||||
|
||||
if(counter.irq_delay) {
|
||||
counter.irq_delay = (counter.irq_delay > clocks) ? (counter.irq_delay - clocks) : 0;
|
||||
if(status.dram_refreshed == false) {
|
||||
if(status.hclock + clocks >= status.dram_refresh_position) {
|
||||
status.dram_refreshed = true;
|
||||
clocks += 40;
|
||||
}
|
||||
}
|
||||
|
||||
if(status.hclock + clocks >= status.line_clocks) {
|
||||
clocks = (status.hclock + clocks) - status.line_clocks;
|
||||
while(status.hclock < status.line_clocks - 2) { tick(); }
|
||||
scanline();
|
||||
}
|
||||
counter.sub(counter.irq_delay, clocks);
|
||||
scheduler.addclocks_cpu(clocks);
|
||||
|
||||
clocks >>= 1;
|
||||
while(clocks--) { tick(); }
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::tick() {
|
||||
status.hclock += 2;
|
||||
|
||||
if(counter.nmi_fire) { nmi_tick(); }
|
||||
if(counter.irq_fire) { irq_tick(); }
|
||||
|
||||
if(status.dram_refreshed == false && status.hclock >= status.dram_refresh_position) {
|
||||
status.dram_refreshed = true;
|
||||
add_clocks(40);
|
||||
return;
|
||||
while(clocks--) {
|
||||
status.hclock += 2;
|
||||
if(status.hclock >= status.line_clocks) { scanline(); }
|
||||
poll_interrupts();
|
||||
}
|
||||
|
||||
poll_interrupts();
|
||||
}
|
||||
|
||||
void sCPU::scanline() {
|
||||
@@ -84,6 +71,7 @@ void sCPU::scanline() {
|
||||
frame();
|
||||
}
|
||||
|
||||
status.prev_line_clocks = status.line_clocks;
|
||||
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
|
||||
|
||||
//dram refresh occurs once every scanline
|
||||
@@ -103,23 +91,20 @@ void sCPU::scanline() {
|
||||
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
|
||||
|
||||
r_ppu->scanline();
|
||||
snes->scanline();
|
||||
snes.scanline();
|
||||
|
||||
update_interrupts();
|
||||
|
||||
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
|
||||
snes->poll_input();
|
||||
snes.poll_input();
|
||||
run_auto_joypad_poll();
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::frame() {
|
||||
status.nmi_read = 1;
|
||||
status.nmi_line = 1;
|
||||
status.nmi_transition = 0;
|
||||
|
||||
status.vcounter = 0;
|
||||
status.interlace_field ^= 1;
|
||||
status.prev_field_lines = status.field_lines;
|
||||
status.field_lines = (status.region_scanlines >> 1);
|
||||
//interlaced even fields have one extra scanline
|
||||
//(263+262=525 NTSC, 313+312=625 PAL)
|
||||
@@ -133,7 +118,7 @@ void sCPU::frame() {
|
||||
}
|
||||
|
||||
r_ppu->frame();
|
||||
snes->frame();
|
||||
snes.frame();
|
||||
}
|
||||
|
||||
/*****
|
||||
@@ -185,15 +170,16 @@ void sCPU::cycle_edge() {
|
||||
if(status.hdmainit_triggered == false) {
|
||||
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
|
||||
status.hdmainit_triggered = true;
|
||||
|
||||
hdma_init_reset();
|
||||
if(hdma_enabled_channels()) {
|
||||
if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
status.hdmainit_pending = true;
|
||||
} else {
|
||||
hdma_init();
|
||||
}
|
||||
add_clocks(18);
|
||||
hdma_init();
|
||||
//if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
// status.dma_state = DMASTATE_DMASYNC;
|
||||
// status.hdmainit_pending = true;
|
||||
//} else {
|
||||
// hdma_init();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,12 +188,14 @@ void sCPU::cycle_edge() {
|
||||
if(status.hclock >= 1106) {
|
||||
status.hdma_triggered = true;
|
||||
if(hdma_active_channels()) {
|
||||
if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
status.hdma_pending = true;
|
||||
} else {
|
||||
hdma_run();
|
||||
}
|
||||
add_clocks(18);
|
||||
hdma_run();
|
||||
//if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
// status.dma_state = DMASTATE_DMASYNC;
|
||||
// status.hdma_pending = true;
|
||||
//} else {
|
||||
// hdma_run();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,30 +219,19 @@ void sCPU::last_cycle() {
|
||||
event.irq = (status.nmi_pending || status.irq_pending);
|
||||
}
|
||||
|
||||
/*****
|
||||
* clocks_executed()
|
||||
*
|
||||
* Return number of clocks executed since last call to this function.
|
||||
* Used by class SNES to control CPU<>APU synchronization.
|
||||
*****/
|
||||
uint32 sCPU::clocks_executed() {
|
||||
uint32 r = status.clocks_executed;
|
||||
status.clocks_executed = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
void sCPU::timing_power() {
|
||||
}
|
||||
|
||||
void sCPU::timing_reset() {
|
||||
counter.enabled = false;
|
||||
counter.nmi_hold = 0;
|
||||
counter.irq_hold = 0;
|
||||
|
||||
counter.nmi_fire = 0;
|
||||
counter.irq_fire = 0;
|
||||
counter.irq_delay = 0;
|
||||
counter.hw_math = 0;
|
||||
counter.irq_fire = 0;
|
||||
counter.nmi_fire = 0;
|
||||
|
||||
status.clock_count = 0;
|
||||
status.clocks_executed = 0;
|
||||
status.clock_count = 0;
|
||||
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
@@ -269,8 +246,11 @@ void sCPU::timing_reset() {
|
||||
status.field_lines = status.region_scanlines >> 1;
|
||||
status.line_clocks = 1364;
|
||||
|
||||
status.prev_field_lines = status.region_scanlines >> 1;
|
||||
status.prev_line_clocks = 1364;
|
||||
|
||||
status.line_rendered = false;
|
||||
status.line_render_position = minmax<0, 1112>((uint16)config::ppu.render_scanline_position);
|
||||
status.line_render_position = min(1112, (uint16)config::ppu.hack.render_scanline_position);
|
||||
|
||||
status.dram_refreshed = false;
|
||||
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
||||
@@ -282,15 +262,14 @@ void sCPU::timing_reset() {
|
||||
|
||||
status.irq_delay = 0;
|
||||
|
||||
status.nmi_read = 1;
|
||||
status.nmi_line = 1;
|
||||
status.nmi_transition = 0;
|
||||
status.nmi_valid = false;
|
||||
status.nmi_line = false;
|
||||
status.nmi_transition = false;
|
||||
status.nmi_pending = false;
|
||||
|
||||
status.irq_read = 1;
|
||||
status.irq_line = 1;
|
||||
status.irq_transition = 0;
|
||||
status.irq_lock = false;
|
||||
status.irq_valid = false;
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
status.irq_pending = false;
|
||||
|
||||
update_interrupts();
|
||||
@@ -304,7 +283,7 @@ void sCPU::timing_reset() {
|
||||
//initial latch values for $213c/$213d
|
||||
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
|
||||
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
|
||||
add_clocks(186);
|
||||
//add_clocks(186);
|
||||
}
|
||||
|
||||
#undef ntsc_color_burst_phase_shift_scanline
|
||||
@@ -13,7 +13,6 @@
|
||||
uint dma_counter();
|
||||
|
||||
void add_clocks(uint clocks);
|
||||
void tick();
|
||||
void scanline();
|
||||
void frame();
|
||||
|
||||
@@ -25,10 +24,6 @@
|
||||
void timing_power();
|
||||
void timing_reset();
|
||||
|
||||
void counter_set(uint &ctr, uint clocks) {
|
||||
if(clocks >= ctr) { ctr = clocks; }
|
||||
}
|
||||
|
||||
//timeshift.cpp
|
||||
void timeshift_forward (uint clocks, uint &v, uint &h);
|
||||
void timeshift_backward(uint clocks, uint &v, uint &h);
|
||||
@@ -36,9 +31,12 @@
|
||||
//irq.cpp
|
||||
enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
||||
void update_interrupts();
|
||||
void nmi_tick();
|
||||
void irq_tick();
|
||||
void poll_interrupts();
|
||||
void nmitimen_update(uint8 data);
|
||||
void hvtime_update(uint16 addr);
|
||||
bool rdnmi();
|
||||
bool timeup();
|
||||
|
||||
bool irq_pos_valid();
|
||||
bool nmi_test();
|
||||
bool irq_test();
|
||||
|
||||
@@ -0,0 +1,586 @@
|
||||
#include "../../base.h"
|
||||
#include "adsp_tables.cpp"
|
||||
|
||||
void aDSP::enter() { loop:
|
||||
run();
|
||||
goto loop;
|
||||
}
|
||||
|
||||
uint8 aDSP::readb(uint16 addr) {
|
||||
return spcram[addr];
|
||||
}
|
||||
|
||||
void aDSP::writeb(uint16 addr, uint8 data) {
|
||||
spcram[addr] = data;
|
||||
}
|
||||
|
||||
uint16 aDSP::readw(uint16 addr) {
|
||||
return (readb(addr + 0)) | (readb(addr + 1) << 8);
|
||||
}
|
||||
|
||||
void aDSP::writew(uint16 addr, uint16 data) {
|
||||
writeb(addr + 0, data);
|
||||
writeb(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
uint8 aDSP::read(uint8 addr) {
|
||||
addr &= 127;
|
||||
int v = addr >> 4;
|
||||
int n = addr & 15;
|
||||
|
||||
switch(addr) {
|
||||
case 0x00: case 0x10: case 0x20: case 0x30:
|
||||
case 0x40: case 0x50: case 0x60: case 0x70:
|
||||
return voice[v].VOLL;
|
||||
case 0x01: case 0x11: case 0x21: case 0x31:
|
||||
case 0x41: case 0x51: case 0x61: case 0x71:
|
||||
return voice[v].VOLR;
|
||||
case 0x02: case 0x12: case 0x22: case 0x32:
|
||||
case 0x42: case 0x52: case 0x62: case 0x72:
|
||||
return voice[v].PITCH;
|
||||
case 0x03: case 0x13: case 0x23: case 0x33:
|
||||
case 0x43: case 0x53: case 0x63: case 0x73:
|
||||
return voice[v].PITCH >> 8;
|
||||
case 0x04: case 0x14: case 0x24: case 0x34:
|
||||
case 0x44: case 0x54: case 0x64: case 0x74:
|
||||
return voice[v].SRCN;
|
||||
case 0x05: case 0x15: case 0x25: case 0x35:
|
||||
case 0x45: case 0x55: case 0x65: case 0x75:
|
||||
return voice[v].ADSR1;
|
||||
case 0x06: case 0x16: case 0x26: case 0x36:
|
||||
case 0x46: case 0x56: case 0x66: case 0x76:
|
||||
return voice[v].ADSR2;
|
||||
case 0x07: case 0x17: case 0x27: case 0x37:
|
||||
case 0x47: case 0x57: case 0x67: case 0x77:
|
||||
return voice[v].GAIN;
|
||||
case 0x08: case 0x18: case 0x28: case 0x38:
|
||||
case 0x48: case 0x58: case 0x68: case 0x78:
|
||||
return voice[v].ENVX;
|
||||
case 0x09: case 0x19: case 0x29: case 0x39:
|
||||
case 0x49: case 0x59: case 0x69: case 0x79:
|
||||
return voice[v].OUTX;
|
||||
|
||||
case 0x0f: case 0x1f: case 0x2f: case 0x3f:
|
||||
case 0x4f: case 0x5f: case 0x6f: case 0x7f:
|
||||
return status.FIR[v];
|
||||
|
||||
case 0x0c: return status.MVOLL;
|
||||
case 0x1c: return status.MVOLR;
|
||||
case 0x2c: return status.EVOLL;
|
||||
case 0x3c: return status.EVOLR;
|
||||
case 0x4c: return status.KON;
|
||||
case 0x5c: return status.KOFF;
|
||||
case 0x6c: return status.FLG;
|
||||
case 0x7c: return status.ENDX;
|
||||
|
||||
case 0x0d: return status.EFB;
|
||||
case 0x2d: return status.PMON;
|
||||
case 0x3d: return status.NON;
|
||||
case 0x4d: return status.EON;
|
||||
case 0x5d: return status.DIR;
|
||||
case 0x6d: return status.ESA;
|
||||
case 0x7d: return status.EDL;
|
||||
}
|
||||
|
||||
return dspram[addr];
|
||||
}
|
||||
|
||||
void aDSP::write(uint8 addr, uint8 data) {
|
||||
//0x80-0xff is a read-only mirror of 0x00-0x7f
|
||||
if(addr & 0x80)return;
|
||||
|
||||
int v = addr >> 4;
|
||||
int n = addr & 15;
|
||||
|
||||
switch(addr) {
|
||||
case 0x00: case 0x10: case 0x20: case 0x30:
|
||||
case 0x40: case 0x50: case 0x60: case 0x70:
|
||||
voice[v].VOLL = data;
|
||||
break;
|
||||
case 0x01: case 0x11: case 0x21: case 0x31:
|
||||
case 0x41: case 0x51: case 0x61: case 0x71:
|
||||
voice[v].VOLR = data;
|
||||
break;
|
||||
case 0x02: case 0x12: case 0x22: case 0x32:
|
||||
case 0x42: case 0x52: case 0x62: case 0x72:
|
||||
voice[v].PITCH &= 0xff00;
|
||||
voice[v].PITCH |= data;
|
||||
break;
|
||||
case 0x03: case 0x13: case 0x23: case 0x33:
|
||||
case 0x43: case 0x53: case 0x63: case 0x73:
|
||||
voice[v].PITCH &= 0x00ff;
|
||||
voice[v].PITCH |= data << 8;
|
||||
break;
|
||||
case 0x04: case 0x14: case 0x24: case 0x34:
|
||||
case 0x44: case 0x54: case 0x64: case 0x74:
|
||||
voice[v].SRCN = data;
|
||||
break;
|
||||
case 0x05: case 0x15: case 0x25: case 0x35:
|
||||
case 0x45: case 0x55: case 0x65: case 0x75:
|
||||
voice[v].ADSR1 = data;
|
||||
voice[v].AdjustEnvelope();
|
||||
break;
|
||||
case 0x06: case 0x16: case 0x26: case 0x36:
|
||||
case 0x46: case 0x56: case 0x66: case 0x76:
|
||||
voice[v].ADSR2 = data;
|
||||
//sustain_level = 0-7, 7 is a special case handled by ATTACK envx mode
|
||||
voice[v].env_sustain = (voice[v].ADSR_sus_level() + 1) << 8;
|
||||
voice[v].AdjustEnvelope();
|
||||
break;
|
||||
case 0x07: case 0x17: case 0x27: case 0x37:
|
||||
case 0x47: case 0x57: case 0x67: case 0x77:
|
||||
voice[v].GAIN = data;
|
||||
voice[v].AdjustEnvelope();
|
||||
break;
|
||||
case 0x08: case 0x18: case 0x28: case 0x38:
|
||||
case 0x48: case 0x58: case 0x68: case 0x78:
|
||||
voice[v].ENVX = data;
|
||||
break;
|
||||
case 0x09: case 0x19: case 0x29: case 0x39:
|
||||
case 0x49: case 0x59: case 0x69: case 0x79:
|
||||
voice[v].OUTX = data;
|
||||
break;
|
||||
|
||||
case 0x0f: case 0x1f: case 0x2f: case 0x3f:
|
||||
case 0x4f: case 0x5f: case 0x6f: case 0x7f:
|
||||
status.FIR[v] = data;
|
||||
break;
|
||||
|
||||
case 0x0c: status.MVOLL = data; break;
|
||||
case 0x1c: status.MVOLR = data; break;
|
||||
case 0x2c: status.EVOLL = data; break;
|
||||
case 0x3c: status.EVOLR = data; break;
|
||||
|
||||
case 0x4c:
|
||||
status.KON = data;
|
||||
status.kon = data;
|
||||
break;
|
||||
case 0x5c:
|
||||
status.KOFF = data;
|
||||
break;
|
||||
case 0x6c:
|
||||
status.FLG = data;
|
||||
status.noise_rate = rate_table[data & 0x1f];
|
||||
break;
|
||||
|
||||
case 0x7c:
|
||||
//read-only register, writes clear all bits of ENDX
|
||||
status.ENDX = 0;
|
||||
break;
|
||||
|
||||
case 0x0d: status.EFB = data; break;
|
||||
case 0x2d: status.PMON = data; break;
|
||||
case 0x3d: status.NON = data; break;
|
||||
case 0x4d: status.EON = data; break;
|
||||
case 0x5d: status.DIR = data; break;
|
||||
case 0x6d: status.ESA = data; break;
|
||||
case 0x7d: status.EDL = data; break;
|
||||
}
|
||||
|
||||
dspram[addr] = data;
|
||||
}
|
||||
|
||||
void aDSP::power() {
|
||||
spcram = r_smp->get_spcram_handle();
|
||||
memset(dspram, 0x00, 128);
|
||||
|
||||
for(int v = 0; v < 8; v++) {
|
||||
voice[v].VOLL = 0;
|
||||
voice[v].VOLR = 0;
|
||||
voice[v].PITCH = 0;
|
||||
voice[v].SRCN = 0;
|
||||
voice[v].ADSR1 = 0;
|
||||
voice[v].ADSR2 = 0;
|
||||
voice[v].GAIN = 0;
|
||||
|
||||
status.FIR[v] = 0;
|
||||
}
|
||||
|
||||
status.FLG = 0xe0;
|
||||
status.MVOLL = status.MVOLR = 0;
|
||||
status.EVOLL = status.EVOLR = 0;
|
||||
status.ENDX = 0;
|
||||
status.EFB = 0;
|
||||
status.PMON = 0;
|
||||
status.NON = 0;
|
||||
status.EON = 0;
|
||||
status.DIR = 0;
|
||||
status.ESA = 0;
|
||||
status.EDL = 0;
|
||||
|
||||
status.echo_length = 0;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void aDSP::reset() {
|
||||
status.KON = 0x00;
|
||||
status.KOFF = 0x00;
|
||||
status.FLG |= 0xe0;
|
||||
|
||||
status.kon = 0x00;
|
||||
status.esa = 0x00;
|
||||
|
||||
status.noise_ctr = 0;
|
||||
status.noise_rate = 0;
|
||||
status.noise_sample = 0x4000;
|
||||
|
||||
status.echo_index = 0;
|
||||
status.fir_buffer_index = 0;
|
||||
|
||||
for(int v = 0; v < 8; v++) {
|
||||
voice[v].ENVX = 0;
|
||||
voice[v].OUTX = 0;
|
||||
|
||||
voice[v].pitch_ctr = 0;
|
||||
|
||||
voice[v].brr_index = 0;
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2));
|
||||
voice[v].brr_looped = false;
|
||||
voice[v].brr_data[0] = 0;
|
||||
voice[v].brr_data[1] = 0;
|
||||
voice[v].brr_data[2] = 0;
|
||||
voice[v].brr_data[3] = 0;
|
||||
voice[v].brr_data_index = 0;
|
||||
|
||||
voice[v].envx = 0;
|
||||
voice[v].env_ctr = 0;
|
||||
voice[v].env_rate = 0;
|
||||
voice[v].env_state = SILENCE;
|
||||
voice[v].env_mode = DIRECT;
|
||||
|
||||
status.fir_buffer[0][v] = 0;
|
||||
status.fir_buffer[1][v] = 0;
|
||||
}
|
||||
|
||||
dsp_counter = 0;
|
||||
}
|
||||
|
||||
void aDSP::run() {
|
||||
uint8 pmon;
|
||||
int32 sample;
|
||||
int32 msamplel, msampler;
|
||||
int32 esamplel, esampler;
|
||||
int32 fir_samplel, fir_sampler;
|
||||
pmon = status.PMON & ~status.NON & ~1;
|
||||
|
||||
if((dsp_counter++ & 1) == 0) {
|
||||
for(uint v = 0; v < 8; v++) {
|
||||
if(status.soft_reset()) {
|
||||
if(voice[v].env_state != SILENCE) {
|
||||
voice[v].env_state = SILENCE;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
}
|
||||
if(status.KOFF & (1 << v)) {
|
||||
if(voice[v].env_state != SILENCE && voice[v].env_state != RELEASE) {
|
||||
voice[v].env_state = RELEASE;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
}
|
||||
if(status.kon & (1 << v)) {
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2));
|
||||
voice[v].brr_index = -9;
|
||||
voice[v].brr_looped = false;
|
||||
voice[v].brr_data[0] = 0;
|
||||
voice[v].brr_data[1] = 0;
|
||||
voice[v].brr_data[2] = 0;
|
||||
voice[v].brr_data[3] = 0;
|
||||
voice[v].envx = 0;
|
||||
voice[v].env_state = ATTACK;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
}
|
||||
status.ENDX &= ~status.kon;
|
||||
status.kon = 0;
|
||||
}
|
||||
|
||||
/*****
|
||||
* update noise
|
||||
*****/
|
||||
status.noise_ctr += status.noise_rate;
|
||||
if(status.noise_ctr >= 0x7800) {
|
||||
status.noise_ctr -= 0x7800;
|
||||
status.noise_sample = (status.noise_sample >> 1) | (((status.noise_sample << 14) ^ (status.noise_sample << 13)) & 0x4000);
|
||||
}
|
||||
|
||||
msamplel = msampler = 0;
|
||||
esamplel = esampler = 0;
|
||||
|
||||
/*****
|
||||
* process voice channels
|
||||
*****/
|
||||
for(int v = 0; v < 8; v++) {
|
||||
if(voice[v].brr_index < -1) {
|
||||
voice[v].brr_index++;
|
||||
voice[v].OUTX = voice[v].outx = 0;
|
||||
voice[v].ENVX = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(voice[v].brr_index >= 0) {
|
||||
if(pmon & (1 << v)) {
|
||||
voice[v].pitch_ctr += (voice[v].pitch_rate() * (voice[v - 1].outx + 0x8000)) >> 15;
|
||||
} else {
|
||||
voice[v].pitch_ctr += voice[v].pitch_rate();
|
||||
}
|
||||
} else {
|
||||
voice[v].pitch_ctr = 0x3000;
|
||||
voice[v].brr_index = 0;
|
||||
}
|
||||
|
||||
/*****
|
||||
* decode BRR samples
|
||||
*****/
|
||||
while(voice[v].pitch_ctr >= 0) {
|
||||
voice[v].pitch_ctr -= 0x1000;
|
||||
|
||||
voice[v].brr_data_index++;
|
||||
voice[v].brr_data_index &= 3;
|
||||
|
||||
if(voice[v].brr_index == 0) {
|
||||
voice[v].brr_header = readb(voice[v].brr_ptr);
|
||||
|
||||
if(voice[v].brr_header_flags() == BRR_END) {
|
||||
status.ENDX |= (1 << v);
|
||||
voice[v].env_state = SILENCE;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
}
|
||||
|
||||
#define S(x) voice[v].brr_data[(voice[v].brr_data_index + (x)) & 3]
|
||||
if(voice[v].env_state != SILENCE) {
|
||||
sample = readb(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
|
||||
if(voice[v].brr_index & 1) {
|
||||
sample = sclip<4>(sample);
|
||||
} else {
|
||||
sample = sclip<4>(sample >> 4);
|
||||
}
|
||||
|
||||
if(voice[v].brr_header_shift() <= 12) {
|
||||
sample = (sample << voice[v].brr_header_shift() >> 1);
|
||||
} else {
|
||||
sample &= ~0x7ff;
|
||||
}
|
||||
|
||||
switch(voice[v].brr_header_filter()) {
|
||||
case 0: //direct
|
||||
break;
|
||||
case 1: //15/16
|
||||
sample += S(-1) + ((-S(-1)) >> 4);
|
||||
break;
|
||||
case 2: //61/32 - 15/16
|
||||
sample += (S(-1) << 1) + ((-((S(-1) << 1) + S(-1))) >> 5)
|
||||
- S(-2) + (S(-2) >> 4);
|
||||
break;
|
||||
case 3: //115/64 - 13/16
|
||||
sample += (S(-1) << 1) + ((-(S(-1) + (S(-1) << 2) + (S(-1) << 3))) >> 6)
|
||||
- S(-2) + (((S(-2) << 1) + S(-2)) >> 4);
|
||||
break;
|
||||
}
|
||||
|
||||
S(0) = sample = sclip<15>(sclamp<16>(sample));
|
||||
} else {
|
||||
S(0) = sample = 0;
|
||||
}
|
||||
|
||||
if(++voice[v].brr_index > 15) {
|
||||
voice[v].brr_index = 0;
|
||||
if(voice[v].brr_header_flags() & BRR_END) {
|
||||
if(voice[v].brr_header_flags() & BRR_LOOP) {
|
||||
status.ENDX |= (1 << v);
|
||||
}
|
||||
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + 2);
|
||||
voice[v].brr_looped = true;
|
||||
} else {
|
||||
voice[v].brr_ptr += 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
* volume envelope adjust
|
||||
*****/
|
||||
voice[v].env_ctr += voice[v].env_rate;
|
||||
|
||||
if(voice[v].env_ctr >= 0x7800) {
|
||||
voice[v].env_ctr -= 0x7800;
|
||||
switch(voice[v].env_mode) {
|
||||
case DIRECT:
|
||||
voice[v].env_rate = 0;
|
||||
break;
|
||||
case LINEAR_DEC:
|
||||
voice[v].envx -= 32;
|
||||
if(voice[v].envx <= 0) {
|
||||
voice[v].envx = 0;
|
||||
voice[v].env_rate = 0;
|
||||
voice[v].env_mode = DIRECT;
|
||||
}
|
||||
break;
|
||||
case LINEAR_INC:
|
||||
voice[v].envx += 32;
|
||||
if(voice[v].envx >= 0x7ff) {
|
||||
voice[v].envx = 0x7ff;
|
||||
voice[v].env_rate = 0;
|
||||
voice[v].env_mode = DIRECT;
|
||||
if(voice[v].ADSR_enabled() && voice[v].env_state == ATTACK) {
|
||||
voice[v].env_state = ((voice[v].env_sustain == 0x800) ? SUSTAIN : DECAY);
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXP_DEC:
|
||||
//multiply by 255/256ths
|
||||
voice[v].envx -= ((voice[v].envx - 1) >> 8) + 1;
|
||||
if(voice[v].ADSR_enabled() && voice[v].env_state == DECAY && voice[v].envx <= voice[v].env_sustain) {
|
||||
voice[v].env_state = SUSTAIN;
|
||||
voice[v].AdjustEnvelope();
|
||||
} else if(voice[v].envx <= 0) {
|
||||
voice[v].envx = 0;
|
||||
voice[v].env_rate = 0;
|
||||
voice[v].env_mode = DIRECT;
|
||||
}
|
||||
break;
|
||||
case BENT_INC:
|
||||
if(voice[v].envx < 0x600) {
|
||||
voice[v].envx += 32;
|
||||
} else {
|
||||
voice[v].envx += 8;
|
||||
|
||||
if(voice[v].envx >= 0x7ff) {
|
||||
voice[v].envx = 0x7ff;
|
||||
voice[v].env_rate = 0;
|
||||
voice[v].env_mode = DIRECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FAST_ATTACK:
|
||||
voice[v].envx += 0x400;
|
||||
if(voice[v].envx >= 0x7ff) {
|
||||
voice[v].envx = 0x7ff;
|
||||
|
||||
//attack raises to max envx. if sustain is also set to max envx, skip decay phase
|
||||
voice[v].env_state = ((voice[v].env_sustain == 0x800) ? SUSTAIN : DECAY);
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
break;
|
||||
case RELEASE_DEC:
|
||||
voice[v].envx -= 8;
|
||||
if(voice[v].envx <= 0) {
|
||||
voice[v].env_state = SILENCE;
|
||||
voice[v].AdjustEnvelope();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
voice[v].ENVX = voice[v].envx >> 4;
|
||||
|
||||
/*****
|
||||
* gaussian interpolation / noise
|
||||
*****/
|
||||
if(status.NON & (1 << v)) {
|
||||
sample = sclip<15>(status.noise_sample);
|
||||
} else {
|
||||
int32 d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1
|
||||
sample = ((gaussian_table[ -1 - d] * S(-3)) >> 11);
|
||||
sample += ((gaussian_table[255 - d] * S(-2)) >> 11);
|
||||
sample += ((gaussian_table[512 + d] * S(-1)) >> 11);
|
||||
sample = sclip <15>(sample);
|
||||
sample += ((gaussian_table[256 + d] * S( 0)) >> 11);
|
||||
sample = sclamp<15>(sample);
|
||||
}
|
||||
#undef S
|
||||
|
||||
/*****
|
||||
* envelope / volume adjust
|
||||
*****/
|
||||
sample = (sample * voice[v].envx) >> 11;
|
||||
voice[v].outx = sample << 1;
|
||||
voice[v].OUTX = sample >> 7;
|
||||
|
||||
if(!status.mute()) {
|
||||
msamplel += ((sample * voice[v].VOLL) >> 7) << 1;
|
||||
msampler += ((sample * voice[v].VOLR) >> 7) << 1;
|
||||
}
|
||||
|
||||
if((status.EON & (1 << v)) && status.echo_write()) {
|
||||
esamplel += ((sample * voice[v].VOLL) >> 7) << 1;
|
||||
esampler += ((sample * voice[v].VOLR) >> 7) << 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
* echo (FIR) adjust
|
||||
*****/
|
||||
#define F(c,x) status.fir_buffer[c][(status.fir_buffer_index + (x)) & 7]
|
||||
status.fir_buffer_index++;
|
||||
F(0,0) = readw((status.esa << 8) + status.echo_index + 0);
|
||||
F(1,0) = readw((status.esa << 8) + status.echo_index + 2);
|
||||
|
||||
fir_samplel = (F(0,-0) * status.FIR[7] +
|
||||
F(0,-1) * status.FIR[6] +
|
||||
F(0,-2) * status.FIR[5] +
|
||||
F(0,-3) * status.FIR[4] +
|
||||
F(0,-4) * status.FIR[3] +
|
||||
F(0,-5) * status.FIR[2] +
|
||||
F(0,-6) * status.FIR[1] +
|
||||
F(0,-7) * status.FIR[0]);
|
||||
|
||||
fir_sampler = (F(1,-0) * status.FIR[7] +
|
||||
F(1,-1) * status.FIR[6] +
|
||||
F(1,-2) * status.FIR[5] +
|
||||
F(1,-3) * status.FIR[4] +
|
||||
F(1,-4) * status.FIR[3] +
|
||||
F(1,-5) * status.FIR[2] +
|
||||
F(1,-6) * status.FIR[1] +
|
||||
F(1,-7) * status.FIR[0]);
|
||||
#undef F
|
||||
|
||||
/*****
|
||||
* update echo buffer
|
||||
*****/
|
||||
if(status.echo_write()) {
|
||||
esamplel += (fir_samplel * status.EFB) >> 14;
|
||||
esampler += (fir_sampler * status.EFB) >> 14;
|
||||
|
||||
esamplel = sclamp<16>(esamplel);
|
||||
esampler = sclamp<16>(esampler);
|
||||
|
||||
writew((status.esa << 8) + status.echo_index + 0, esamplel);
|
||||
writew((status.esa << 8) + status.echo_index + 2, esampler);
|
||||
}
|
||||
|
||||
status.echo_index += 4;
|
||||
if(status.echo_index >= status.echo_length) {
|
||||
status.echo_index = 0;
|
||||
status.echo_length = (status.EDL & 0x0f) << 11;
|
||||
}
|
||||
|
||||
//ESA read occurs at roughly 22/32th sample
|
||||
//ESA fetch occurs at roughly 29/32th sample
|
||||
//as this is not a subsample-level S-DSP emulator,
|
||||
//simulate ~25/32th delay by caching ESA for one
|
||||
//complete sample ...
|
||||
status.esa = status.ESA;
|
||||
|
||||
/*****
|
||||
* main output adjust
|
||||
*****/
|
||||
if(!status.mute()) {
|
||||
msamplel = (msamplel * status.MVOLL) >> 7;
|
||||
msampler = (msampler * status.MVOLR) >> 7;
|
||||
|
||||
msamplel += (fir_samplel * status.EVOLL) >> 14;
|
||||
msampler += (fir_sampler * status.EVOLR) >> 14;
|
||||
|
||||
msamplel = sclamp<16>(msamplel);
|
||||
msampler = sclamp<16>(msampler);
|
||||
}
|
||||
|
||||
snes.audio_update(msamplel, msampler);
|
||||
scheduler.addclocks_dsp(32 * 3);
|
||||
}
|
||||
|
||||
aDSP::aDSP() {}
|
||||
aDSP::~aDSP() {}
|
||||
@@ -0,0 +1,172 @@
|
||||
class aDSP : public DSP {
|
||||
private:
|
||||
uint8 dspram[128];
|
||||
uint8 *spcram;
|
||||
|
||||
uint32 dsp_counter;
|
||||
|
||||
enum { BRR_END = 1, BRR_LOOP = 2 };
|
||||
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
|
||||
public:
|
||||
static const uint16 rate_table[32];
|
||||
static const int16 gaussian_table[512];
|
||||
|
||||
enum EnvelopeStates {
|
||||
ATTACK,
|
||||
DECAY,
|
||||
SUSTAIN,
|
||||
RELEASE,
|
||||
SILENCE
|
||||
};
|
||||
|
||||
enum EnvelopeModes {
|
||||
DIRECT,
|
||||
LINEAR_DEC,
|
||||
EXP_DEC,
|
||||
LINEAR_INC,
|
||||
BENT_INC,
|
||||
|
||||
FAST_ATTACK,
|
||||
RELEASE_DEC
|
||||
};
|
||||
|
||||
private:
|
||||
struct Status {
|
||||
//$0c,$1c
|
||||
int8 MVOLL, MVOLR;
|
||||
//$2c,$3c
|
||||
int8 EVOLL, EVOLR;
|
||||
//$4c,$5c
|
||||
uint8 KON, KOFF;
|
||||
//$6c
|
||||
uint8 FLG;
|
||||
//$7c
|
||||
uint8 ENDX;
|
||||
//$0d
|
||||
int8 EFB;
|
||||
//$2d,$3d,$4d
|
||||
uint8 PMON, NON, EON;
|
||||
//$5d
|
||||
uint8 DIR;
|
||||
//$6d,$7d
|
||||
uint8 ESA, EDL;
|
||||
|
||||
//$xf
|
||||
int8 FIR[8];
|
||||
|
||||
//internal variables
|
||||
uint8 kon, esa;
|
||||
|
||||
int16 noise_ctr, noise_rate;
|
||||
uint16 noise_sample;
|
||||
|
||||
uint16 echo_index, echo_length;
|
||||
int16 fir_buffer[2][8];
|
||||
uint8 fir_buffer_index;
|
||||
|
||||
//functions
|
||||
bool soft_reset() { return !!(FLG & 0x80); }
|
||||
bool mute() { return !!(FLG & 0x40); }
|
||||
bool echo_write() { return !(FLG & 0x20); }
|
||||
} status;
|
||||
|
||||
struct Voice {
|
||||
//$x0-$x1
|
||||
int8 VOLL, VOLR;
|
||||
//$x2-$x3
|
||||
int16 PITCH;
|
||||
//$x4
|
||||
uint8 SRCN;
|
||||
//$x5-$x7
|
||||
uint8 ADSR1, ADSR2, GAIN;
|
||||
//$x8-$x9
|
||||
uint8 ENVX, OUTX;
|
||||
|
||||
//internal variables
|
||||
int16 pitch_ctr;
|
||||
|
||||
int8 brr_index;
|
||||
uint16 brr_ptr;
|
||||
uint8 brr_header;
|
||||
bool brr_looped;
|
||||
|
||||
int16 brr_data[4];
|
||||
uint8 brr_data_index;
|
||||
|
||||
int16 envx;
|
||||
uint16 env_ctr, env_rate, env_sustain;
|
||||
enum EnvelopeStates env_state;
|
||||
enum EnvelopeModes env_mode;
|
||||
|
||||
int16 outx;
|
||||
|
||||
//functions
|
||||
int16 pitch_rate() { return PITCH & 0x3fff; }
|
||||
|
||||
uint8 brr_header_shift() { return brr_header >> 4; }
|
||||
uint8 brr_header_filter() { return (brr_header >> 2) & 3; }
|
||||
uint8 brr_header_flags() { return brr_header & 3; }
|
||||
|
||||
bool ADSR_enabled() { return !!(ADSR1 & 0x80); }
|
||||
uint8 ADSR_decay() { return (ADSR1 >> 4) & 7; }
|
||||
uint8 ADSR_attack() { return ADSR1 & 15; }
|
||||
uint8 ADSR_sus_level() { return ADSR2 >> 5; }
|
||||
uint8 ADSR_sus_rate() { return ADSR2 & 31; }
|
||||
|
||||
void AdjustEnvelope() {
|
||||
if(env_state == SILENCE) {
|
||||
env_mode = DIRECT;
|
||||
env_rate = 0;
|
||||
envx = 0;
|
||||
} else if(env_state == RELEASE) {
|
||||
env_mode = RELEASE_DEC;
|
||||
env_rate = 0x7800;
|
||||
} else if(ADSR_enabled()) {
|
||||
switch(env_state) {
|
||||
case ATTACK:
|
||||
env_rate = rate_table[(ADSR_attack() << 1) + 1];
|
||||
env_mode = (env_rate == 0x7800) ? FAST_ATTACK : LINEAR_INC;
|
||||
break;
|
||||
case DECAY:
|
||||
env_rate = rate_table[(ADSR_decay() << 1) + 0x10];
|
||||
env_mode = EXP_DEC;
|
||||
break;
|
||||
case SUSTAIN:
|
||||
env_rate = rate_table[ADSR_sus_rate()];
|
||||
env_mode = (env_rate == 0) ? DIRECT : EXP_DEC;
|
||||
break;
|
||||
}
|
||||
} else if(GAIN & 0x80) {
|
||||
switch(GAIN & 0x60) {
|
||||
case 0x00: env_mode = LINEAR_DEC; break;
|
||||
case 0x20: env_mode = EXP_DEC; break;
|
||||
case 0x40: env_mode = LINEAR_INC; break;
|
||||
case 0x60: env_mode = BENT_INC; break;
|
||||
}
|
||||
env_rate = rate_table[GAIN & 0x1f];
|
||||
} else {
|
||||
env_mode = DIRECT;
|
||||
env_rate = 0;
|
||||
envx = (GAIN & 0x7f) << 4;
|
||||
}
|
||||
}
|
||||
} voice[8];
|
||||
|
||||
public:
|
||||
void enter();
|
||||
void run();
|
||||
|
||||
uint8 read (uint8 addr);
|
||||
void write(uint8 addr, uint8 data);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
aDSP();
|
||||
~aDSP();
|
||||
};
|
||||
@@ -1,11 +1,11 @@
|
||||
const uint16 bDSP::RateTable[32] = {
|
||||
const uint16 aDSP::rate_table[32] = {
|
||||
0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
|
||||
0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
|
||||
0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
|
||||
0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
|
||||
};
|
||||
|
||||
const int16 bDSP::GaussTable[512] = {
|
||||
const int16 aDSP::gaussian_table[512] = {
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
|
||||
+650
-534
File diff suppressed because it is too large.
Load diff
+160
-164
@@ -1,171 +1,167 @@
|
||||
class bDSP : public DSP {
|
||||
private:
|
||||
uint8 dspram[128];
|
||||
uint8 *spcram;
|
||||
|
||||
uint32 dsp_counter;
|
||||
|
||||
enum { BRR_END = 1, BRR_LOOP = 2 };
|
||||
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
|
||||
public:
|
||||
static const uint16 RateTable[32];
|
||||
static const int16 GaussTable[512];
|
||||
|
||||
enum EnvelopeStates {
|
||||
ATTACK,
|
||||
DECAY,
|
||||
SUSTAIN,
|
||||
RELEASE,
|
||||
SILENCE
|
||||
};
|
||||
|
||||
enum EnvelopeModes {
|
||||
DIRECT,
|
||||
LINEAR_DEC,
|
||||
EXP_DEC,
|
||||
LINEAR_INC,
|
||||
BENT_INC,
|
||||
|
||||
FAST_ATTACK,
|
||||
RELEASE_DEC
|
||||
};
|
||||
|
||||
private:
|
||||
struct Status {
|
||||
//$0c,$1c
|
||||
int8 MVOLL, MVOLR;
|
||||
//$2c,$3c
|
||||
int8 EVOLL, EVOLR;
|
||||
//$4c,$5c
|
||||
uint8 KON, KOFF;
|
||||
//$6c
|
||||
uint8 FLG;
|
||||
//$7c
|
||||
uint8 ENDX;
|
||||
//$0d
|
||||
int8 EFB;
|
||||
//$2d,$3d,$4d
|
||||
uint8 PMON, NON, EON;
|
||||
//$5d
|
||||
uint8 DIR;
|
||||
//$6d,$7d
|
||||
uint8 ESA, EDL;
|
||||
|
||||
//$xf
|
||||
int8 FIR[8];
|
||||
|
||||
//internal variables
|
||||
uint8 kon;
|
||||
bool key_flag;
|
||||
|
||||
int16 noise_ctr, noise_rate;
|
||||
uint16 noise_sample;
|
||||
|
||||
uint16 echo_index, echo_size, echo_target;
|
||||
int16 fir_buffer[2][8];
|
||||
uint8 fir_buffer_index;
|
||||
|
||||
//functions
|
||||
bool soft_reset() { return bool(FLG & 0x80); }
|
||||
bool mute() { return bool(FLG & 0x40); }
|
||||
bool echo_write() { return !(FLG & 0x20); }
|
||||
} status;
|
||||
|
||||
struct Voice {
|
||||
//$x0-$x1
|
||||
int8 VOLL, VOLR;
|
||||
//$x2-$x3
|
||||
int16 PITCH;
|
||||
//$x4
|
||||
uint8 SRCN;
|
||||
//$x5-$x7
|
||||
uint8 ADSR1, ADSR2, GAIN;
|
||||
//$x8-$x9
|
||||
uint8 ENVX, OUTX;
|
||||
|
||||
//internal variables
|
||||
int16 pitch_ctr;
|
||||
|
||||
int8 brr_index;
|
||||
uint16 brr_ptr;
|
||||
uint8 brr_header;
|
||||
bool brr_looped;
|
||||
|
||||
int16 brr_data[4];
|
||||
uint8 brr_data_index;
|
||||
|
||||
int16 envx;
|
||||
uint16 env_ctr, env_rate, env_sustain;
|
||||
enum EnvelopeStates env_state;
|
||||
enum EnvelopeModes env_mode;
|
||||
|
||||
int16 outx;
|
||||
|
||||
//functions
|
||||
int16 pitch_rate() { return PITCH & 0x3fff; }
|
||||
|
||||
uint8 brr_header_shift() { return brr_header >> 4; }
|
||||
uint8 brr_header_filter() { return (brr_header >> 2) & 3; }
|
||||
uint8 brr_header_flags() { return brr_header & 3; }
|
||||
|
||||
bool ADSR_enabled() { return bool(ADSR1 & 0x80); }
|
||||
uint8 ADSR_decay() { return (ADSR1 >> 4) & 7; }
|
||||
uint8 ADSR_attack() { return ADSR1 & 15; }
|
||||
uint8 ADSR_sus_level() { return ADSR2 >> 5; }
|
||||
uint8 ADSR_sus_rate() { return ADSR2 & 31; }
|
||||
|
||||
void AdjustEnvelope() {
|
||||
if(env_state == SILENCE) {
|
||||
env_mode = DIRECT;
|
||||
env_rate = 0;
|
||||
envx = 0;
|
||||
} else if(env_state == RELEASE) {
|
||||
env_mode = RELEASE_DEC;
|
||||
env_rate = 0x7800;
|
||||
} else if(ADSR_enabled()) {
|
||||
switch(env_state) {
|
||||
case ATTACK:
|
||||
env_rate = RateTable[(ADSR_attack() << 1) + 1];
|
||||
env_mode = (env_rate == 0x7800) ? FAST_ATTACK : LINEAR_INC;
|
||||
break;
|
||||
case DECAY:
|
||||
env_rate = RateTable[(ADSR_decay() << 1) + 0x10];
|
||||
env_mode = EXP_DEC;
|
||||
break;
|
||||
case SUSTAIN:
|
||||
env_rate = RateTable[ADSR_sus_rate()];
|
||||
env_mode = (env_rate == 0) ? DIRECT : EXP_DEC;
|
||||
break;
|
||||
}
|
||||
} else if(GAIN & 0x80) {
|
||||
switch(GAIN & 0x60) {
|
||||
case 0x00: env_mode = LINEAR_DEC; break;
|
||||
case 0x20: env_mode = EXP_DEC; break;
|
||||
case 0x40: env_mode = LINEAR_INC; break;
|
||||
case 0x60: env_mode = BENT_INC; break;
|
||||
}
|
||||
env_rate = RateTable[GAIN & 0x1f];
|
||||
} else {
|
||||
env_mode = DIRECT;
|
||||
env_rate = 0;
|
||||
envx = (GAIN & 0x7f) << 4;
|
||||
}
|
||||
}
|
||||
} voice[8];
|
||||
void enter();
|
||||
|
||||
uint8 read( uint8 addr );
|
||||
void write( uint8 addr, uint8 data );
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
bDSP();
|
||||
~bDSP();
|
||||
|
||||
public:
|
||||
uint8 read (uint8 addr);
|
||||
void write(uint8 addr, uint8 data);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
uint32 run();
|
||||
enum { echo_hist_size = 8 };
|
||||
enum { register_count = 128 };
|
||||
enum { voice_count = 8 };
|
||||
|
||||
enum env_mode_t { env_release, env_attack, env_decay, env_sustain };
|
||||
enum { brr_buf_size = 12 };
|
||||
struct voice_t
|
||||
{
|
||||
int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
|
||||
int buf_pos; // place in buffer where next samples will be decoded
|
||||
int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
|
||||
int brr_addr; // address of current BRR block
|
||||
int brr_offset; // current decoding offset in BRR block
|
||||
uint8* regs; // pointer to voice's DSP registers
|
||||
int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
|
||||
int kon_delay; // KON delay/current setup phase
|
||||
env_mode_t env_mode;
|
||||
int env; // current envelope level
|
||||
int hidden_env; // used by GAIN mode 7, very obscure quirk
|
||||
uint8 t_envx_out;
|
||||
};
|
||||
private:
|
||||
|
||||
struct state_t
|
||||
{
|
||||
uint8 regs [register_count];
|
||||
|
||||
// Echo history keeps most recent 8 samples
|
||||
int echo_hist [echo_hist_size] [2];
|
||||
int echo_hist_pos;
|
||||
|
||||
int every_other_sample; // toggles every sample
|
||||
int kon; // KON value when last checked
|
||||
int noise;
|
||||
int counter;
|
||||
int echo_offset; // offset from ESA in echo buffer
|
||||
int echo_length; // number of bytes that echo_offset will stop at
|
||||
|
||||
// Hidden registers also written to when main register is written to
|
||||
int new_kon;
|
||||
uint8 endx_buf;
|
||||
uint8 envx_buf;
|
||||
uint8 outx_buf;
|
||||
|
||||
// Temporary state between clocks
|
||||
|
||||
// read once per sample
|
||||
int t_pmon;
|
||||
int t_non;
|
||||
int t_eon;
|
||||
int t_dir;
|
||||
int t_koff;
|
||||
|
||||
// read a few clocks ahead then used
|
||||
int t_brr_next_addr;
|
||||
int t_adsr0;
|
||||
int t_brr_header;
|
||||
int t_brr_byte;
|
||||
int t_srcn;
|
||||
|
||||
// internal state that is recalculated every sample
|
||||
int t_dir_addr;
|
||||
int t_pitch;
|
||||
int t_output;
|
||||
int t_looped;
|
||||
|
||||
// left/right sums
|
||||
int t_main_out [2];
|
||||
int t_echo_out [2];
|
||||
|
||||
voice_t voices [voice_count];
|
||||
};
|
||||
state_t m;
|
||||
uint8* ram;
|
||||
|
||||
unsigned read_counter( int rate );
|
||||
|
||||
void run_envelope( voice_t* const v );
|
||||
void decode_brr( voice_t* v );
|
||||
|
||||
bDSP();
|
||||
~bDSP();
|
||||
void voice_output( voice_t const* v, int ch );
|
||||
void voice_V1( voice_t* const );
|
||||
void voice_V2( voice_t* const );
|
||||
void voice_V3( voice_t* const );
|
||||
void voice_V3a( voice_t* const );
|
||||
void voice_V3b( voice_t* const );
|
||||
void voice_V3c( voice_t* const );
|
||||
void voice_V4( voice_t* const );
|
||||
void voice_V5( voice_t* const );
|
||||
void voice_V6( voice_t* const );
|
||||
void voice_V7( voice_t* const );
|
||||
void voice_V8( voice_t* const );
|
||||
void voice_V9( voice_t* const );
|
||||
void voice_V7_V4_V1( voice_t* const );
|
||||
void voice_V8_V5_V2( voice_t* const );
|
||||
void voice_V9_V6_V3( voice_t* const );
|
||||
|
||||
int calc_echo_output( int ch, int sample );
|
||||
|
||||
// Global registers
|
||||
enum {
|
||||
r_mvoll = 0x0C, r_mvolr = 0x1C,
|
||||
r_evoll = 0x2C, r_evolr = 0x3C,
|
||||
r_kon = 0x4C, r_koff = 0x5C,
|
||||
r_flg = 0x6C, r_endx = 0x7C,
|
||||
r_efb = 0x0D, r_pmon = 0x2D,
|
||||
r_non = 0x3D, r_eon = 0x4D,
|
||||
r_dir = 0x5D, r_esa = 0x6D,
|
||||
r_edl = 0x7D,
|
||||
r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
|
||||
};
|
||||
|
||||
// Voice registers
|
||||
enum {
|
||||
v_voll = 0x00, v_volr = 0x01,
|
||||
v_pitchl = 0x02, v_pitchh = 0x03,
|
||||
v_srcn = 0x04, v_adsr0 = 0x05,
|
||||
v_adsr1 = 0x06, v_gain = 0x07,
|
||||
v_envx = 0x08, v_outx = 0x09
|
||||
};
|
||||
};
|
||||
|
||||
inline uint8 bDSP::read( uint8 addr )
|
||||
{
|
||||
return m.regs [addr];
|
||||
}
|
||||
|
||||
inline void bDSP::write( uint8 addr, uint8 data )
|
||||
{
|
||||
m.regs [addr] = data;
|
||||
switch ( addr & 0x0F )
|
||||
{
|
||||
case v_envx:
|
||||
m.envx_buf = data;
|
||||
break;
|
||||
|
||||
case v_outx:
|
||||
m.outx_buf = data;
|
||||
break;
|
||||
|
||||
case 0x0C:
|
||||
if ( addr == r_kon )
|
||||
m.new_kon = data;
|
||||
|
||||
if ( addr == r_endx ) // always cleared, regardless of data written
|
||||
{
|
||||
m.endx_buf = 0;
|
||||
m.regs [r_endx] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "../../base.h"
|
||||
#include "spc_dsp.h"
|
||||
|
||||
void bDSP::power() {
|
||||
spc_dsp_init(r_smp->get_spcram_handle());
|
||||
spc_dsp_reset();
|
||||
}
|
||||
|
||||
void bDSP::reset() {
|
||||
spc_dsp_soft_reset();
|
||||
}
|
||||
|
||||
uint8 bDSP::read(uint8 addr) {
|
||||
return spc_dsp_read(addr);
|
||||
}
|
||||
|
||||
void bDSP::write(uint8 addr, uint8 data) {
|
||||
spc_dsp_write(addr, data);
|
||||
}
|
||||
|
||||
#define SPC_DSP_CUSTOM_RUN 1 //causes spc_dsp_run() to not be defined since it's huge and we don't need it
|
||||
#define SPC_DSP_OUT_HOOK(left, right) snes.audio_update(left, right);
|
||||
#include "spc_dsp.cpp"
|
||||
|
||||
void bDSP::enter() { loop:
|
||||
#define PHASE(n) scheduler.addclocks_dsp(3);
|
||||
#include "spc_dsp_timing.h"
|
||||
goto loop;
|
||||
}
|
||||
|
||||
bDSP::bDSP() {}
|
||||
bDSP::~bDSP() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
class bDSP : public DSP { public:
|
||||
void enter();
|
||||
uint8 read(uint8 addr);
|
||||
void write(uint8 addr, uint8 data);
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
bDSP();
|
||||
~bDSP();
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
Overall operation
|
||||
-----------------
|
||||
This DSP emulator fundamentally emulates the different options the DSP
|
||||
performs on each clock. The pattern of operations repeats every 32
|
||||
clocks (except one minor detail, which repeats every 64 clocks instead).
|
||||
There are three main types of operations:
|
||||
|
||||
- Miscellaneous processing
|
||||
- Voice processing
|
||||
- Echo processing
|
||||
|
||||
Each is done over several clocks, and several operations are done on
|
||||
each clock. Each clock is defined as a separate function, then called
|
||||
from a large switch block in a loop.
|
||||
|
||||
Many times a value is read on one clock but not used until a later
|
||||
clock, so many non-local temporary variables are used in the code to
|
||||
store these values. These are named with t_ to make it clear that they
|
||||
don't store long-term state.
|
||||
|
||||
|
||||
Circular buffers
|
||||
----------------
|
||||
Two circular buffers are used in the code (echo history and BRR decode).
|
||||
Both need efficient index-based access with wrap-around. Things are
|
||||
greatly simplified by repeating the contents of buffer twice, so instead
|
||||
of
|
||||
|
||||
0 1 2 3 4 5 6 7
|
||||
|
||||
it stores
|
||||
|
||||
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
|
||||
|
||||
The position in this case would always be 0 to 7, so reading up to +8
|
||||
won't go outside buffer. This duplication is maintained by simply
|
||||
writing data twice when filling buffer:
|
||||
|
||||
0 1 2 3 4 # 6 7 0 1 2 3 4 # 6 7
|
||||
new data -----^---------------^
|
||||
|
||||
No wrap checking needs to be done when writing either, since the above
|
||||
reasoning holds. When making a state snapshot, only the first copy needs
|
||||
to be saved. When restoring, simply duplicate the data twice.
|
||||
|
||||
|
||||
Code
|
||||
----
|
||||
- Currently all state is in static variables. They have either a t_ or
|
||||
m_ prefix to allow easy migration to a structure.
|
||||
|
||||
- Static state that persists over several samples or more is prefixed
|
||||
with m_.
|
||||
|
||||
- State which is temporary to the current sample is prefixed with t_.
|
||||
These are usually just overwritten with new data on the next sample.
|
||||
These generally correspond to temporaries/registers in actual DSP
|
||||
itself.
|
||||
|
||||
- Minimal stdint.h included in case your system doesn't have one.
|
||||
|
||||
|
||||
--
|
||||
Shay Green <[email protected]>
|
||||
@@ -0,0 +1,828 @@
|
||||
// http://www.slack.net/~ant/
|
||||
|
||||
#include "spc_dsp.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Copyright (C) 2007 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
// Volume registers and efb are signed! Easy to forget int8_t cast.
|
||||
// Prefixes are to avoid accidental use of locals with same names.
|
||||
|
||||
// Global registers
|
||||
enum {
|
||||
r_mvoll = 0x0C, r_mvolr = 0x1C,
|
||||
r_evoll = 0x2C, r_evolr = 0x3C,
|
||||
r_kon = 0x4C, r_koff = 0x5C,
|
||||
r_flg = 0x6C, r_endx = 0x7C,
|
||||
r_efb = 0x0D, r_pmon = 0x2D,
|
||||
r_non = 0x3D, r_eon = 0x4D,
|
||||
r_dir = 0x5D, r_esa = 0x6D,
|
||||
r_edl = 0x7D,
|
||||
r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
|
||||
};
|
||||
|
||||
// Voice registers
|
||||
enum {
|
||||
v_voll = 0x00, v_volr = 0x01,
|
||||
v_pitchl = 0x02, v_pitchh = 0x03,
|
||||
v_srcn = 0x04, v_adsr0 = 0x05,
|
||||
v_adsr1 = 0x06, v_gain = 0x07,
|
||||
v_envx = 0x08, v_outx = 0x09
|
||||
};
|
||||
|
||||
// Internal envelope modes
|
||||
enum env_mode_t { env_release, env_attack, env_decay, env_sustain };
|
||||
|
||||
// Internal voice state
|
||||
enum { brr_buf_size = 12 };
|
||||
enum { brr_block_size = 9 };
|
||||
typedef struct voice_t
|
||||
{
|
||||
int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
|
||||
int buf_pos; // place in buffer where next samples will be decoded
|
||||
int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
|
||||
int brr_addr; // address of current BRR block
|
||||
int brr_offset; // current decoding offset in BRR block
|
||||
uint8_t* regs; // pointer to voice's DSP registers
|
||||
int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
|
||||
int kon_delay; // KON delay/current setup phase
|
||||
enum env_mode_t env_mode;
|
||||
int env; // current envelope level
|
||||
int t_envx_out;
|
||||
int hidden_env; // used by GAIN mode 7, very obscure quirk
|
||||
} voice_t;
|
||||
|
||||
static voice_t m_voice_state [spc_dsp_voice_count];
|
||||
static uint8_t* m_ram; // 64K shared RAM between DSP and SMP
|
||||
spc_dsp_t m_spc_dsp;
|
||||
spc_dsp_sample_t* m_spc_dsp_out_begin;
|
||||
spc_dsp_sample_t* m_spc_dsp_out;
|
||||
spc_dsp_sample_t* m_spc_dsp_out_end;
|
||||
|
||||
// "Member" access
|
||||
#define m m_spc_dsp
|
||||
|
||||
// Access global DSP register
|
||||
#define REG(n) m.regs [r_##n]
|
||||
|
||||
// Access voice DSP register
|
||||
#define VREG(r,n) r [v_##n]
|
||||
|
||||
// if ( io < -32768 ) io = -32768;
|
||||
// if ( io > 32767 ) io = 32767;
|
||||
#define CLAMP16( io )\
|
||||
{\
|
||||
if ( (int16_t) io != io )\
|
||||
io = 0x7FFF ^ (io >> 31);\
|
||||
}
|
||||
|
||||
// Gaussian interpolation
|
||||
|
||||
static short const gauss [512] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
|
||||
2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
|
||||
11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17,
|
||||
18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27,
|
||||
28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||
58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77,
|
||||
78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102,
|
||||
104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
|
||||
134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
|
||||
171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
|
||||
212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
|
||||
260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
|
||||
314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
|
||||
374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
|
||||
439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
|
||||
508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
|
||||
582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
|
||||
659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
|
||||
737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
|
||||
816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
|
||||
894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
|
||||
969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
|
||||
1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
|
||||
1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
|
||||
1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
|
||||
1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
|
||||
1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
|
||||
1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
|
||||
1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
|
||||
};
|
||||
|
||||
static inline int interpolate( voice_t const* const v )
|
||||
{
|
||||
// Make pointers into gaussian based on fractional position between samples
|
||||
int offset = v->interp_pos >> 4 & 0xFF;
|
||||
short const* fwd = gauss + 255 - offset;
|
||||
short const* rev = gauss + offset; // mirror left half of gaussian
|
||||
|
||||
int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
|
||||
int out;
|
||||
out = (fwd [ 0] * in [0]) >> 11;
|
||||
out += (fwd [256] * in [1]) >> 11;
|
||||
out += (rev [256] * in [2]) >> 11;
|
||||
out = (int16_t) out;
|
||||
out += (rev [ 0] * in [3]) >> 11;
|
||||
|
||||
CLAMP16( out );
|
||||
out &= ~1;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//// Counters
|
||||
|
||||
enum { simple_counter_range = 2048 * 5 * 3 }; // 30720
|
||||
|
||||
static unsigned short const counter_rates [32] =
|
||||
{
|
||||
simple_counter_range + 1, // never fires
|
||||
2048, 1536,
|
||||
1280, 1024, 768,
|
||||
640, 512, 384,
|
||||
320, 256, 192,
|
||||
160, 128, 96,
|
||||
80, 64, 48,
|
||||
40, 32, 24,
|
||||
20, 16, 12,
|
||||
10, 8, 6,
|
||||
5, 4, 3,
|
||||
2,
|
||||
1
|
||||
};
|
||||
|
||||
static unsigned short const counter_offsets [32] =
|
||||
{
|
||||
1, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
536, 0, 1040,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
static inline void init_counters( void ) { }
|
||||
|
||||
static inline void run_counters( void )
|
||||
{
|
||||
if ( --m.counter < 0 )
|
||||
m.counter = simple_counter_range - 1;
|
||||
}
|
||||
|
||||
static inline unsigned read_counter( int rate )
|
||||
{
|
||||
return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
|
||||
}
|
||||
|
||||
|
||||
//// Envelope
|
||||
|
||||
static inline void run_envelope( voice_t* const v )
|
||||
{
|
||||
int env = v->env;
|
||||
if ( v->env_mode == env_release ) // 60%
|
||||
{
|
||||
if ( (env -= 0x8) < 0 )
|
||||
env = 0;
|
||||
v->env = env;
|
||||
}
|
||||
else
|
||||
{
|
||||
int rate;
|
||||
int env_data = VREG(v->regs,adsr1);
|
||||
if ( m.t_adsr0 & 0x80 ) // 99% ADSR
|
||||
{
|
||||
if ( v->env_mode >= env_decay ) // 99%
|
||||
{
|
||||
env--;
|
||||
env -= env >> 8;
|
||||
rate = env_data & 0x1F;
|
||||
if ( v->env_mode == env_decay ) // 1%
|
||||
rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10;
|
||||
}
|
||||
else // env_attack
|
||||
{
|
||||
rate = (m.t_adsr0 & 0x0F) * 2 + 1;
|
||||
env += rate < 31 ? 0x20 : 0x400;
|
||||
}
|
||||
}
|
||||
else // GAIN
|
||||
{
|
||||
env_data = VREG(v->regs,gain);
|
||||
int mode = env_data >> 5;
|
||||
if ( mode < 4 ) // direct
|
||||
{
|
||||
env = env_data * 0x10;
|
||||
rate = 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
rate = env_data & 0x1F;
|
||||
if ( mode == 4 ) // 4: linear decrease
|
||||
{
|
||||
env -= 0x20;
|
||||
}
|
||||
else if ( mode < 6 ) // 5: exponential decrease
|
||||
{
|
||||
env--;
|
||||
env -= env >> 8;
|
||||
}
|
||||
else // 6,7: linear increase
|
||||
{
|
||||
env += 0x20;
|
||||
if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
|
||||
env += 0x8 - 0x20; // 7: two-slope linear increase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sustain level
|
||||
if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
|
||||
v->env_mode = env_sustain;
|
||||
|
||||
v->hidden_env = env;
|
||||
|
||||
// unsigned cast because linear decrease going negative also triggers this
|
||||
if ( (unsigned) env > 0x7FF )
|
||||
{
|
||||
env = (env < 0 ? 0 : 0x7FF);
|
||||
if ( v->env_mode == env_attack )
|
||||
v->env_mode = env_decay;
|
||||
}
|
||||
|
||||
if ( !read_counter( rate ) )
|
||||
v->env = env; // nothing else is controlled by the counter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// BRR Decoding
|
||||
|
||||
static inline void decode_brr( voice_t* v )
|
||||
{
|
||||
// Arrange the four input nybbles in 0xABCD order for easy decoding
|
||||
int nybbles = m.t_brr_byte * 0x100 + m_ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
|
||||
|
||||
int const header = m.t_brr_header;
|
||||
|
||||
// 0: >>1 1: <<0 2: <<1 ... 12: <<11 13-15: >>4 <<11
|
||||
static unsigned char const shifts [16 * 2] = {
|
||||
13,12,12,12,12,12,12,12,12,12,12, 12, 12, 16, 16, 16,
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
|
||||
};
|
||||
int const scale = header >> 4;
|
||||
int const right_shift = shifts [scale];
|
||||
int const left_shift = shifts [scale + 16];
|
||||
|
||||
// Write to next four samples in circular buffer
|
||||
int* pos = &v->buf [v->buf_pos];
|
||||
if ( (v->buf_pos += 4) >= brr_buf_size )
|
||||
v->buf_pos = 0;
|
||||
|
||||
// Decode four samples
|
||||
for ( int* end = pos + 4; pos < end; pos++ )
|
||||
{
|
||||
// Extract upper nybble and scale appropriately
|
||||
int s = ((int16_t) nybbles >> right_shift) << left_shift;
|
||||
nybbles <<= 4;
|
||||
|
||||
// Apply IIR filter (8 is the most commonly used)
|
||||
int const filter = header & 0x0C;
|
||||
int const p1 = pos [brr_buf_size - 1];
|
||||
int const p2 = pos [brr_buf_size - 2] >> 1;
|
||||
if ( filter >= 8 )
|
||||
{
|
||||
s += p1;
|
||||
s -= p2;
|
||||
if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
|
||||
{
|
||||
s += p2 >> 4;
|
||||
s += (p1 * -3) >> 6;
|
||||
}
|
||||
else // s += p1 * 0.8984375 - p2 * 0.40625
|
||||
{
|
||||
s += (p1 * -13) >> 7;
|
||||
s += (p2 * 3) >> 4;
|
||||
}
|
||||
}
|
||||
else if ( filter ) // s += p1 * 0.46875
|
||||
{
|
||||
s += p1 >> 1;
|
||||
s += (-p1) >> 5;
|
||||
}
|
||||
|
||||
// Adjust and write sample
|
||||
CLAMP16( s );
|
||||
s = (int16_t) (s * 2);
|
||||
pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// Misc
|
||||
|
||||
#define MISC_CLOCK( n ) inline static void misc_##n( void )
|
||||
|
||||
MISC_CLOCK( 27 )
|
||||
{
|
||||
m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON
|
||||
}
|
||||
MISC_CLOCK( 28 )
|
||||
{
|
||||
m.t_non = REG(non);
|
||||
m.t_eon = REG(eon);
|
||||
m.t_dir = REG(dir);
|
||||
}
|
||||
MISC_CLOCK( 29 )
|
||||
{
|
||||
if ( (m.every_other_sample ^= 1) != 0 )
|
||||
m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read
|
||||
}
|
||||
MISC_CLOCK( 30 )
|
||||
{
|
||||
if ( m.every_other_sample )
|
||||
{
|
||||
m.kon = m.new_kon;
|
||||
m.t_koff = REG(koff) | m.mute_mask;
|
||||
}
|
||||
|
||||
run_counters();
|
||||
|
||||
// Noise
|
||||
if ( !read_counter( REG(flg) & 0x1F ) )
|
||||
{
|
||||
int feedback = (m.noise << 13) ^ (m.noise << 14);
|
||||
m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// Voices
|
||||
|
||||
#define VOICE_CLOCK( n ) static void voice_##n( voice_t* const v )
|
||||
|
||||
inline VOICE_CLOCK( V1 )
|
||||
{
|
||||
m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
|
||||
m.t_srcn = VREG(v->regs,srcn);
|
||||
}
|
||||
inline VOICE_CLOCK( V2 )
|
||||
{
|
||||
// Read sample pointer (ignored if not needed)
|
||||
uint8_t const* entry = &m_ram [m.t_dir_addr];
|
||||
if ( !v->kon_delay )
|
||||
entry += 2;
|
||||
m.t_brr_next_addr = entry [1] * 0x100 + entry [0];
|
||||
|
||||
m.t_adsr0 = VREG(v->regs,adsr0);
|
||||
|
||||
// Read pitch, spread over two clocks
|
||||
m.t_pitch = VREG(v->regs,pitchl);
|
||||
}
|
||||
inline VOICE_CLOCK( V3a )
|
||||
{
|
||||
m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8;
|
||||
}
|
||||
inline VOICE_CLOCK( V3b )
|
||||
{
|
||||
// Read BRR header and byte
|
||||
m.t_brr_byte = m_ram [(v->brr_addr + v->brr_offset) & 0xFFFF];
|
||||
m.t_brr_header = m_ram [v->brr_addr]; // brr_addr doesn't need masking
|
||||
}
|
||||
VOICE_CLOCK( V3c )
|
||||
{
|
||||
// Pitch modulation using previous voice's output
|
||||
if ( m.t_pmon & v->vbit )
|
||||
m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10;
|
||||
|
||||
if ( v->kon_delay )
|
||||
{
|
||||
// Get ready to start BRR decoding on next sample
|
||||
if ( v->kon_delay == 5 )
|
||||
{
|
||||
v->brr_addr = m.t_brr_next_addr;
|
||||
v->brr_offset = 1;
|
||||
v->buf_pos = 0;
|
||||
m.t_brr_header = 0; // header is ignored on this sample
|
||||
}
|
||||
|
||||
// Envelope is never run during KON
|
||||
v->env = 0;
|
||||
v->hidden_env = 0;
|
||||
|
||||
// Disable BRR decoding until last three samples
|
||||
v->interp_pos = 0;
|
||||
if ( --v->kon_delay & 3 )
|
||||
v->interp_pos = 0x4000;
|
||||
|
||||
// Pitch is never added during KON
|
||||
m.t_pitch = 0;
|
||||
}
|
||||
|
||||
// Gaussian interpolation
|
||||
int output = interpolate( v );
|
||||
|
||||
// Noise
|
||||
if ( m.t_non & v->vbit )
|
||||
output = (int16_t) (m.noise * 2);
|
||||
|
||||
// Apply envelope
|
||||
m.t_output = (output * v->env) >> 11 & ~1;
|
||||
v->t_envx_out = v->env >> 4;
|
||||
|
||||
// Immediate silence due to end of sample or soft reset
|
||||
if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 )
|
||||
{
|
||||
v->env_mode = env_release;
|
||||
v->env = 0;
|
||||
}
|
||||
|
||||
if ( m.every_other_sample )
|
||||
{
|
||||
// KOFF
|
||||
if ( m.t_koff & v->vbit )
|
||||
v->env_mode = env_release;
|
||||
|
||||
// KON
|
||||
if ( m.kon & v->vbit )
|
||||
{
|
||||
v->kon_delay = 5;
|
||||
v->env_mode = env_attack;
|
||||
}
|
||||
}
|
||||
|
||||
// Run envelope for next sample
|
||||
if ( !v->kon_delay )
|
||||
run_envelope( v );
|
||||
}
|
||||
static inline void voice_output( voice_t const* v, int ch )
|
||||
{
|
||||
// Apply left/right volume
|
||||
int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7;
|
||||
|
||||
// Add to output total
|
||||
m.t_main_out [ch] += amp;
|
||||
CLAMP16( m.t_main_out [ch] );
|
||||
|
||||
// Optionally add to echo total
|
||||
if ( m.t_eon & v->vbit )
|
||||
{
|
||||
m.t_echo_out [ch] += amp;
|
||||
CLAMP16( m.t_echo_out [ch] );
|
||||
}
|
||||
}
|
||||
VOICE_CLOCK( V4 )
|
||||
{
|
||||
// Decode BRR
|
||||
m.t_looped = 0;
|
||||
if ( v->interp_pos >= 0x4000 )
|
||||
{
|
||||
decode_brr( v );
|
||||
|
||||
if ( (v->brr_offset += 2) >= brr_block_size )
|
||||
{
|
||||
// Start decoding next BRR block
|
||||
assert( v->brr_offset == brr_block_size );
|
||||
v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
|
||||
if ( m.t_brr_header & 1 )
|
||||
{
|
||||
v->brr_addr = m.t_brr_next_addr;
|
||||
m.t_looped = v->vbit;
|
||||
}
|
||||
v->brr_offset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply pitch
|
||||
v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
|
||||
|
||||
// Keep from getting too far ahead (when using pitch modulation)
|
||||
if ( v->interp_pos > 0x7FFF )
|
||||
v->interp_pos = 0x7FFF;
|
||||
|
||||
// Output left
|
||||
voice_output( v, 0 );
|
||||
}
|
||||
inline VOICE_CLOCK( V5 )
|
||||
{
|
||||
// Output right
|
||||
voice_output( v, 1 );
|
||||
|
||||
// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
|
||||
|
||||
m.endx_buf = REG(endx) | m.t_looped;
|
||||
|
||||
// Clear bit in ENDX if KON just began
|
||||
if ( v->kon_delay == 5 )
|
||||
m.endx_buf &= ~v->vbit;
|
||||
}
|
||||
inline VOICE_CLOCK( V6 )
|
||||
{
|
||||
m.outx_buf = m.t_output >> 8;
|
||||
}
|
||||
inline VOICE_CLOCK( V7 )
|
||||
{
|
||||
// Update ENDX
|
||||
REG(endx) = (uint8_t) m.endx_buf;
|
||||
|
||||
m.envx_buf = v->t_envx_out;
|
||||
}
|
||||
inline VOICE_CLOCK( V8 )
|
||||
{
|
||||
// Update OUTX
|
||||
VREG(v->regs,outx) = (uint8_t) m.outx_buf;
|
||||
}
|
||||
inline VOICE_CLOCK( V9 )
|
||||
{
|
||||
// Update ENVX
|
||||
VREG(v->regs,envx) = (uint8_t) m.envx_buf;
|
||||
}
|
||||
|
||||
// Most voices do all these in one clock, so make a handy composite
|
||||
inline VOICE_CLOCK( V3 )
|
||||
{
|
||||
voice_V3a( v );
|
||||
voice_V3b( v );
|
||||
voice_V3c( v );
|
||||
}
|
||||
|
||||
// Common combinations of voice steps on different voices. This greatly reduces
|
||||
// code size and allows everything to be inlined in these functions.
|
||||
VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); }
|
||||
VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); }
|
||||
VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); }
|
||||
|
||||
|
||||
//// Echo
|
||||
|
||||
// Current echo buffer pointer for left/right channel
|
||||
#define ECHO_PTR( ch ) (&m_ram [m.t_echo_ptr + ch * 2])
|
||||
|
||||
// Sample in echo history buffer, where 0 is the oldest
|
||||
#define ECHO_FIR( i ) (m.echo_hist_pos [i])
|
||||
|
||||
// Calculate FIR point for left/right channel
|
||||
#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6)
|
||||
|
||||
#define ECHO_CLOCK( n ) inline static void echo_##n( void )
|
||||
|
||||
static inline void echo_read( int ch )
|
||||
{
|
||||
uint8_t const* in = ECHO_PTR( ch );
|
||||
int s = (int8_t) in [1] * 0x100 + in [0];
|
||||
// second copy simplifies wrap-around handling
|
||||
ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
|
||||
}
|
||||
|
||||
ECHO_CLOCK( 22 )
|
||||
{
|
||||
// History
|
||||
if ( ++m.echo_hist_pos >= &m.echo_hist [spc_dsp_echo_hist_size] )
|
||||
m.echo_hist_pos = m.echo_hist;
|
||||
|
||||
m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
|
||||
echo_read( 0 );
|
||||
|
||||
// FIR (using l and r temporaries below helps compiler optimize)
|
||||
int l = CALC_FIR( 0, 0 );
|
||||
int r = CALC_FIR( 0, 1 );
|
||||
|
||||
m.t_echo_in [0] = l;
|
||||
m.t_echo_in [1] = r;
|
||||
}
|
||||
ECHO_CLOCK( 23 )
|
||||
{
|
||||
int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 );
|
||||
int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 );
|
||||
|
||||
m.t_echo_in [0] += l;
|
||||
m.t_echo_in [1] += r;
|
||||
|
||||
echo_read( 1 );
|
||||
}
|
||||
ECHO_CLOCK( 24 )
|
||||
{
|
||||
int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 );
|
||||
int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 );
|
||||
|
||||
m.t_echo_in [0] += l;
|
||||
m.t_echo_in [1] += r;
|
||||
}
|
||||
ECHO_CLOCK( 25 )
|
||||
{
|
||||
int l = m.t_echo_in [0] + CALC_FIR( 6, 0 );
|
||||
int r = m.t_echo_in [1] + CALC_FIR( 6, 1 );
|
||||
|
||||
l = (int16_t) l;
|
||||
r = (int16_t) r;
|
||||
|
||||
l += (int16_t) CALC_FIR( 7, 0 );
|
||||
r += (int16_t) CALC_FIR( 7, 1 );
|
||||
|
||||
CLAMP16( l );
|
||||
CLAMP16( r );
|
||||
|
||||
m.t_echo_in [0] = l & ~1;
|
||||
m.t_echo_in [1] = r & ~1;
|
||||
}
|
||||
static inline int echo_output( int ch )
|
||||
{
|
||||
int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) +
|
||||
(int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7);
|
||||
CLAMP16( out );
|
||||
return out;
|
||||
}
|
||||
ECHO_CLOCK( 26 )
|
||||
{
|
||||
// Left output volumes
|
||||
// (save sample for next clock so we can output both together)
|
||||
m.t_main_out [0] = echo_output( 0 );
|
||||
|
||||
// Echo feedback
|
||||
int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7);
|
||||
int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7);
|
||||
|
||||
CLAMP16( l );
|
||||
CLAMP16( r );
|
||||
|
||||
m.t_echo_out [0] = l & ~1;
|
||||
m.t_echo_out [1] = r & ~1;
|
||||
}
|
||||
ECHO_CLOCK( 27 )
|
||||
{
|
||||
// Output
|
||||
int outl = m.t_main_out [0];
|
||||
int outr = echo_output( 1 );
|
||||
m.t_main_out [0] = 0;
|
||||
m.t_main_out [1] = 0;
|
||||
|
||||
// TODO: global muting isn't this simple (turns DAC on and off
|
||||
// or something, causing small ~37-sample pulse when first muted)
|
||||
if ( REG(flg) & 0x40 )
|
||||
{
|
||||
outl = 0;
|
||||
outr = 0;
|
||||
}
|
||||
|
||||
// Output sample to DAC
|
||||
#ifdef SPC_DSP_OUT_HOOK
|
||||
SPC_DSP_OUT_HOOK( outl, outr );
|
||||
#else
|
||||
spc_dsp_sample_t* out = m_spc_dsp_out;
|
||||
assert( !out || out < m_spc_dsp_out_end ); // fails if output buffer is too small
|
||||
if ( out != m_spc_dsp_out_end )
|
||||
{
|
||||
out [0] = outl;
|
||||
out [1] = outr;
|
||||
m_spc_dsp_out = out + 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ECHO_CLOCK( 28 )
|
||||
{
|
||||
m.t_echo_enabled = REG(flg);
|
||||
}
|
||||
static inline void echo_write( int ch )
|
||||
{
|
||||
if ( !(m.t_echo_enabled & 0x20) )
|
||||
{
|
||||
uint8_t* out = ECHO_PTR( ch );
|
||||
int s = m.t_echo_out [ch];
|
||||
out [0] = (uint8_t) s;
|
||||
out [1] = (uint8_t) (s >> 8);
|
||||
}
|
||||
m.t_echo_out [ch] = 0;
|
||||
}
|
||||
ECHO_CLOCK( 29 )
|
||||
{
|
||||
m.t_esa = REG(esa);
|
||||
|
||||
if ( !m.echo_offset )
|
||||
m.echo_length = (REG(edl) & 0x0F) * 0x800;
|
||||
|
||||
m.echo_offset += 4;
|
||||
if ( m.echo_offset >= m.echo_length )
|
||||
m.echo_offset = 0;
|
||||
|
||||
// Write left echo
|
||||
echo_write( 0 );
|
||||
|
||||
m.t_echo_enabled = REG(flg);
|
||||
}
|
||||
ECHO_CLOCK( 30 )
|
||||
{
|
||||
// Write right echo
|
||||
echo_write( 1 );
|
||||
}
|
||||
|
||||
|
||||
//// Timing
|
||||
|
||||
#if !SPC_DSP_CUSTOM_RUN
|
||||
|
||||
void spc_dsp_run( int clocks_remain )
|
||||
{
|
||||
assert( clocks_remain > 0 );
|
||||
|
||||
int const phase = m.phase;
|
||||
m.phase = (phase + clocks_remain) & 31;
|
||||
switch ( phase )
|
||||
{
|
||||
loop:
|
||||
|
||||
#define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
|
||||
#include "spc_dsp_timing.h"
|
||||
#undef PHASE
|
||||
|
||||
if ( --clocks_remain )
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//// Setup
|
||||
|
||||
void spc_dsp_reset( void )
|
||||
{
|
||||
// Clear everything to zero, then set things which must be non-zero
|
||||
memset( m_voice_state, 0, sizeof m_voice_state );
|
||||
memset( &m_spc_dsp, 0, sizeof m_spc_dsp );
|
||||
|
||||
m.noise = 1;
|
||||
m.echo_hist_pos = m.echo_hist;
|
||||
m.every_other_sample = 1;
|
||||
init_counters();
|
||||
|
||||
int i;
|
||||
for ( i = spc_dsp_voice_count; --i >= 0; )
|
||||
{
|
||||
voice_t* v = &m_voice_state [i];
|
||||
v->regs = &m.regs [i * 0x10];
|
||||
v->vbit = 1 << i;
|
||||
v->brr_offset = 1;
|
||||
}
|
||||
|
||||
REG(flg) = 0xE0;
|
||||
}
|
||||
|
||||
void spc_dsp_soft_reset( void )
|
||||
{
|
||||
// TODO: doesn't reset everything
|
||||
spc_dsp_reset();
|
||||
}
|
||||
|
||||
void spc_dsp_init( void* ram_64k )
|
||||
{
|
||||
m_ram = (uint8_t*) ram_64k;
|
||||
spc_dsp_reset();
|
||||
|
||||
#if INT_MAX < 0x7FFFFFFF
|
||||
#error "Requires that int have at least 32 bits"
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
// be sure this sign-extends
|
||||
assert( (int16_t) 0x8000 == -0x8000 );
|
||||
|
||||
// be sure right shift preserves sign
|
||||
assert( (-1 >> 1) == -1 );
|
||||
|
||||
// check clamp macro
|
||||
int i;
|
||||
i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
|
||||
i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void spc_dsp_load( uint8_t const regs [spc_dsp_register_count] )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < 0x80; i++ )
|
||||
spc_dsp_write( i, regs [i] );
|
||||
m.t_esa = regs [r_esa];
|
||||
m.t_dir = regs [r_dir];
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// SNES SPC-700 DSP emulator
|
||||
|
||||
#ifndef SPC_DSP_H
|
||||
#define SPC_DSP_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//// Setup
|
||||
|
||||
// Initializes DSP and has it use the 64K RAM provided
|
||||
void spc_dsp_init( void* ram_64k );
|
||||
|
||||
// Restores DSP registers using supplied values
|
||||
enum { spc_dsp_register_count = 128 };
|
||||
void spc_dsp_load( uint8_t const regs [spc_dsp_register_count] );
|
||||
|
||||
// Mutes voice n if bit 1<<b is set
|
||||
enum { spc_dsp_voice_count = 8 };
|
||||
static void spc_dsp_mute_voices( int mask );
|
||||
|
||||
// Sets destination for output samples. If out is NULL or out_size is 0,
|
||||
// doesn't generate any.
|
||||
typedef short spc_dsp_sample_t;
|
||||
static void spc_dsp_set_output( spc_dsp_sample_t* out, int out_size );
|
||||
|
||||
// Number of samples written to output since it was last set, always
|
||||
// a multiple of 2
|
||||
static int spc_dsp_sample_count( void );
|
||||
|
||||
|
||||
//// Emulation
|
||||
|
||||
// Resets DSP to power-on state. Does not affect anything set by above functions.
|
||||
void spc_dsp_reset( void );
|
||||
|
||||
// Emulates pressing reset switch on SNES
|
||||
void spc_dsp_soft_reset( void );
|
||||
|
||||
// Reads/writes DSP registers. For accuracy, you must first call spc_run_dsp()
|
||||
// to catch the DSP up to present.
|
||||
static int spc_dsp_read( int addr );
|
||||
static void spc_dsp_write( int addr, int data );
|
||||
|
||||
// Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
|
||||
// a pair of samples will be generated.
|
||||
void spc_dsp_run( int clock_count );
|
||||
|
||||
|
||||
//// private
|
||||
|
||||
enum { spc_dsp_echo_hist_size = 8 };
|
||||
|
||||
extern spc_dsp_sample_t* m_spc_dsp_out_begin;
|
||||
extern spc_dsp_sample_t* m_spc_dsp_out;
|
||||
extern spc_dsp_sample_t* m_spc_dsp_out_end;
|
||||
|
||||
typedef struct spc_dsp_t
|
||||
{
|
||||
uint8_t regs [spc_dsp_register_count];
|
||||
|
||||
// Echo history keeps most recent 8 samples (twice the size to simplify wrap handling)
|
||||
int echo_hist [spc_dsp_echo_hist_size * 2] [2];
|
||||
int (*echo_hist_pos) [2]; // &echo_hist [0 to 7]
|
||||
int mute_mask;
|
||||
|
||||
int every_other_sample; // toggles every sample
|
||||
int kon; // KON value when last checked
|
||||
int noise;
|
||||
int counter;
|
||||
int echo_offset; // offset from ESA in echo buffer
|
||||
int echo_length; // number of bytes that echo_offset will stop at
|
||||
int phase; // next clock cycle to run (0-31)
|
||||
|
||||
// Hidden registers also written to when main register is written to
|
||||
int new_kon;
|
||||
int endx_buf;
|
||||
int envx_buf;
|
||||
int outx_buf;
|
||||
|
||||
// Temporary state between clocks
|
||||
|
||||
// read once per sample
|
||||
int t_pmon;
|
||||
int t_non;
|
||||
int t_eon;
|
||||
int t_dir;
|
||||
int t_koff;
|
||||
|
||||
// read a few clocks ahead then used
|
||||
int t_brr_next_addr;
|
||||
int t_adsr0;
|
||||
int t_brr_header;
|
||||
int t_brr_byte;
|
||||
int t_srcn;
|
||||
int t_esa;
|
||||
int t_echo_enabled;
|
||||
|
||||
// internal state that is recalculated every sample
|
||||
int t_dir_addr;
|
||||
int t_pitch;
|
||||
int t_output;
|
||||
int t_looped;
|
||||
int t_echo_ptr;
|
||||
|
||||
// left/right sums
|
||||
int t_main_out [2];
|
||||
int t_echo_out [2];
|
||||
int t_echo_in [2];
|
||||
|
||||
} spc_dsp_t;
|
||||
extern spc_dsp_t m_spc_dsp;
|
||||
|
||||
static inline int spc_dsp_read( int addr )
|
||||
{
|
||||
assert( (unsigned) addr < spc_dsp_register_count );
|
||||
return m_spc_dsp.regs [addr];
|
||||
}
|
||||
|
||||
static inline void spc_dsp_write( int addr, int data )
|
||||
{
|
||||
assert( (unsigned) addr < spc_dsp_register_count );
|
||||
|
||||
m_spc_dsp.regs [addr] = data;
|
||||
switch ( addr & 0x0F )
|
||||
{
|
||||
case 0x08:
|
||||
m_spc_dsp.envx_buf = data;
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
m_spc_dsp.outx_buf = data;
|
||||
break;
|
||||
|
||||
case 0x0C:
|
||||
if ( addr == 0x4C ) // KON
|
||||
m_spc_dsp.new_kon = data;
|
||||
|
||||
if ( addr == 0x7C ) // ENDX, write always clears it regardless of data
|
||||
{
|
||||
m_spc_dsp.endx_buf = 0;
|
||||
m_spc_dsp.regs [0x7C] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void spc_dsp_mute_voices( int mask ) { m_spc_dsp.mute_mask = mask; }
|
||||
|
||||
static inline void spc_dsp_set_output( spc_dsp_sample_t* out, int out_size )
|
||||
{
|
||||
assert( out_size % 2 == 0 ); // must be even
|
||||
m_spc_dsp_out_begin = out;
|
||||
m_spc_dsp_out = out;
|
||||
if ( out )
|
||||
out += out_size;
|
||||
m_spc_dsp_out_end = out;
|
||||
}
|
||||
|
||||
static inline int spc_dsp_sample_count( void ) { return m_spc_dsp_out - m_spc_dsp_out_begin; }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
// Execute clock for a particular voice
|
||||
#define V( clock, voice ) voice_##clock( &m_voice_state [voice] );
|
||||
|
||||
/* The most common sequence of clocks uses composite operations
|
||||
for efficiency. For example, the following are equivalent to the
|
||||
individual steps on the right:
|
||||
|
||||
V(2_31 ,2) -> V( 2,2) V(31,3)
|
||||
V(3_0_29,2) -> V( 3,2) V( 0,3) V(29,4)
|
||||
V(4_1_30,2) -> V( 4,2) V( 1,3) V(30,4) */
|
||||
|
||||
// Voice 0 1 2 3 4 5 6 7
|
||||
PHASE( 0) V(V5,0)V(V2,1)
|
||||
PHASE( 1) V(V6,0)V(V3,1)
|
||||
PHASE( 2) V(V7_V4_V1,0)
|
||||
PHASE( 3) V(V8_V5_V2,0)
|
||||
PHASE( 4) V(V9_V6_V3,0)
|
||||
PHASE( 5) V(V7_V4_V1,1)
|
||||
PHASE( 6) V(V8_V5_V2,1)
|
||||
PHASE( 7) V(V9_V6_V3,1)
|
||||
PHASE( 8) V(V7_V4_V1,2)
|
||||
PHASE( 9) V(V8_V5_V2,2)
|
||||
PHASE(10) V(V9_V6_V3,2)
|
||||
PHASE(11) V(V7_V4_V1,3)
|
||||
PHASE(12) V(V8_V5_V2,3)
|
||||
PHASE(13) V(V9_V6_V3,3)
|
||||
PHASE(14) V(V7_V4_V1,4)
|
||||
PHASE(15) V(V8_V5_V2,4)
|
||||
PHASE(16) V(V9_V6_V3,4)
|
||||
PHASE(17) V(V1,0) V(V7,5)V(V4,6)
|
||||
PHASE(18) V(V8_V5_V2,5)
|
||||
PHASE(19) V(V9_V6_V3,5)
|
||||
PHASE(20) V(V1,1) V(V7,6)V(V4,7)
|
||||
PHASE(21) V(V8,6)V(V5,7) V(V2,0) // t_brr_next_addr order dependency
|
||||
PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();
|
||||
PHASE(23) V(V7,7) echo_23();
|
||||
PHASE(24) V(V8,7) echo_24();
|
||||
PHASE(25) V(V3b,0) V(V9,7) echo_25();
|
||||
PHASE(26) echo_26();
|
||||
PHASE(27) misc_27(); echo_27();
|
||||
PHASE(28) misc_28(); echo_28();
|
||||
PHASE(29) misc_29(); echo_29();
|
||||
PHASE(30) misc_30();V(V3c,0) echo_30();
|
||||
PHASE(31) V(V4,0) V(V1,2)
|
||||
|
||||
#undef V
|
||||
@@ -0,0 +1,43 @@
|
||||
// Byte order handling
|
||||
|
||||
#ifndef SPC_ENDIAN_H
|
||||
#define SPC_ENDIAN_H
|
||||
|
||||
//#include <stdint.h>
|
||||
|
||||
static inline unsigned get_le16( void const* p )
|
||||
{
|
||||
return ((uint8_t const*) p) [1] * 0x100u +
|
||||
((uint8_t const*) p) [0];
|
||||
}
|
||||
|
||||
static inline int get_le16s( void const* p )
|
||||
{
|
||||
return ((int8_t const*) p) [1] * 0x100 +
|
||||
((uint8_t const*) p) [0];
|
||||
}
|
||||
|
||||
static inline void set_le16( void* p, unsigned n )
|
||||
{
|
||||
((uint8_t*) p) [1] = (uint8_t) (n >> 8);
|
||||
((uint8_t*) p) [0] = (uint8_t) n;
|
||||
}
|
||||
|
||||
// *A versions are used where data is aligned
|
||||
// Sometimes BIG_ENDIAN is defined to 0x1234 or something, so treat values
|
||||
// other than 1 as false.
|
||||
#if BIG_ENDIAN != 1
|
||||
#define GET_LE16A( addr ) (*(uint16_t const*) (addr))
|
||||
#define GET_LE16SA( addr ) (*( int16_t const*) (addr))
|
||||
#define SET_LE16A( addr, data ) (void) (*(uint16_t*) (addr) = (data))
|
||||
|
||||
#else
|
||||
#define GET_LE16A( addr ) get_le16 ( addr )
|
||||
#define GET_LE16SA( addr ) get_le16s( addr )
|
||||
#define SET_LE16A( addr, data ) set_le16 ( addr, data )
|
||||
#endif
|
||||
|
||||
#define GET_LE16( addr ) GET_LE16A( addr )
|
||||
#define SET_LE16( addr, data ) SET_LE16A( addr, data )
|
||||
|
||||
#endif
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
class DSP {
|
||||
public:
|
||||
class DSP { public:
|
||||
virtual void enter() = 0;
|
||||
|
||||
virtual uint8 read (uint8 addr) = 0;
|
||||
virtual void write(uint8 addr, uint8 data) = 0;
|
||||
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual uint32 run() = 0;
|
||||
|
||||
DSP() {}
|
||||
virtual ~DSP() {}
|
||||
|
||||
+1
-2
@@ -20,13 +20,12 @@
|
||||
|
||||
#include "cpu/cpu.h"
|
||||
#include "cpu/scpu/scpu.h"
|
||||
//#include "cpu/bcpu/bcpu.h"
|
||||
|
||||
#include "smp/smp.h"
|
||||
#include "smp/ssmp/ssmp.h"
|
||||
//#include "smp/bsmp/bsmp.h"
|
||||
|
||||
#include "dsp/dsp.h"
|
||||
//#include "dsp/adsp/adsp.h"
|
||||
#include "dsp/bdsp/bdsp.h"
|
||||
|
||||
#include "ppu/ppu.h"
|
||||
|
||||
+17
-10
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
libarray : version 0.07 ~byuu (10/14/06)
|
||||
libarray : version 0.09 ~byuu (2007-03-06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBARRAY
|
||||
#define __LIBARRAY
|
||||
#ifndef LIBARRAY_H
|
||||
#define LIBARRAY_H
|
||||
|
||||
template<typename T> class array {
|
||||
protected:
|
||||
@@ -25,14 +25,10 @@ protected:
|
||||
|
||||
public:
|
||||
uint size() { return buffersize; }
|
||||
uint capacity() { return buffersize; }
|
||||
uint capacity() { return poolsize; }
|
||||
|
||||
void reset() {
|
||||
if(pool) {
|
||||
free(pool);
|
||||
pool = 0;
|
||||
}
|
||||
|
||||
safe_free(pool);
|
||||
poolsize = 0;
|
||||
buffersize = 0;
|
||||
}
|
||||
@@ -44,7 +40,7 @@ public:
|
||||
buffersize = size;
|
||||
}
|
||||
|
||||
pool = static_cast<T*>(realloc(pool, sizeof(T) * size));
|
||||
pool = (T*)realloc(pool, sizeof(T) * size);
|
||||
poolsize = size;
|
||||
}
|
||||
|
||||
@@ -69,6 +65,17 @@ public:
|
||||
|
||||
~array() { reset(); }
|
||||
|
||||
array &operator=(array &source) {
|
||||
safe_free(pool);
|
||||
buffersize = source.buffersize;
|
||||
poolsize = source.poolsize;
|
||||
//allocate entire pool size ...
|
||||
pool = (T*)realloc(pool, sizeof(T) * poolsize);
|
||||
//... but only copy used pool objects
|
||||
memcpy(pool, source.pool, sizeof(T) * buffersize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline T &operator[](int index) {
|
||||
if(index >= buffersize)resize(index + 1);
|
||||
if(index >= buffersize)throw "array[] out of bounds";
|
||||
|
||||
Loaded 100 of 342 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user