mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-18 18:12:48 +02:00
Compare commits
73 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0114e10ede | ||
|
8c591ce44a | ||
|
e2cc164f70 | ||
|
d09e54149b | ||
|
8e4f1be189 | ||
|
f529a84fd1 | ||
|
567d415290 | ||
|
435a194ccd | ||
|
df9de289b9 | ||
|
dd83559786 | ||
|
100ef3a271 | ||
|
bccc5b5a12 | ||
|
acee547da9 | ||
|
b1b146fd7d | ||
|
53e913e225 | ||
|
0cf16ce784 | ||
|
ce38d577ef | ||
|
0a87b99370 | ||
|
82d5761705 | ||
|
9133129209 | ||
|
7d83cde40a | ||
|
bbc77a6cf2 | ||
|
ebb9367c68 | ||
|
96fe8f760d | ||
|
8abd1b2dfe | ||
|
f6efcbe6fd | ||
|
36859ea52c | ||
|
64589148d4 | ||
|
89ae1101ee | ||
|
340d86845a | ||
|
b895f29bed | ||
|
1ef279cb83 | ||
|
0241dd78b7 | ||
|
a13c3aece6 | ||
|
20977817ae | ||
|
ba25c82939 | ||
|
3babe932fd | ||
|
6bdeaef0f4 | ||
|
9e3827e2a2 | ||
|
e499670ad9 | ||
|
805398e5a8 | ||
|
7e6e3e3a69 | ||
|
16ba1d1191 | ||
|
29c871ef62 | ||
|
42f1d08c02 | ||
|
521f4f6952 | ||
|
92cfb1268a | ||
|
4d922ba17c | ||
|
3b2918791c | ||
|
b7d34a8aa3 | ||
|
8fd90cc123 | ||
|
e651beb72e | ||
|
4cbba77fc7 | ||
|
1194d3f9dc | ||
|
89a1b3d65f | ||
|
5a82cdf978 | ||
|
52be510d2b | ||
|
8b7219bdef | ||
|
926ffd9695 | ||
|
a1389a2ba3 | ||
|
5263ffb7aa | ||
|
1744bcb99c | ||
|
6362044c05 | ||
|
319b244af4 | ||
|
a3f1802845 | ||
|
4370acae2e | ||
|
5a804eac58 | ||
|
3b65b50aea | ||
|
a85ff8c437 | ||
|
a15d15047c | ||
|
f77aca7172 | ||
|
c32195cbd6 | ||
|
161366df9b |
12
license.txt
12
license.txt
@@ -1,5 +1,5 @@
|
||||
bsnes (TM) Reference License
|
||||
Copyright (C) 2004 - 2007 byuu
|
||||
Copyright (C) 2004 - 2008 byuu
|
||||
All rights reserved
|
||||
|
||||
1. Definitions
|
||||
@@ -53,21 +53,19 @@ 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 decompressor, author: NSRT Team, license: GPL (*)
|
||||
JMA decompressor, author: NSRT Team, license: GPL*
|
||||
NTSC filter, author: blargg, license: LGPL
|
||||
zlib decompressor, license: zlib license
|
||||
|
||||
(*) bsnes has received an exemption from the copyright holder to use this work.
|
||||
(* bsnes has received an exemption from the copyright holder to use this work.)
|
||||
|
||||
The software also includes works which have been released to the public domain,
|
||||
which are not bound to any licensing agreements. Below is a complete list of all
|
||||
such software.
|
||||
|
||||
libco, author: byuu
|
||||
libui, author: byuu
|
||||
OBC-1 emu, author: byuu
|
||||
S-DD1 emu, author: Andreas Naive
|
||||
S-RTC emu, author: byuu
|
||||
S-DD1 decompressor, author: Andreas Naive
|
||||
SPC7110 decompressor, author: neviksti
|
||||
|
||||
Any software listed above as exemptions may be relicensed individually from
|
||||
bsnes under their respective terms. However, no bsnes licensed portions can be
|
||||
|
88
readme.txt
88
readme.txt
@@ -1,10 +1,11 @@
|
||||
bsnes
|
||||
Version 0.027
|
||||
Version: 0.036
|
||||
Author: byuu
|
||||
|
||||
--------
|
||||
========
|
||||
General:
|
||||
--------
|
||||
========
|
||||
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
||||
October 14th, 2004.
|
||||
|
||||
@@ -13,18 +14,37 @@ http://byuu.org/
|
||||
|
||||
Please see license.txt for important licensing information.
|
||||
|
||||
--------------
|
||||
Shortcut Keys:
|
||||
--------------
|
||||
Esc - Toggle menubar visibility
|
||||
F11 - Toggle fullscreen mode
|
||||
==============
|
||||
Configuration:
|
||||
==============
|
||||
|
||||
bsnes has two configuration files: bsnes.cfg, for program settings; and
|
||||
locale.cfg, for localization.
|
||||
|
||||
For each file, bsnes will start by looking inside the same folder where the
|
||||
bsnes executable is located. If said file is not found, it will then check your
|
||||
user profile folder. On Windows, this is located at "%APPDATA%/.bsnes". On all
|
||||
other operating systems, this is located at "~/.bsnes". If said file is still
|
||||
not found, it will automatically be created in your user profile folder.
|
||||
|
||||
If you wish to use bsnes in single-user mode, be sure that both files exist
|
||||
inside the same folder as the bsnes executable. If they do not, you can simply
|
||||
create new blank files and bsnes will use them in the future.
|
||||
|
||||
If you wish to use bsnes in multi-user mode, simply delete these two files from
|
||||
the bsnes executable directory if they exist.
|
||||
|
||||
If you wish to have multiple configuration profiles for the same user, you will
|
||||
need to make copies of the bsnes executable, and use each one in single-user
|
||||
mode.
|
||||
|
||||
====================
|
||||
Known Limitation(s):
|
||||
====================
|
||||
|
||||
------------------
|
||||
Known Limitations:
|
||||
------------------
|
||||
S-CPU
|
||||
- Invalid DMA / HDMA transfers not fully emulated
|
||||
- Multiply / Divide register delays not implemented
|
||||
- Multiply / divide register delays not implemented
|
||||
- "Glitch" when reading joypad registers during auto polling not implemented
|
||||
|
||||
S-PPU
|
||||
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
|
||||
@@ -40,9 +60,20 @@ Hardware Bugs
|
||||
- S-CPU.r1 HDMA crashing bug not emulated
|
||||
- S-CPU<>S-SMP communication bus conflicts not emulated
|
||||
|
||||
---------------------
|
||||
===============
|
||||
Known Issue(s):
|
||||
===============
|
||||
|
||||
On Windows, attempting to load a ZIP, GZ or JMA compressed archive with
|
||||
non-ANSI characters in the filename will fail. This is because Windows
|
||||
requires UTF-16 encoding, but these libraries only work with UTF-8.
|
||||
Note that loading uncompressed images (SMC, SFC, etc) with non-ANSI characters
|
||||
works properly on all platforms.
|
||||
|
||||
=====================
|
||||
Unsupported Hardware:
|
||||
---------------------
|
||||
=====================
|
||||
|
||||
SA-1
|
||||
Coprocessor used in many popular games, including:
|
||||
- Dragon Ball Z Hyper Dimension
|
||||
@@ -59,26 +90,27 @@ Coprocessor used in many popular games, including:
|
||||
- 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
|
||||
|
||||
ST-011
|
||||
SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
|
||||
SETA DSP used by Quick-move Shogi Match with Nidan Rank-holder Morita
|
||||
|
||||
ST-018
|
||||
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
||||
SETA RISC CPU used by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
||||
|
||||
Super Gameboy
|
||||
Cartridge passthrough used for playing Gameboy games
|
||||
|
||||
------------------------
|
||||
Unsupported Controllers:
|
||||
------------------------
|
||||
==========================
|
||||
Unsupported Controller(s):
|
||||
==========================
|
||||
|
||||
Mouse
|
||||
Super Scope
|
||||
Justifier
|
||||
Multitap (4-port and 5-port)
|
||||
|
||||
=============
|
||||
Contributors:
|
||||
=============
|
||||
|
||||
Andreas Naive, anomie, blargg, DMV27, FitzRoy, GIGO, Jonas Quinn, kode54, krom,
|
||||
mudlord, Nach, neviksti, Overload, RedDwarf, Richard Bannister, tetsuo55, TRAC,
|
||||
zones
|
||||
|
423
src/Makefile
423
src/Makefile
@@ -1,333 +1,280 @@
|
||||
######################
|
||||
### bsnes makefile ###
|
||||
######################
|
||||
include lib/nall/Makefile.string
|
||||
prefix = /usr/local
|
||||
|
||||
ifeq ($(PLATFORM),)
|
||||
null_: help
|
||||
################
|
||||
### compiler ###
|
||||
################
|
||||
|
||||
ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
||||
flags = -O3 -fomit-frame-pointer -Ilib
|
||||
c = $(compiler) $(flags)
|
||||
cpp = $(subst cc,++,$(compiler)) $(flags)
|
||||
obj = o
|
||||
rule = -c $< -o $@
|
||||
link = -s
|
||||
mkbin = -o$1
|
||||
mkdef = -D$1
|
||||
mklib = -l$1
|
||||
else ifeq ($(compiler),cl) # Visual C++
|
||||
flags = /nologo /wd4355 /wd4996 /O2 /EHsc /Ilib
|
||||
c = cl $(flags)
|
||||
cpp = cl $(flags)
|
||||
obj = obj
|
||||
rule = /c $< /Fo$@
|
||||
link = /link
|
||||
mkbin = /Fe$1
|
||||
mkdef = /D$1
|
||||
mklib = $1.lib
|
||||
else
|
||||
unknown_compiler: help;
|
||||
endif
|
||||
|
||||
##################################
|
||||
### platform-specific settings ###
|
||||
##################################
|
||||
##########
|
||||
### os ###
|
||||
##########
|
||||
|
||||
PREFIX = /usr/local
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-x86)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco.x86
|
||||
MIU = miu.gtk
|
||||
VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ)
|
||||
ifeq ($(platform),x) # X11
|
||||
ruby = video.glx video.xv video.sdl audio.openal audio.oss audio.alsa audio.ao input.sdl input.x
|
||||
link += `pkg-config --libs gtk+-2.0`
|
||||
link += $(call mklib,Xtst)
|
||||
delete = rm -f $1
|
||||
else ifeq ($(platform),win) # Windows
|
||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.directinput
|
||||
link += $(if $(findstring mingw,$(compiler)),-mwindows)
|
||||
link += $(call mklib,uuid)
|
||||
link += $(call mklib,kernel32)
|
||||
link += $(call mklib,user32)
|
||||
link += $(call mklib,gdi32)
|
||||
link += $(call mklib,shell32)
|
||||
link += $(call mklib,winmm)
|
||||
link += $(call mklib,comdlg32)
|
||||
link += $(call mklib,comctl32)
|
||||
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
||||
else
|
||||
unknown_platform: help;
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-x86-64)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_MIU `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf64
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco.x86-64
|
||||
MIU = miu.gtk
|
||||
VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ)
|
||||
endif
|
||||
############
|
||||
### ruby ###
|
||||
############
|
||||
|
||||
ifeq ($(PLATFORM),win-mingw-x86)
|
||||
OS = win
|
||||
CC = mingw32-gcc
|
||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN
|
||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
||||
LIBCO = libco.x86
|
||||
MIU = miu.win
|
||||
VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ)
|
||||
endif
|
||||
rubyflags =
|
||||
rubyflags += $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-x86)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_MIU
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LIBCO = libco.x86
|
||||
MIU = miu.win
|
||||
VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ)
|
||||
endif
|
||||
|
||||
#####################################
|
||||
### compiler / assembler switches ###
|
||||
#####################################
|
||||
|
||||
ifeq ($(CC),gcc)
|
||||
OUT = -obsnes
|
||||
CPP = g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OUT = -obsnes
|
||||
CPP = mingw32-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
|
||||
endif
|
||||
link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9))
|
||||
link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
|
||||
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
|
||||
link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32))
|
||||
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
|
||||
link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound))
|
||||
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
|
||||
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
||||
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
||||
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
|
||||
link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`)
|
||||
|
||||
####################################
|
||||
### main target and dependencies ###
|
||||
####################################
|
||||
|
||||
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(MIU).$(OBJ) $(VAI) bstring.$(OBJ) \
|
||||
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \
|
||||
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
|
||||
bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \
|
||||
sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \
|
||||
obc1.$(OBJ) st010.$(OBJ)
|
||||
objects = main libco hiro ruby libfilter string reader cart cheat \
|
||||
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \
|
||||
bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||
|
||||
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
|
||||
ifeq ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
flags += $(call mkdef,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
|
||||
ifeq ($(enable_jma),true)
|
||||
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
|
||||
flags += $(call mkdef,JMA_SUPPORT)
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
ifeq ($(CC),cl)
|
||||
OBJECTS += bsnes.res
|
||||
endif
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OBJECTS += bsnesrc.o
|
||||
objects := $(patsubst %,obj/%.$(obj),$(objects))
|
||||
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
|
||||
|
||||
# Windows resource file
|
||||
ifeq ($(platform),win)
|
||||
ifeq ($(compiler),cl)
|
||||
objects += obj/bsnes.res
|
||||
else ifneq ($(findstring gcc,$(compiler)),)
|
||||
objects += obj/bsnesrc.$(obj)
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(OBJECTS)
|
||||
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
|
||||
################
|
||||
### implicit ###
|
||||
################
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
######################
|
||||
compile = \
|
||||
$(strip \
|
||||
$(if $(filter %.c,$<), \
|
||||
$(c) $1 $(rule), \
|
||||
$(if $(filter %.cpp,$<), \
|
||||
$(cpp) $1 $(rule) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
%.$(OBJ): $<
|
||||
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
||||
$(if $(filter %.s,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
||||
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
|
||||
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
|
||||
%.$(obj): $<; $(call compile)
|
||||
|
||||
all: build;
|
||||
|
||||
############
|
||||
### main ###
|
||||
############
|
||||
|
||||
main.$(OBJ): ui/main.cpp config/* \
|
||||
ui/* ui/vai/* \
|
||||
ui/miu/* ui/miu/loader/* ui/miu/settings/*
|
||||
|
||||
bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
|
||||
bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o
|
||||
|
||||
##########
|
||||
### ui ###
|
||||
##########
|
||||
|
||||
video.direct3d.$(OBJ) : ui/vai/video/video.direct3d.cpp ui/vai/video/*
|
||||
video.directdraw.$(OBJ) : ui/vai/video/video.directdraw.cpp ui/vai/video/*
|
||||
video.gdi.$(OBJ) : ui/vai/video/video.gdi.cpp ui/vai/video/*
|
||||
video.gtk.$(OBJ) : ui/vai/video/video.gtk.cpp ui/vai/video/*
|
||||
video.xv.$(OBJ) : ui/vai/video/video.xv.cpp ui/vai/video/*
|
||||
audio.ao.$(OBJ) : ui/vai/audio/audio.ao.cpp ui/vai/audio/*
|
||||
audio.directsound.$(OBJ): ui/vai/audio/audio.directsound.cpp ui/vai/audio/*
|
||||
input.directinput.$(OBJ): ui/vai/input/input.directinput.cpp ui/vai/input/*
|
||||
input.x.$(OBJ) : ui/vai/input/input.x.cpp ui/vai/input/*
|
||||
|
||||
#############
|
||||
### libco ###
|
||||
#############
|
||||
|
||||
libco.x86.$(OBJ) : lib/libco/libco.x86.asm lib/libco/*
|
||||
libco.x86-64.$(OBJ): lib/libco/libco.x86-64.asm lib/libco/*
|
||||
libco.pcc.$(OBJ) : lib/libco/libco.ppc.s lib/libco/*
|
||||
libco.ppc64.$(OBJ) : lib/libco/libco.ppc64.s lib/libco/*
|
||||
|
||||
###########
|
||||
### miu ###
|
||||
###########
|
||||
|
||||
miu.gtk.$(OBJ): lib/miu.gtk/miu.gtk.cpp lib/miu.gtk/*
|
||||
miu.win.$(OBJ): lib/miu.win/miu.win.cpp lib/miu.win/*
|
||||
obj/main.$(obj): ui/main.cpp ui/* ui/base/* ui/loader/* ui/settings/*
|
||||
obj/bsnes.res: ui/bsnes.rc; rc /r /foobj/bsnes.res ui/bsnes.rc
|
||||
obj/bsnesrc.$(obj): ui/bsnes.rc; windres ui/bsnes.rc obj/bsnesrc.$(obj)
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
|
||||
bstring.$(OBJ): lib/bstring.cpp lib/*
|
||||
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/* lib/ruby/video/* lib/ruby/audio/* lib/ruby/input/*
|
||||
$(call compile,$(rubydef) $(rubyflags))
|
||||
obj/hiro.$(obj): lib/hiro/hiro.cpp lib/hiro/* lib/hiro/gtk/* lib/hiro/win/*
|
||||
$(call compile,$(if $(call streq,$(platform),x),`pkg-config --cflags gtk+-2.0`))
|
||||
obj/libco.$(obj): lib/libco/libco.c lib/libco/*
|
||||
$(call compile,-static)
|
||||
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/*
|
||||
obj/string.$(obj): lib/nall/string.cpp lib/nall/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
#################
|
||||
|
||||
reader.$(OBJ): reader/reader.cpp reader/*
|
||||
cart.$(OBJ) : cart/cart.cpp cart/*
|
||||
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
|
||||
obj/reader.$(obj): reader/reader.cpp reader/*
|
||||
obj/cart.$(obj) : cart/cart.cpp cart/*
|
||||
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
|
||||
memory.$(OBJ) : memory/memory.cpp memory/*
|
||||
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
|
||||
smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||
obj/memory.$(obj) : memory/memory.cpp memory/*
|
||||
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/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/*
|
||||
obj/cpu.$(obj) : cpu/cpu.cpp cpu/*
|
||||
obj/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/*
|
||||
obj/smp.$(obj) : smp/smp.cpp smp/*
|
||||
obj/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/*
|
||||
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
obj/bdsp.$(obj): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
||||
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
|
||||
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
|
||||
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
obj/ppu.$(obj) : ppu/ppu.cpp ppu/*
|
||||
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
|
||||
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/*
|
||||
superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/*
|
||||
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
|
||||
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
st010.$(OBJ) : chip/st010/st010.cpp chip/st010/*
|
||||
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
||||
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
||||
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### 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/*
|
||||
obj/adler32.$(obj) : reader/zlib/adler32.c reader/zlib/*
|
||||
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/*
|
||||
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/*
|
||||
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/*
|
||||
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/*
|
||||
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/*
|
||||
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/*
|
||||
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/*
|
||||
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/*
|
||||
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/*
|
||||
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/*
|
||||
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/*
|
||||
obj/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/*
|
||||
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/*
|
||||
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/*
|
||||
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/*
|
||||
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/*
|
||||
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/*
|
||||
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/*
|
||||
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/*
|
||||
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/*
|
||||
|
||||
####################
|
||||
### misc targets ###
|
||||
####################
|
||||
###############
|
||||
### targets ###
|
||||
###############
|
||||
|
||||
build: $(objects)
|
||||
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
|
||||
|
||||
install:
|
||||
install -m 775 bsnes $(PREFIX)/bin/bsnes
|
||||
install -m 775 data/bsnes.png $(PREFIX)/share/icons/bsnes.png
|
||||
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
||||
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/icons/bsnes.png
|
||||
|
||||
clean:
|
||||
-@$(RM) *.$(OBJ)
|
||||
-@$(RM) *.res
|
||||
-@$(RM) *.pgd
|
||||
-@$(RM) *.pgc
|
||||
-@$(RM) *.ilk
|
||||
-@$(RM) *.pdb
|
||||
-@$(RM) *.manifest
|
||||
-@$(call delete,obj/*.$(obj))
|
||||
-@$(call delete,*.res)
|
||||
-@$(call delete,*.pgd)
|
||||
-@$(call delete,*.pgc)
|
||||
-@$(call delete,*.ilk)
|
||||
-@$(call delete,*.pdb)
|
||||
-@$(call delete,*.manifest)
|
||||
|
||||
help:
|
||||
@echo "Usage: $(MAKE) PLATFORM=platform [options]"
|
||||
@echo "Usage: $(MAKE) platform=(os) compiler=(cc) [options]"
|
||||
@echo ""
|
||||
@echo "Available platform targets:"
|
||||
@echo " x-gcc-x86 - Linux / BSD (x86) (requires yasm)"
|
||||
@echo " x-gcc-x86-64 - Linux / BSD (x86-64) (requires yasm)"
|
||||
@echo " win-mingw-x86 - Windows (x86) (requires nasm)"
|
||||
@echo " win-visualc-x86 - Windows (x86) (requires nasm)"
|
||||
@echo "Supported platforms:"
|
||||
@echo " x - Linux / BSD (x86, x86-64)"
|
||||
@echo " win - Windows (x86, x86-64)"
|
||||
@echo ""
|
||||
@echo "Supported compilers:"
|
||||
@echo " gcc - GCC compiler"
|
||||
@echo " mingw32-gcc - MinGW compiler"
|
||||
@echo " i586-mingw32-gcc - MinGW cross compiler"
|
||||
@echo " cl - Visual C++"
|
||||
@echo ""
|
||||
@echo "Available options:"
|
||||
@echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||
@echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)"
|
||||
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||
@echo " enable_jma=[true|false] - Enable JMA support (default=false)"
|
||||
@echo ""
|
||||
@echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true"
|
||||
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
|
||||
@echo ""
|
||||
|
66
src/base.h
66
src/base.h
@@ -1,54 +1,50 @@
|
||||
#define BSNES_VERSION "0.027"
|
||||
#define BSNES_VERSION "0.036"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
#define CPUCORE sCPU
|
||||
#define SMPCORE sSMP
|
||||
#define DSPCORE bDSP
|
||||
#define DSPCORE sDSP
|
||||
#define PPUCORE bPPU
|
||||
|
||||
//FAVOR_ACCURACY calculates RTO during frameskip, whereas FAVOR_SPEED does not
|
||||
//S-DSP can be encapsulated into a state machine using #define magic
|
||||
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
|
||||
#define USE_STATE_MACHINE
|
||||
|
||||
//FAST_FRAMESKIP disables calculation of RTO during frameskip
|
||||
//frameskip offers near-zero speedup if RTO is calculated
|
||||
//accuracy is not affected by this define when frameskipping is off
|
||||
#define FAST_FRAMESKIP
|
||||
|
||||
//#define FAVOR_ACCURACY
|
||||
#define FAVOR_SPEED
|
||||
|
||||
//game genie + pro action replay code support (~1-3% speed hit)
|
||||
//game genie + pro action replay code support (~2% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
#if defined(PROCESSOR_X86) || defined(PROCESSOR_X86_64)
|
||||
#define ARCH_LSB
|
||||
#elif defined(PROCESSOR_PPC) || defined(PROCESSOR_PPC64)
|
||||
#define ARCH_MSB
|
||||
#else //guess
|
||||
#define ARCH_LSB
|
||||
#endif
|
||||
#include <nall/algorithm.hpp>
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/config.hpp>
|
||||
#include <nall/detect.hpp>
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/modulo.hpp>
|
||||
#include <nall/new.hpp>
|
||||
#include <nall/sort.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
using namespace nall;
|
||||
|
||||
#include "lib/libco.h"
|
||||
#include "lib/bbase.h"
|
||||
#include "lib/bfunction.h"
|
||||
#include "lib/barray.h"
|
||||
#include "lib/bvector.h"
|
||||
#include "lib/bkeymap.h"
|
||||
#include "lib/bstring.h"
|
||||
#include "lib/bconfig.h"
|
||||
#include <libco/libco.h>
|
||||
#include <bbase.h>
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(const char*, ...);
|
||||
void dprintf(const char*, ...);
|
||||
void dprintf(uint, const char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
none = 0,
|
||||
debug,
|
||||
cpu,
|
||||
ppu,
|
||||
smp,
|
||||
dsp,
|
||||
bus,
|
||||
};
|
||||
};
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
//helper: disable access to FILE, when possible (GZIP / JMA require it)
|
||||
//reason: Windows fopen() does not support UTF-8 filenames; use nall::file instead.
|
||||
#if !defined(GZIP_SUPPORT) && !defined(JMA_SUPPORT)
|
||||
#define FILE FILE_deprecated
|
||||
#endif
|
||||
|
BIN
src/bsnes.lnk
BIN
src/bsnes.lnk
Binary file not shown.
@@ -1,4 +1,8 @@
|
||||
#include "../base.h"
|
||||
#define CART_CPP
|
||||
|
||||
#include <nall/crc32.hpp>
|
||||
#include <nall/ups.hpp>
|
||||
|
||||
#include "cart_normal.cpp"
|
||||
#include "cart_bsx.cpp"
|
||||
@@ -9,7 +13,7 @@
|
||||
#include "cart_header.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram;
|
||||
MappedRAM cartrom, cartram, cartrtc;
|
||||
MappedRAM bscram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
@@ -23,17 +27,18 @@ Cartridge::Region Cartridge::region() { return info.region; }
|
||||
bool Cartridge::loaded() { return cart.loaded; }
|
||||
|
||||
void Cartridge::load_begin(CartridgeType cart_type) {
|
||||
cart.rom = cart.ram = 0;
|
||||
cart.rom = cart.ram = cart.rtc = 0;
|
||||
bs.ram = 0;
|
||||
stA.rom = stA.ram = 0;
|
||||
stB.rom = stB.ram = 0;
|
||||
|
||||
cart.rom_size = cart.ram_size = 0;
|
||||
cart.rom_size = cart.ram_size = cart.rtc_size = 0;
|
||||
bs.ram_size = 0;
|
||||
stA.rom_size = stA.ram_size = 0;
|
||||
stB.rom_size = stB.ram_size = 0;
|
||||
|
||||
info.type = cart_type;
|
||||
info.patched = false;
|
||||
|
||||
info.bsxbase = false;
|
||||
info.bsxcart = false;
|
||||
@@ -44,6 +49,8 @@ void Cartridge::load_begin(CartridgeType cart_type) {
|
||||
info.sa1 = false;
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.spc7110 = false;
|
||||
info.spc7110rtc = false;
|
||||
info.cx4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
@@ -58,7 +65,6 @@ void Cartridge::load_begin(CartridgeType cart_type) {
|
||||
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = LoROM;
|
||||
info.name[0] = 0;
|
||||
info.region = NTSC;
|
||||
|
||||
info.rom_size = 0;
|
||||
@@ -68,6 +74,7 @@ void Cartridge::load_begin(CartridgeType cart_type) {
|
||||
void Cartridge::load_end() {
|
||||
memory::cartrom.map(cart.rom, cart.rom_size);
|
||||
memory::cartram.map(cart.ram, cart.ram_size);
|
||||
memory::cartrtc.map(cart.rtc, cart.rtc_size);
|
||||
memory::bscram.map(bs.ram, bs.ram_size);
|
||||
memory::stArom.map(stA.rom, stA.rom_size);
|
||||
memory::stAram.map(stA.ram, stA.ram_size);
|
||||
@@ -82,12 +89,9 @@ void Cartridge::load_end() {
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
|
||||
char fn[PATH_MAX];
|
||||
strcpy(fn, cart.fn);
|
||||
modify_extension(fn, "cht");
|
||||
if(fexists(fn)) {
|
||||
if(file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||
cheat.clear();
|
||||
cheat.load(fn);
|
||||
cheat.load(cheatfn);
|
||||
}
|
||||
|
||||
cart.loaded = true;
|
||||
@@ -106,19 +110,20 @@ bool Cartridge::unload() {
|
||||
case CartridgeSufamiTurbo: unload_cart_st(); break;
|
||||
}
|
||||
|
||||
safe_free(cart.rom);
|
||||
safe_free(cart.ram);
|
||||
safe_free(bs.ram);
|
||||
safe_free(stA.rom);
|
||||
safe_free(stA.ram);
|
||||
safe_free(stB.rom);
|
||||
safe_free(stB.ram);
|
||||
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
|
||||
if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
|
||||
if(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
|
||||
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
|
||||
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
|
||||
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
|
||||
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
||||
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
||||
|
||||
char fn[PATH_MAX];
|
||||
char fn[PATH_MAX];
|
||||
strcpy(fn, cart.fn);
|
||||
modify_extension(fn, "cht");
|
||||
if(cheat.count() > 0 || fexists(fn)) {
|
||||
cheat.save(fn);
|
||||
if(cheat.count() > 0 || file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||
cheat.save(cheatfn);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
|
@@ -18,8 +18,7 @@ public:
|
||||
VERSION = 0x1b,
|
||||
ICKSUM = 0x1c,
|
||||
CKSUM = 0x1e,
|
||||
RESL = 0x3c,
|
||||
RESH = 0x3d,
|
||||
RESETV = 0x3c,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
@@ -32,6 +31,7 @@ public:
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SPC7110ROM,
|
||||
BSXROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
@@ -48,8 +48,8 @@ public:
|
||||
struct {
|
||||
bool loaded;
|
||||
char fn[PATH_MAX];
|
||||
uint8 *rom, *ram;
|
||||
uint rom_size, ram_size;
|
||||
uint8 *rom, *ram, *rtc;
|
||||
uint rom_size, ram_size, rtc_size;
|
||||
} cart;
|
||||
|
||||
struct {
|
||||
@@ -68,7 +68,8 @@ public:
|
||||
CartridgeType type;
|
||||
|
||||
uint32 crc32;
|
||||
char name[128];
|
||||
char filename[PATH_MAX * 4];
|
||||
bool patched;
|
||||
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
@@ -83,6 +84,8 @@ public:
|
||||
bool sa1;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool spc7110;
|
||||
bool spc7110rtc;
|
||||
bool cx4;
|
||||
bool dsp1;
|
||||
bool dsp2;
|
||||
@@ -116,24 +119,38 @@ public:
|
||||
void load_end();
|
||||
bool unload();
|
||||
|
||||
unsigned score_header(unsigned);
|
||||
void find_header();
|
||||
void read_header();
|
||||
void read_extended_header();
|
||||
|
||||
bool load_file(const char *fn, uint8 *&data, uint &size);
|
||||
enum CompressionMode {
|
||||
CompressionNone, //always load without compression
|
||||
CompressionInspect, //use file header inspection
|
||||
CompressionAuto, //use file extension or file header inspection (configured by user)
|
||||
};
|
||||
bool load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression = CompressionNone);
|
||||
bool save_file(const char *fn, uint8 *data, uint size);
|
||||
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size);
|
||||
char* modify_extension(char *filename, const char *extension);
|
||||
char* get_base_filename(char *filename);
|
||||
char* get_path_filename(char *filename, const char *path, const char *source, const char *extension);
|
||||
char* get_patch_filename(const char *source, const char *extension);
|
||||
char* get_save_filename(const char *source, const char *extension);
|
||||
char* get_cheat_filename(const char *source, const char *extension);
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
private:
|
||||
char patchfn[PATH_MAX];
|
||||
char savefn[PATH_MAX];
|
||||
char rtcfn[PATH_MAX];
|
||||
char cheatfn[PATH_MAX];
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern MappedRAM cartrom, cartram;
|
||||
extern MappedRAM cartrom, cartram, cartrtc;
|
||||
extern MappedRAM bscram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
||||
if(!base || !*base) return;
|
||||
|
||||
@@ -5,15 +7,24 @@ void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
||||
strcpy(bs.fn, slot ? slot : "");
|
||||
load_begin(CartridgeBSC);
|
||||
|
||||
uint8 *data;
|
||||
uint size;
|
||||
load_file(cart.fn, data, size);
|
||||
uint8_t *data = 0;
|
||||
unsigned size;
|
||||
load_file(cart.fn, data, size, CompressionAuto);
|
||||
cart.rom = data, cart.rom_size = size;
|
||||
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(*bs.fn) {
|
||||
if(load_file(bs.fn, data, size) == true) {
|
||||
if(load_file(bs.fn, data, size, CompressionAuto) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = data, bs.ram_size = size;
|
||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,18 +35,31 @@ uint size;
|
||||
info.region = NTSC;
|
||||
|
||||
if(info.ram_size > 0) {
|
||||
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
||||
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
||||
memset(cart.ram, 0xff, cart.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
strcpy(info.filename, cart.fn);
|
||||
get_base_filename(info.filename);
|
||||
if(*bs.fn) {
|
||||
char filenameBS[PATH_MAX];
|
||||
strcpy(filenameBS, bs.fn);
|
||||
get_base_filename(filenameBS);
|
||||
strcat(info.filename, " + ");
|
||||
strcat(info.filename, filenameBS);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_bsc() {
|
||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
||||
if(!base || !*base) return;
|
||||
|
||||
@@ -10,36 +12,50 @@ void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
||||
info.mapper = BSXROM;
|
||||
info.region = NTSC;
|
||||
|
||||
uint8 *data;
|
||||
uint size;
|
||||
load_file(cart.fn, data, size);
|
||||
uint8_t *data = 0;
|
||||
unsigned size;
|
||||
load_file(cart.fn, data, size, CompressionAuto);
|
||||
cart.rom = data, cart.rom_size = size;
|
||||
cart.ram = 0, cart.ram_size = 0;
|
||||
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "psr"), data, size) == true) {
|
||||
if(load_file(get_save_filename(cart.fn, "psr"), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(*bs.fn) {
|
||||
if(load_file(bs.fn, data, size) == true) {
|
||||
if(load_file(bs.fn, data, size, CompressionAuto) == true) {
|
||||
info.bsxflash = true;
|
||||
bs.ram = data, bs.ram_size = size;
|
||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
strcpy(info.filename, !*bs.fn ? cart.fn : bs.fn);
|
||||
get_base_filename(info.filename);
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_bsx() {
|
||||
save_file(get_save_filename(cart.fn, "srm"), bsxcart.sram.handle (), bsxcart.sram.size ());
|
||||
save_file(get_save_filename(cart.fn, "psr"), bsxcart.psram.handle(), bsxcart.psram.size());
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
#include "../reader/filereader.h"
|
||||
|
||||
#if defined(GZIP_SUPPORT)
|
||||
@@ -10,7 +12,7 @@
|
||||
#endif
|
||||
|
||||
char* Cartridge::modify_extension(char *filename, const char *extension) {
|
||||
int i;
|
||||
int i;
|
||||
for(i = strlen(filename); i >= 0; i--) {
|
||||
if(filename[i] == '.') break;
|
||||
if(filename[i] == '/') break;
|
||||
@@ -22,39 +24,82 @@ int i;
|
||||
return filename;
|
||||
}
|
||||
|
||||
char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||
strcpy(savefn, source);
|
||||
for(char *p = savefn; *p; p++) { if(*p == '\\') *p = '/'; }
|
||||
modify_extension(savefn, extension);
|
||||
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
|
||||
char* Cartridge::get_base_filename(char *filename) {
|
||||
//remove extension
|
||||
for(int i = strlen(filename) - 1; i >= 0; i--) {
|
||||
if(filename[i] == '.') {
|
||||
filename[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//override path with user-specified folder, if one was defined
|
||||
if(config::path.save != "") {
|
||||
//remove directory information
|
||||
for(int i = strlen(filename) - 1; i >= 0; i--) {
|
||||
if(filename[i] == '/' || filename[i] == '\\') {
|
||||
i++;
|
||||
char *output = filename;
|
||||
while(true) {
|
||||
*output++ = filename[i];
|
||||
if(!filename[i]) break;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
char* Cartridge::get_path_filename(char *filename, const char *path, const char *source, const char *extension) {
|
||||
strcpy(filename, source);
|
||||
for(char *p = filename; *p; p++) { if(*p == '\\') *p = '/'; }
|
||||
modify_extension(filename, extension);
|
||||
|
||||
//override path with user-specified folder, if one was defined
|
||||
if(*path) {
|
||||
lstring part;
|
||||
split(part, "/", savefn);
|
||||
string fn = config::path.save();
|
||||
split(part, "/", filename);
|
||||
string fn = path;
|
||||
if(strend(fn, "/") == false) strcat(fn, "/");
|
||||
strcat(fn, part[count(part) - 1]);
|
||||
strcpy(savefn, fn);
|
||||
strcpy(filename, fn);
|
||||
|
||||
//resolve relative path, if found
|
||||
if(strbegin(fn, "./") == true) {
|
||||
ltrim(fn, "./");
|
||||
strcpy(savefn, config::path.base);
|
||||
strcat(savefn, fn);
|
||||
strcpy(filename, config::path.base);
|
||||
strcat(filename, fn);
|
||||
}
|
||||
}
|
||||
|
||||
return savefn;
|
||||
return filename;
|
||||
}
|
||||
|
||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
dprintf("* Loading \"%s\"...", fn);
|
||||
char* Cartridge::get_patch_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(patchfn, config::path.patch, source, extension);
|
||||
}
|
||||
|
||||
if(fexists(fn) == false) return false;
|
||||
char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(savefn, config::path.save, source, extension);
|
||||
}
|
||||
|
||||
switch(Reader::detect(fn)) {
|
||||
char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
||||
return get_path_filename(cheatfn, config::path.cheat, source, extension);
|
||||
}
|
||||
|
||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression) {
|
||||
if(file::exists(fn) == false) return false;
|
||||
|
||||
Reader::Type filetype = Reader::Normal;
|
||||
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
||||
if(compression == CompressionAuto) filetype = Reader::detect(fn, config::file.autodetect_type);
|
||||
|
||||
switch(filetype) {
|
||||
default:
|
||||
case Reader::RF_NORMAL: {
|
||||
dprintf("* Warning: filetype detected as unsupported compression type.");
|
||||
dprintf("* Will attempt to load as uncompressed file -- may fail.");
|
||||
case Reader::Normal: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
@@ -65,7 +110,7 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
case Reader::GZIP: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
@@ -75,15 +120,19 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::RF_ZIP: {
|
||||
case Reader::ZIP: {
|
||||
ZipReader zf(fn);
|
||||
if(!zf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
case Reader::JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
@@ -99,9 +148,36 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) {
|
||||
uint8_t *outdata = 0;
|
||||
unsigned outsize;
|
||||
ups patcher;
|
||||
ups::result result = patcher.apply(pdata, psize, data, size, outdata, outsize);
|
||||
|
||||
bool apply = false;
|
||||
if(result == ups::ok) apply = true;
|
||||
if(config::file.bypass_patch_crc32 == true) {
|
||||
if(result == ups::input_crc32_invalid) apply = true;
|
||||
if(result == ups::output_crc32_invalid) apply = true;
|
||||
}
|
||||
|
||||
//if patch application was successful, replace old data, size with new data, size
|
||||
if(apply == true) {
|
||||
delete[] data;
|
||||
data = new uint8_t[size = outsize];
|
||||
memcpy(data, outdata, outsize);
|
||||
}
|
||||
|
||||
if(outdata) delete[] outdata;
|
||||
return apply;
|
||||
}
|
||||
|
||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||
FileWriter ff(fn);
|
||||
if(!ff.ready())return false;
|
||||
ff.write(data, size);
|
||||
file fp;
|
||||
if(!fp.open(fn, file::mode_write)) return false;
|
||||
fp.write(data, size);
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
|
@@ -1,13 +1,16 @@
|
||||
void Cartridge::read_header() {
|
||||
uint8 *rom = cart.rom;
|
||||
uint index = info.header_index;
|
||||
uint8 mapper = rom[index + MAPPER];
|
||||
uint8 rom_type = rom[index + ROM_TYPE];
|
||||
uint8 company = rom[index + COMPANY];
|
||||
uint8 region = rom[index + REGION] & 0x7f;
|
||||
#ifdef CART_CPP
|
||||
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
bool has_bsxflash = false;
|
||||
void Cartridge::read_header() {
|
||||
uint8 *rom = cart.rom;
|
||||
uint index = info.header_index;
|
||||
uint8 mapper = rom[index + MAPPER];
|
||||
uint8 rom_type = rom[index + ROM_TYPE];
|
||||
uint8 rom_size = rom[index + ROM_SIZE];
|
||||
uint8 company = rom[index + COMPANY];
|
||||
uint8 region = rom[index + REGION] & 0x7f;
|
||||
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
bool has_bsxflash = false;
|
||||
if(rom[index - 14] == 'Z') {
|
||||
if(rom[index - 11] == 'J') {
|
||||
uint8 n13 = rom[index - 13];
|
||||
@@ -49,6 +52,12 @@ bool has_bsxflash = false;
|
||||
info.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||
info.spc7110 = true;
|
||||
info.spc7110rtc = (rom_type == 0xf9);
|
||||
info.mapper = SPC7110ROM;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.cx4 = true;
|
||||
}
|
||||
@@ -91,13 +100,14 @@ bool has_bsxflash = false;
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf6) {
|
||||
//TODO: both ST010 and ST011 share the same mapper + rom_type
|
||||
//need way to determine which is which
|
||||
//for now, default to supported ST010
|
||||
if(mapper == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
|
||||
info.st010 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
||||
info.st011 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||
info.st018 = true;
|
||||
}
|
||||
@@ -108,71 +118,97 @@ bool has_bsxflash = false;
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||
}
|
||||
|
||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
||||
info.name[21] = 0;
|
||||
unsigned Cartridge::score_header(unsigned addr) {
|
||||
if(cart.rom_size < addr + 64) return 0; //image too small to contain header at this location?
|
||||
uint8 *rom = cart.rom;
|
||||
int score = 0;
|
||||
|
||||
for(int i = 0; i < 22; i++) {
|
||||
if(info.name[i] & 0x80) {
|
||||
info.name[i] = '?';
|
||||
}
|
||||
}
|
||||
uint16 resetvector = rom[addr + RESETV] | (rom[addr + RESETV + 1] << 8);
|
||||
uint16 checksum = rom[addr + CKSUM] | (rom[addr + CKSUM + 1] << 8);
|
||||
uint16 ichecksum = rom[addr + ICKSUM] | (rom[addr + ICKSUM + 1] << 8);
|
||||
|
||||
uint8 resetop = rom[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||
uint8 mapper = rom[addr + MAPPER] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
|
||||
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
||||
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
||||
if(resetvector < 0x8000) return 0;
|
||||
|
||||
//some images duplicate the header in multiple locations, and others have completely
|
||||
//invalid header information that cannot be relied upon.
|
||||
//below code will analyze the first opcode executed at the specified reset vector to
|
||||
//determine the probability that this is the correct header.
|
||||
|
||||
//most likely opcodes
|
||||
if(resetop == 0x78 //sei
|
||||
|| resetop == 0x18 //clc (clc; xce)
|
||||
|| resetop == 0x38 //sec (sec; xce)
|
||||
|| resetop == 0x9c //stz $nnnn (stz $4200)
|
||||
|| resetop == 0x4c //jmp $nnnn
|
||||
|| resetop == 0x5c //jml $nnnnnn
|
||||
) score += 8;
|
||||
|
||||
//plausible opcodes
|
||||
if(resetop == 0xc2 //rep #$nn
|
||||
|| resetop == 0xe2 //sep #$nn
|
||||
|| resetop == 0xad //lda $nnnn
|
||||
|| resetop == 0xae //ldx $nnnn
|
||||
|| resetop == 0xac //ldy $nnnn
|
||||
|| resetop == 0xaf //lda $nnnnnn
|
||||
|| resetop == 0xa9 //lda #$nn
|
||||
|| resetop == 0xa2 //ldx #$nn
|
||||
|| resetop == 0xa0 //ldy #$nn
|
||||
|| resetop == 0x20 //jsr $nnnn
|
||||
|| resetop == 0x22 //jsl $nnnnnn
|
||||
) score += 4;
|
||||
|
||||
//implausible opcodes
|
||||
if(resetop == 0x40 //rti
|
||||
|| resetop == 0x60 //rts
|
||||
|| resetop == 0x6b //rtl
|
||||
|| resetop == 0xcd //cmp $nnnn
|
||||
|| resetop == 0xec //cpx $nnnn
|
||||
|| resetop == 0xcc //cpy $nnnn
|
||||
) score -= 4;
|
||||
|
||||
//least likely opcodes
|
||||
if(resetop == 0x00 //brk #$nn
|
||||
|| resetop == 0x02 //cop #$nn
|
||||
|| resetop == 0xdb //stp
|
||||
|| resetop == 0x42 //wdm
|
||||
|| resetop == 0xff //sbc $nnnnnn,x
|
||||
) score -= 8;
|
||||
|
||||
//at times, both the header and reset vector's first opcode will match ...
|
||||
//fallback and rely on info validity in these cases to determine more likely header.
|
||||
|
||||
//a valid checksum is the biggest indicator of a valid header.
|
||||
if((checksum + ichecksum) == 0xffff && (checksum != 0) && (ichecksum != 0)) score += 4;
|
||||
|
||||
if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
|
||||
if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
|
||||
if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
|
||||
if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
|
||||
|
||||
if(rom[addr + COMPANY] == 0x33) score += 2; //0x33 indicates extended header
|
||||
if(rom[addr + ROM_TYPE] < 0x08) score++;
|
||||
if(rom[addr + ROM_SIZE] < 0x10) score++;
|
||||
if(rom[addr + RAM_SIZE] < 0x08) score++;
|
||||
if(rom[addr + REGION] < 14) score++;
|
||||
|
||||
if(score < 0) score = 0;
|
||||
return score;
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0,
|
||||
score_hi = 0,
|
||||
score_ex = 0;
|
||||
uint8 *rom = cart.rom;
|
||||
|
||||
if(cart.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 + COMPANY] < 3)score_lo++;
|
||||
if(rom[0xffc0 + COMPANY] < 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(cart.rom_size < 0x401000) {
|
||||
score_ex = 0;
|
||||
} else {
|
||||
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
|
||||
else score_ex += 16;
|
||||
}
|
||||
unsigned score_lo = score_header(0x007fc0);
|
||||
unsigned score_hi = score_header(0x00ffc0);
|
||||
unsigned score_ex = score_header(0x40ffc0);
|
||||
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
info.header_index = 0x007fc0;
|
||||
@@ -182,3 +218,5 @@ uint16 cksum, icksum;
|
||||
info.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
|
@@ -1,22 +1,30 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_normal(const char *filename) {
|
||||
if(!filename || !*filename) return;
|
||||
|
||||
uint8 *data;
|
||||
uint size;
|
||||
if(load_file(filename, data, size) == false) return;
|
||||
uint8_t *data = 0;
|
||||
unsigned size;
|
||||
if(load_file(filename, data, size, CompressionAuto) == false) return;
|
||||
strcpy(cart.fn, filename);
|
||||
|
||||
load_begin(CartridgeNormal);
|
||||
|
||||
//load ROM data, ignore 512-byte header if detected
|
||||
//load ROM data, ignore 512-byte header if detected
|
||||
if((size & 0x7fff) != 512) {
|
||||
cart.rom = (uint8*)malloc(cart.rom_size = size);
|
||||
cart.rom = new uint8_t[cart.rom_size = size];
|
||||
memcpy(cart.rom, data, size);
|
||||
} else {
|
||||
cart.rom = (uint8*)malloc(cart.rom_size = size - 512);
|
||||
cart.rom = new uint8_t[cart.rom_size = size - 512];
|
||||
memcpy(cart.rom, data + 512, size - 512);
|
||||
}
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
info.patched = true;
|
||||
}
|
||||
|
||||
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
|
||||
|
||||
@@ -24,18 +32,33 @@ uint size;
|
||||
read_header();
|
||||
|
||||
if(info.ram_size > 0) {
|
||||
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
||||
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
||||
memset(cart.ram, 0xff, cart.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size) == true) {
|
||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
if(info.srtc || info.spc7110rtc) {
|
||||
cart.rtc = new(zeromemory) uint8_t[cart.rtc_size = 20];
|
||||
if(load_file(get_save_filename(cart.fn, "rtc"), data, size, CompressionNone) == true) {
|
||||
memcpy(cart.rtc, data, min(size, cart.rtc_size));
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
strcpy(info.filename, cart.fn);
|
||||
get_base_filename(info.filename);
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_normal() {
|
||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||
if(cart.rtc) save_file(get_save_filename(cart.fn, "rtc"), cart.rtc, cart.rtc_size);
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
||||
if(!base || !*base) return;
|
||||
|
||||
@@ -10,50 +12,85 @@ void Cartridge::load_cart_st(const char *base, const char *slotA, const char *sl
|
||||
info.mapper = STROM;
|
||||
info.region = NTSC;
|
||||
|
||||
uint8 *data;
|
||||
uint size;
|
||||
if(load_file(cart.fn, data, size) == true) {
|
||||
cart.rom = (uint8*)malloc(cart.rom_size = 0x040000);
|
||||
uint8_t *data = 0;
|
||||
unsigned size;
|
||||
if(load_file(cart.fn, data, size, CompressionAuto) == true) {
|
||||
cart.rom = new(zeromemory) uint8_t[cart.rom_size = 0x040000];
|
||||
memcpy(cart.rom, data, min(size, cart.rom_size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
if(*stA.fn) {
|
||||
if(load_file(stA.fn, data, size) == true) {
|
||||
stA.rom = (uint8*)malloc(stA.rom_size = 0x100000);
|
||||
if(load_file(stA.fn, data, size, CompressionAuto) == true) {
|
||||
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||
memcpy(stA.rom, data, min(size, stA.rom_size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
if(load_file(get_patch_filename(stA.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, stA.rom, stA.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
stA.ram = (uint8*)malloc(stA.ram_size = 0x020000);
|
||||
stA.ram = new uint8_t[stA.ram_size = 0x020000];
|
||||
memset(stA.ram, 0xff, stA.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(stA.fn, "srm"), data, size) == true) {
|
||||
memcpy(stA.ram, data, min(size, 0x020000));
|
||||
safe_free(data);
|
||||
if(load_file(get_save_filename(stA.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(stA.ram, data, min(size, 0x020000U));
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(*stB.fn) {
|
||||
if(load_file(stB.fn, data, size) == true) {
|
||||
stB.rom = (uint8*)malloc(stB.rom_size = 0x100000);
|
||||
if(load_file(stB.fn, data, size, CompressionAuto) == true) {
|
||||
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||
memcpy(stB.rom, data, min(size, stB.rom_size));
|
||||
safe_free(data);
|
||||
delete[] data;
|
||||
if(load_file(get_patch_filename(stB.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||
apply_patch(data, size, stB.rom, stB.rom_size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
stB.ram = (uint8*)malloc(stB.ram_size = 0x020000);
|
||||
stB.ram = new uint8_t[stB.ram_size = 0x020000];
|
||||
memset(stB.ram, 0xff, stB.ram_size);
|
||||
|
||||
if(load_file(get_save_filename(stB.fn, "srm"), data, size) == true) {
|
||||
memcpy(stB.ram, data, min(size, 0x020000));
|
||||
safe_free(data);
|
||||
if(load_file(get_save_filename(stB.fn, "srm"), data, size, CompressionNone) == true) {
|
||||
memcpy(stB.ram, data, min(size, 0x020000U));
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
load_end();
|
||||
|
||||
//set base filename
|
||||
if(!*stA.fn && !*stB.fn) {
|
||||
strcpy(info.filename, cart.fn);
|
||||
get_base_filename(info.filename);
|
||||
} else if(*stA.fn && !*stB.fn) {
|
||||
strcpy(info.filename, stA.fn);
|
||||
get_base_filename(info.filename);
|
||||
} else if(!*stA.fn && *stB.fn) {
|
||||
strcpy(info.filename, stB.fn);
|
||||
get_base_filename(info.filename);
|
||||
} else {
|
||||
char filenameA[PATH_MAX], filenameB[PATH_MAX];
|
||||
strcpy(filenameA, stA.fn);
|
||||
get_base_filename(filenameA);
|
||||
strcpy(filenameB, stB.fn);
|
||||
get_base_filename(filenameB);
|
||||
strcpy(info.filename, filenameA);
|
||||
strcat(info.filename, " + ");
|
||||
strcat(info.filename, filenameB);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::unload_cart_st() {
|
||||
if(stA.ram) save_file(get_save_filename(stA.fn, "srm"), stA.ram, stA.ram_size);
|
||||
if(stB.ram) save_file(get_save_filename(stB.fn, "srm"), stB.ram, stB.ram_size);
|
||||
}
|
||||
|
||||
#endif //ifdef CART_CPP
|
||||
|
@@ -1,6 +1,3 @@
|
||||
@make -r PLATFORM=win-mingw-x86
|
||||
::@make -r PLATFORM=win-mingw-x86 GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
::@make -r PLATFORM=win-visualc-x86
|
||||
::@make -r PLATFORM=win-visualc-x86 GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
@move bsnes.exe ../bsnes.exe>nul
|
||||
@make platform=win compiler=mingw32-gcc
|
||||
::@make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||
@pause
|
@@ -1 +1,2 @@
|
||||
make PLATFORM=x-gcc-x86
|
||||
make platform=x compiler=gcc
|
||||
#make platform=x compiler=gcc enable_gzip=true enable_jma=true
|
||||
|
@@ -10,21 +10,21 @@ Cheat cheat;
|
||||
*****/
|
||||
|
||||
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
||||
string t, part;
|
||||
string t, part;
|
||||
strcpy(t, str);
|
||||
strlower(t());
|
||||
if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) {
|
||||
type = CT_PRO_ACTION_REPLAY;
|
||||
type = ProActionReplay;
|
||||
replace(t, ":", "");
|
||||
uint32 r = strhex(t);
|
||||
uint32 r = strhex((const char*)t);
|
||||
addr = r >> 8;
|
||||
data = r & 0xff;
|
||||
return true;
|
||||
} else if(strlen(t) == 9 && t()[4] == '-') {
|
||||
type = CT_GAME_GENIE;
|
||||
type = GameGenie;
|
||||
replace(t, "-", "");
|
||||
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
||||
uint32 r = strhex(t);
|
||||
uint32 r = strhex((const char*)t);
|
||||
//8421 8421 8421 8421 8421 8421
|
||||
//abcd efgh ijkl mnop qrst uvwx
|
||||
//ijkl qrst opab cduv wxef ghmn
|
||||
@@ -47,10 +47,10 @@ string t, part;
|
||||
}
|
||||
|
||||
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
||||
if(type == CT_PRO_ACTION_REPLAY) {
|
||||
if(type == ProActionReplay) {
|
||||
sprintf(str, "%0.6x:%0.2x", addr, data);
|
||||
return true;
|
||||
} else if(type == CT_GAME_GENIE) {
|
||||
} else if(type == GameGenie) {
|
||||
uint32 r = addr;
|
||||
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
||||
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
||||
@@ -79,9 +79,9 @@ bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
||||
*****/
|
||||
|
||||
uint Cheat::mirror_address(uint addr) {
|
||||
if((addr & 0x40e000) != 0x0000)return addr;
|
||||
//8k WRAM mirror
|
||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||
if((addr & 0x40e000) != 0x0000) return addr;
|
||||
//8k WRAM mirror
|
||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||
return (0x7e0000 + (addr & 0x1fff));
|
||||
}
|
||||
|
||||
@@ -104,10 +104,10 @@ void Cheat::set(uint32 addr) {
|
||||
void Cheat::clear(uint32 addr) {
|
||||
addr = mirror_address(addr);
|
||||
|
||||
//is there more than one cheat code using the same address
|
||||
//(and likely a different override value) that is enabled?
|
||||
//if so, do not clear code lookup table entry for this address.
|
||||
uint8 r;
|
||||
//is there more than one cheat code using the same address
|
||||
//(and likely a different override value) that is enabled?
|
||||
//if so, do not clear code lookup table entry for this address.
|
||||
uint8 r;
|
||||
if(read(addr, r) == true)return;
|
||||
|
||||
mask[addr >> 3] &= ~(1 << (addr & 7));
|
||||
@@ -133,13 +133,13 @@ uint8 r;
|
||||
bool Cheat::read(uint32 addr, uint8 &data) {
|
||||
addr = mirror_address(addr);
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
if(enabled(i) == false)continue;
|
||||
if(enabled(i) == false) continue;
|
||||
if(addr == mirror_address(index[i].addr)) {
|
||||
data = index[i].data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//code not found, or code is disabled
|
||||
//code not found, or code is disabled
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -148,8 +148,9 @@ bool Cheat::read(uint32 addr, uint8 &data) {
|
||||
* enabled. if any are, make sure the cheat system is on.
|
||||
* otherwise, turn cheat system off to speed up emulation.
|
||||
*****/
|
||||
|
||||
void Cheat::update_cheat_status() {
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
for(unsigned i = 0; i < cheat_count; i++) {
|
||||
if(index[i].enabled) {
|
||||
cheat_enabled = true;
|
||||
return;
|
||||
@@ -163,11 +164,11 @@ void Cheat::update_cheat_status() {
|
||||
*****/
|
||||
|
||||
bool Cheat::add(bool enable, char *code, char *desc) {
|
||||
if(cheat_count >= CHEAT_LIMIT)return false;
|
||||
if(cheat_count >= CheatLimit) return false;
|
||||
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false)return false;
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false) return false;
|
||||
|
||||
index[cheat_count].enabled = enable;
|
||||
index[cheat_count].addr = addr;
|
||||
@@ -188,17 +189,17 @@ uint8 data, type;
|
||||
}
|
||||
|
||||
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
|
||||
if(n >= cheat_count)return false;
|
||||
if(n >= cheat_count) return false;
|
||||
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false)return false;
|
||||
uint32 addr, len;
|
||||
uint8 data, type;
|
||||
if(decode(code, addr, data, type) == false) return false;
|
||||
|
||||
//disable current code and clear from code lookup table
|
||||
//disable current code and clear from code lookup table
|
||||
index[n].enabled = false;
|
||||
clear(index[n].addr);
|
||||
|
||||
//update code and enable in code lookup table
|
||||
//update code and enable in code lookup table
|
||||
index[n].enabled = enable;
|
||||
index[n].addr = addr;
|
||||
index[n].data = data;
|
||||
@@ -217,9 +218,9 @@ uint8 data, type;
|
||||
}
|
||||
|
||||
bool Cheat::remove(uint32 n) {
|
||||
if(n >= cheat_count)return false;
|
||||
if(n >= cheat_count) return false;
|
||||
|
||||
for(int i = n; i < cheat_count; i++) {
|
||||
for(unsigned i = n; i < cheat_count; i++) {
|
||||
index[i].enabled = index[i + 1].enabled;
|
||||
index[i].addr = index[i + 1].addr;
|
||||
index[i].data = index[i + 1].data;
|
||||
@@ -233,7 +234,7 @@ bool Cheat::remove(uint32 n) {
|
||||
}
|
||||
|
||||
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
|
||||
if(n >= cheat_count)return false;
|
||||
if(n >= cheat_count) return false;
|
||||
enable = index[n].enabled;
|
||||
addr = index[n].addr;
|
||||
data = index[n].data;
|
||||
@@ -247,19 +248,19 @@ bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, c
|
||||
*****/
|
||||
|
||||
bool Cheat::enabled(uint32 n) {
|
||||
if(n >= cheat_count)return false;
|
||||
if(n >= cheat_count) return false;
|
||||
return index[n].enabled;
|
||||
}
|
||||
|
||||
void Cheat::enable(uint32 n) {
|
||||
if(n >= cheat_count)return;
|
||||
if(n >= cheat_count) return;
|
||||
index[n].enabled = true;
|
||||
set(index[n].addr);
|
||||
update_cheat_status();
|
||||
}
|
||||
|
||||
void Cheat::disable(uint32 n) {
|
||||
if(n >= cheat_count)return;
|
||||
if(n >= cheat_count) return;
|
||||
index[n].enabled = false;
|
||||
clear(index[n].addr);
|
||||
update_cheat_status();
|
||||
@@ -274,15 +275,15 @@ void Cheat::disable(uint32 n) {
|
||||
/* ... */
|
||||
|
||||
bool Cheat::load(const char *fn) {
|
||||
string data;
|
||||
string data;
|
||||
if(!fread(data, fn)) return false;
|
||||
replace(data, "\r\n", "\n");
|
||||
qreplace(data, "=", ",");
|
||||
qreplace(data, " ", "");
|
||||
|
||||
lstring line;
|
||||
lstring line;
|
||||
split(line, "\n", data);
|
||||
for(int i = 0; i < ::count(line); i++) {
|
||||
for(unsigned i = 0; i < ::count(line); i++) {
|
||||
lstring part;
|
||||
split(part, ",", line[i]);
|
||||
if(::count(part) != 3) continue;
|
||||
@@ -294,15 +295,15 @@ lstring line;
|
||||
}
|
||||
|
||||
bool Cheat::save(const char *fn) {
|
||||
FILE *fp = fopen(fn, "wb");
|
||||
if(!fp) return false;
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
||||
index[i].code,
|
||||
index[i].enabled ? "enabled" : "disabled",
|
||||
index[i].desc);
|
||||
file fp;
|
||||
if(!fp.open(fn, file::mode_write)) return false;
|
||||
for(unsigned i = 0; i < cheat_count; i++) {
|
||||
fp.print(string()
|
||||
<< index[i].code << " = "
|
||||
<< (index[i].enabled ? "enabled" : "disabled") << ", \""
|
||||
<< index[i].desc << "\"\r\n");
|
||||
}
|
||||
fclose(fp);
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -314,7 +315,7 @@ void Cheat::clear() {
|
||||
cheat_enabled = false;
|
||||
cheat_count = 0;
|
||||
memset(mask, 0, 0x200000);
|
||||
for(int i = 0; i <= CHEAT_LIMIT; i++) {
|
||||
for(unsigned i = 0; i <= CheatLimit; i++) {
|
||||
index[i].enabled = false;
|
||||
index[i].addr = 0x000000;
|
||||
index[i].data = 0x00;
|
||||
|
@@ -1,19 +1,23 @@
|
||||
#define CHEAT_LIMIT 1024
|
||||
|
||||
class Cheat {
|
||||
public:
|
||||
enum { CT_PRO_ACTION_REPLAY, CT_GAME_GENIE };
|
||||
enum { CheatLimit = 1024 };
|
||||
|
||||
struct CheatIndex {
|
||||
enum Type {
|
||||
ProActionReplay,
|
||||
GameGenie,
|
||||
};
|
||||
|
||||
struct CheatIndex {
|
||||
bool enabled;
|
||||
uint32 addr;
|
||||
uint8 data;
|
||||
char code[ 16 + 1];
|
||||
char desc[128 + 1];
|
||||
} index[CHEAT_LIMIT + 1];
|
||||
bool cheat_enabled;
|
||||
uint32 cheat_count;
|
||||
uint8 mask[0x200000];
|
||||
} index[CheatLimit + 1];
|
||||
|
||||
bool cheat_enabled;
|
||||
uint32 cheat_count;
|
||||
uint8 mask[0x200000];
|
||||
|
||||
inline bool enabled() { return cheat_enabled; }
|
||||
inline uint count() { return cheat_count; }
|
||||
@@ -22,27 +26,26 @@ uint8 mask[0x200000];
|
||||
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
|
||||
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
|
||||
|
||||
private:
|
||||
uint mirror_address(uint addr);
|
||||
void set(uint32 addr);
|
||||
void clear(uint32 addr);
|
||||
public:
|
||||
|
||||
bool read(uint32 addr, uint8 &data);
|
||||
|
||||
void update_cheat_status();
|
||||
bool add(bool enable, char *code, char *desc);
|
||||
bool edit(uint32 n, bool enable, char *code, char *desc);
|
||||
bool get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc);
|
||||
bool remove (uint32 n);
|
||||
bool remove(uint32 n);
|
||||
bool enabled(uint32 n);
|
||||
void enable (uint32 n);
|
||||
void enable(uint32 n);
|
||||
void disable(uint32 n);
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn);
|
||||
void clear();
|
||||
|
||||
Cheat();
|
||||
|
||||
private:
|
||||
uint mirror_address(uint addr);
|
||||
void set(uint32 addr);
|
||||
void clear(uint32 addr);
|
||||
};
|
||||
|
||||
extern Cheat cheat;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define BSX_CPP
|
||||
|
||||
#include "bsx_base.cpp"
|
||||
#include "bsx_cart.cpp"
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef BSX_CPP
|
||||
|
||||
void BSXBase::init() {
|
||||
}
|
||||
|
||||
@@ -131,3 +133,5 @@ void BSXBase::mmio_write(uint addr, uint8 data) {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef BSX_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef BSX_CPP
|
||||
|
||||
void BSXCart::init() {
|
||||
}
|
||||
|
||||
@@ -18,7 +20,7 @@ void BSXCart::reset() {
|
||||
}
|
||||
|
||||
void BSXCart::update_memory_map() {
|
||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||
|
||||
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
||||
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||
@@ -82,14 +84,16 @@ void BSXCart::mmio_write(uint addr, uint8 data) {
|
||||
}
|
||||
|
||||
BSXCart::BSXCart() {
|
||||
sram_data = (uint8*)malloc( 32 * 1024);
|
||||
psram_data = (uint8*)malloc(512 * 1024);
|
||||
sram_data = new uint8_t[ 32 * 1024];
|
||||
psram_data = new uint8_t[512 * 1024];
|
||||
|
||||
sram.map (sram_data, 32 * 1024);
|
||||
psram.map(psram_data, 512 * 1024);
|
||||
}
|
||||
|
||||
BSXCart::~BSXCart() {
|
||||
safe_free(sram_data);
|
||||
safe_free(psram_data);
|
||||
delete[] sram_data;
|
||||
delete[] psram_data;
|
||||
}
|
||||
|
||||
#endif //ifdef BSX_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef BSX_CPP
|
||||
|
||||
void BSXFlash::init() {}
|
||||
void BSXFlash::enable() {}
|
||||
|
||||
@@ -107,3 +109,5 @@ void BSXFlash::write(uint addr, uint8 data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef BSX_CPP
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include "bsx/bsx.h"
|
||||
#include "superfx/superfx.h"
|
||||
#include "srtc/srtc.h"
|
||||
#include "sdd1/sdd1.h"
|
||||
#include "spc7110/spc7110.h"
|
||||
#include "cx4/cx4.h"
|
||||
#include "dsp1/dsp1.h"
|
||||
#include "dsp2/dsp2.h"
|
||||
|
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "../../base.h"
|
||||
#define CX4_CPP
|
||||
|
||||
#include "cx4data.cpp"
|
||||
#include "cx4fn.cpp"
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
const uint8 Cx4::immediate_data[48] = {
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
|
||||
@@ -181,3 +183,5 @@ const int16 Cx4::CosTable[512] = {
|
||||
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
|
||||
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
|
||||
};
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
#include <math.h>
|
||||
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
|
||||
#define sar(b, n) ((b) >> (n))
|
||||
@@ -240,3 +242,5 @@ uint8 bit = 0x80;
|
||||
LineY += D;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
//Build OAM
|
||||
void Cx4::op00_00() {
|
||||
uint32 oamptr = ram[0x626] << 2;
|
||||
@@ -217,3 +219,5 @@ uint16 mask2 = 0x3f3f;
|
||||
destptr += 16;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CX4_CPP
|
||||
|
||||
//Sprite Functions
|
||||
void Cx4::op00() {
|
||||
switch(reg[0x4d]) {
|
||||
@@ -220,3 +222,5 @@ void Cx4::op89() {
|
||||
str(0, 0x054336);
|
||||
str(1, 0xffffff);
|
||||
}
|
||||
|
||||
#endif //ifdef CX4_CPP
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define DSP1_CPP
|
||||
|
||||
#include "dsp1emu.cpp"
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef DSP1_CPP
|
||||
|
||||
// DSP-1's emulation code
|
||||
//
|
||||
// Based on research by Overload, The Dumper, Neviksti and Andreas Naive
|
||||
@@ -1620,3 +1622,4 @@ const int16 Dsp1::SinTable[256] = {
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif //ifdef DSP1_CPP
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define DSP2_CPP
|
||||
|
||||
#include "dsp2_op.cpp"
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef DSP2_CPP
|
||||
|
||||
//convert bitmap to bitplane tile
|
||||
void DSP2::op01() {
|
||||
//op01 size is always 32 bytes input and output
|
||||
@@ -171,3 +173,5 @@ uint8 pixelarray[512];
|
||||
status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef DSP2_CPP
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define DSP3_CPP
|
||||
|
||||
namespace DSP3i {
|
||||
#define bool8 uint8
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef DSP3_CPP
|
||||
|
||||
//DSP-3 emulator code
|
||||
//Copyright (c) 2003-2006 John Weidman, Kris Bleakley, Lancer, z80 gaiden
|
||||
|
||||
@@ -1140,3 +1142,5 @@ void InitDSP3()
|
||||
{
|
||||
DSP3_Reset();
|
||||
}
|
||||
|
||||
#endif //ifdef DSP3_CPP
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define DSP4_CPP
|
||||
|
||||
namespace DSP4i {
|
||||
inline uint16 READ_WORD(uint8 *addr) {
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef DSP4_CPP
|
||||
|
||||
//DSP-4 emulator code
|
||||
//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden
|
||||
|
||||
@@ -2144,3 +2146,5 @@ void DSP4GetByte()
|
||||
dsp4_byte = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef DSP4_CPP
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define SDD1_CPP
|
||||
|
||||
#include "sdd1emu.cpp"
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef SDD1_CPP
|
||||
|
||||
/************************************************************************
|
||||
|
||||
S-DD1'algorithm emulation code
|
||||
@@ -445,3 +447,5 @@ SDD1emu::SDD1emu() :
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
#endif //ifdef SDD1_CPP
|
||||
|
511
src/chip/spc7110/decomp.cpp
Normal file
511
src/chip/spc7110/decomp.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
#ifdef SPC7110_CPP
|
||||
|
||||
uint8 SPC7110Decomp::read() {
|
||||
if(decomp_buffer_length == 0) {
|
||||
//decompress at least (decomp_buffer_size / 2) bytes to the buffer
|
||||
switch(decomp_mode) {
|
||||
case 0: mode0(false); break;
|
||||
case 1: mode1(false); break;
|
||||
case 2: mode2(false); break;
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 data = decomp_buffer[decomp_buffer_rdoffset++];
|
||||
decomp_buffer_rdoffset &= decomp_buffer_size - 1;
|
||||
decomp_buffer_length--;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SPC7110Decomp::write(uint8 data) {
|
||||
decomp_buffer[decomp_buffer_wroffset++] = data;
|
||||
decomp_buffer_wroffset &= decomp_buffer_size - 1;
|
||||
decomp_buffer_length++;
|
||||
}
|
||||
|
||||
uint8 SPC7110Decomp::dataread() {
|
||||
unsigned size = memory::cartrom.size() - 0x100000;
|
||||
while(decomp_offset >= size) decomp_offset -= size;
|
||||
return memory::cartrom.read(0x100000 + decomp_offset++);
|
||||
}
|
||||
|
||||
void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) {
|
||||
decomp_mode = mode;
|
||||
decomp_offset = offset;
|
||||
|
||||
decomp_buffer_rdoffset = 0;
|
||||
decomp_buffer_wroffset = 0;
|
||||
decomp_buffer_length = 0;
|
||||
|
||||
//reset context states
|
||||
for(unsigned i = 0; i < 32; i++) {
|
||||
context[i].index = 0;
|
||||
context[i].invert = 0;
|
||||
}
|
||||
|
||||
switch(decomp_mode) {
|
||||
case 0: mode0(true); break;
|
||||
case 1: mode1(true); break;
|
||||
case 2: mode2(true); break;
|
||||
}
|
||||
|
||||
//decompress up to requested output data index
|
||||
while(index--) read();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void SPC7110Decomp::mode0(bool init) {
|
||||
static uint8 val, in, span;
|
||||
static int out, inverts, lps, in_count;
|
||||
|
||||
if(init == true) {
|
||||
out = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = dataread();
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||
for(unsigned bit = 0; bit < 8; bit++) {
|
||||
//get context
|
||||
uint8 mask = (1 << (bit & 3)) - 1;
|
||||
uint8 con = mask + ((inverts & mask) ^ (lps & mask));
|
||||
if(bit > 3) con += 15;
|
||||
|
||||
//get prob and mps
|
||||
unsigned prob = probability(con);
|
||||
unsigned mps = (((out >> 15) & 1) ^ context[con].invert);
|
||||
|
||||
//get bit
|
||||
unsigned flag_lps;
|
||||
if(val <= span - prob) { //mps
|
||||
span = span - prob;
|
||||
out = (out << 1) + mps;
|
||||
flag_lps = 0;
|
||||
} else { //lps
|
||||
val = val - (span - (prob - 1));
|
||||
span = prob - 1;
|
||||
out = (out << 1) + 1 - mps;
|
||||
flag_lps = 1;
|
||||
}
|
||||
|
||||
//renormalize
|
||||
unsigned shift = 0;
|
||||
while(span < 0x7f) {
|
||||
shift++;
|
||||
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
|
||||
in <<= 1;
|
||||
if(--in_count == 0) {
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//update processing info
|
||||
lps = (lps << 1) + flag_lps;
|
||||
inverts = (inverts << 1) + context[con].invert;
|
||||
|
||||
//update context state
|
||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||
if(flag_lps) context[con].index = next_lps(con);
|
||||
else if(shift) context[con].index = next_mps(con);
|
||||
}
|
||||
|
||||
//save byte
|
||||
write(out);
|
||||
}
|
||||
}
|
||||
|
||||
void SPC7110Decomp::mode1(bool init) {
|
||||
static int pixelorder[4], realorder[4];
|
||||
static uint8 in, val, span;
|
||||
static int out, inverts, lps, in_count;
|
||||
|
||||
if(init == true) {
|
||||
for(unsigned i = 0; i < 4; i++) pixelorder[i] = i;
|
||||
out = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = dataread();
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||
//get first symbol context
|
||||
unsigned a = ((out >> (1 * 2)) & 3);
|
||||
unsigned b = ((out >> (7 * 2)) & 3);
|
||||
unsigned c = ((out >> (8 * 2)) & 3);
|
||||
unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||
|
||||
//update pixel order
|
||||
unsigned m, n;
|
||||
for(m = 0; m < 4; m++) if(pixelorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
||||
pixelorder[0] = a;
|
||||
|
||||
//calculate the real pixel order
|
||||
for(m = 0; m < 4; m++) realorder[m] = pixelorder[m];
|
||||
|
||||
//rotate reference pixel c value to top
|
||||
for(m = 0; m < 4; m++) if(realorder[m] == c) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = c;
|
||||
|
||||
//rotate reference pixel b value to top
|
||||
for(m = 0; m < 4; m++) if(realorder[m] == b) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = b;
|
||||
|
||||
//rotate reference pixel a value to top
|
||||
for(m = 0; m < 4; m++) if(realorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = a;
|
||||
|
||||
//get 2 symbols
|
||||
for(unsigned bit = 0; bit < 2; bit++) {
|
||||
//get prob
|
||||
unsigned prob = probability(con);
|
||||
|
||||
//get symbol
|
||||
unsigned flag_lps;
|
||||
if(val <= span - prob) { //mps
|
||||
span = span - prob;
|
||||
flag_lps = 0;
|
||||
} else { //lps
|
||||
val = val - (span - (prob - 1));
|
||||
span = prob - 1;
|
||||
flag_lps = 1;
|
||||
}
|
||||
|
||||
//renormalize
|
||||
unsigned shift = 0;
|
||||
while(span < 0x7f) {
|
||||
shift++;
|
||||
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
|
||||
in <<= 1;
|
||||
if(--in_count == 0) {
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//update processing info
|
||||
lps = (lps << 1) + flag_lps;
|
||||
inverts = (inverts << 1) + context[con].invert;
|
||||
|
||||
//update context state
|
||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||
if(flag_lps) context[con].index = next_lps(con);
|
||||
else if(shift) context[con].index = next_mps(con);
|
||||
|
||||
//get next context
|
||||
con = 5 + (con << 1) + ((lps ^ inverts) & 1);
|
||||
}
|
||||
|
||||
//get pixel
|
||||
b = realorder[(lps ^ inverts) & 3];
|
||||
out = (out << 2) + b;
|
||||
}
|
||||
|
||||
//turn pixel data into bitplanes
|
||||
unsigned data = morton_2x8(out);
|
||||
write(data >> 8);
|
||||
write(data >> 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SPC7110Decomp::mode2(bool init) {
|
||||
static int pixelorder[16], realorder[16];
|
||||
static uint8 bitplanebuffer[16], buffer_index;
|
||||
static uint8 in, val, span;
|
||||
static int out0, out1, inverts, lps, in_count;
|
||||
|
||||
if(init == true) {
|
||||
for(unsigned i = 0; i < 16; i++) pixelorder[i] = i;
|
||||
buffer_index = 0;
|
||||
out0 = out1 = inverts = lps = 0;
|
||||
span = 0xff;
|
||||
val = dataread();
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||
//get first symbol context
|
||||
unsigned a = ((out0 >> (0 * 4)) & 15);
|
||||
unsigned b = ((out0 >> (7 * 4)) & 15);
|
||||
unsigned c = ((out1 >> (0 * 4)) & 15);
|
||||
unsigned con = 0;
|
||||
unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||
|
||||
//update pixel order
|
||||
unsigned m, n;
|
||||
for(m = 0; m < 16; m++) if(pixelorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
||||
pixelorder[0] = a;
|
||||
|
||||
//calculate the real pixel order
|
||||
for(m = 0; m < 16; m++) realorder[m] = pixelorder[m];
|
||||
|
||||
//rotate reference pixel c value to top
|
||||
for(m = 0; m < 16; m++) if(realorder[m] == c) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = c;
|
||||
|
||||
//rotate reference pixel b value to top
|
||||
for(m = 0; m < 16; m++) if(realorder[m] == b) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = b;
|
||||
|
||||
//rotate reference pixel a value to top
|
||||
for(m = 0; m < 16; m++) if(realorder[m] == a) break;
|
||||
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||
realorder[0] = a;
|
||||
|
||||
//get 4 symbols
|
||||
for(unsigned bit = 0; bit < 4; bit++) {
|
||||
//get prob
|
||||
unsigned prob = probability(con);
|
||||
|
||||
//get symbol
|
||||
unsigned flag_lps;
|
||||
if(val <= span - prob) { //mps
|
||||
span = span - prob;
|
||||
flag_lps = 0;
|
||||
} else { //lps
|
||||
val = val - (span - (prob - 1));
|
||||
span = prob - 1;
|
||||
flag_lps = 1;
|
||||
}
|
||||
|
||||
//renormalize
|
||||
unsigned shift = 0;
|
||||
while(span < 0x7f) {
|
||||
shift++;
|
||||
|
||||
span = (span << 1) + 1;
|
||||
val = (val << 1) + (in >> 7);
|
||||
|
||||
in <<= 1;
|
||||
if(--in_count == 0) {
|
||||
in = dataread();
|
||||
in_count = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//update processing info
|
||||
lps = (lps << 1) + flag_lps;
|
||||
unsigned invertbit = context[con].invert;
|
||||
inverts = (inverts << 1) + invertbit;
|
||||
|
||||
//update context state
|
||||
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||
if(flag_lps) context[con].index = next_lps(con);
|
||||
else if(shift) context[con].index = next_mps(con);
|
||||
|
||||
//get next context
|
||||
con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
|
||||
}
|
||||
|
||||
//get pixel
|
||||
b = realorder[(lps ^ inverts) & 0x0f];
|
||||
out1 = (out1 << 4) + ((out0 >> 28) & 0x0f);
|
||||
out0 = (out0 << 4) + b;
|
||||
}
|
||||
|
||||
//convert pixel data into bitplanes
|
||||
unsigned data = morton_4x8(out0);
|
||||
write(data >> 24);
|
||||
write(data >> 16);
|
||||
bitplanebuffer[buffer_index++] = data >> 8;
|
||||
bitplanebuffer[buffer_index++] = data >> 0;
|
||||
|
||||
if(buffer_index == 16) {
|
||||
for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]);
|
||||
buffer_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const uint8 SPC7110Decomp::evolution_table[53][4] = {
|
||||
//{ prob, nextlps, nextmps, toggle invert },
|
||||
|
||||
{ 0x5a, 1, 1, 1 },
|
||||
{ 0x25, 6, 2, 0 },
|
||||
{ 0x11, 8, 3, 0 },
|
||||
{ 0x08, 10, 4, 0 },
|
||||
{ 0x03, 12, 5, 0 },
|
||||
{ 0x01, 15, 5, 0 },
|
||||
|
||||
{ 0x5a, 7, 7, 1 },
|
||||
{ 0x3f, 19, 8, 0 },
|
||||
{ 0x2c, 21, 9, 0 },
|
||||
{ 0x20, 22, 10, 0 },
|
||||
{ 0x17, 23, 11, 0 },
|
||||
{ 0x11, 25, 12, 0 },
|
||||
{ 0x0c, 26, 13, 0 },
|
||||
{ 0x09, 28, 14, 0 },
|
||||
{ 0x07, 29, 15, 0 },
|
||||
{ 0x05, 31, 16, 0 },
|
||||
{ 0x04, 32, 17, 0 },
|
||||
{ 0x03, 34, 18, 0 },
|
||||
{ 0x02, 35, 5, 0 },
|
||||
|
||||
{ 0x5a, 20, 20, 1 },
|
||||
{ 0x48, 39, 21, 0 },
|
||||
{ 0x3a, 40, 22, 0 },
|
||||
{ 0x2e, 42, 23, 0 },
|
||||
{ 0x26, 44, 24, 0 },
|
||||
{ 0x1f, 45, 25, 0 },
|
||||
{ 0x19, 46, 26, 0 },
|
||||
{ 0x15, 25, 27, 0 },
|
||||
{ 0x11, 26, 28, 0 },
|
||||
{ 0x0e, 26, 29, 0 },
|
||||
{ 0x0b, 27, 30, 0 },
|
||||
{ 0x09, 28, 31, 0 },
|
||||
{ 0x08, 29, 32, 0 },
|
||||
{ 0x07, 30, 33, 0 },
|
||||
{ 0x05, 31, 34, 0 },
|
||||
{ 0x04, 33, 35, 0 },
|
||||
{ 0x04, 33, 36, 0 },
|
||||
{ 0x03, 34, 37, 0 },
|
||||
{ 0x02, 35, 38, 0 },
|
||||
{ 0x02, 36, 5, 0 },
|
||||
|
||||
{ 0x58, 39, 40, 1 },
|
||||
{ 0x4d, 47, 41, 0 },
|
||||
{ 0x43, 48, 42, 0 },
|
||||
{ 0x3b, 49, 43, 0 },
|
||||
{ 0x34, 50, 44, 0 },
|
||||
{ 0x2e, 51, 45, 0 },
|
||||
{ 0x29, 44, 46, 0 },
|
||||
{ 0x25, 45, 24, 0 },
|
||||
|
||||
{ 0x56, 47, 48, 1 },
|
||||
{ 0x4f, 47, 49, 0 },
|
||||
{ 0x47, 48, 50, 0 },
|
||||
{ 0x41, 49, 51, 0 },
|
||||
{ 0x3c, 50, 52, 0 },
|
||||
{ 0x37, 51, 43, 0 },
|
||||
};
|
||||
|
||||
const uint8 SPC7110Decomp::mode2_context_table[32][2] = {
|
||||
//{ next 0, next 1 },
|
||||
|
||||
{ 1, 2 },
|
||||
|
||||
{ 3, 8 },
|
||||
{ 13, 14 },
|
||||
|
||||
{ 15, 16 },
|
||||
{ 17, 18 },
|
||||
{ 19, 20 },
|
||||
{ 21, 22 },
|
||||
{ 23, 24 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 25, 26 },
|
||||
{ 27, 28 },
|
||||
{ 29, 30 },
|
||||
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
{ 31, 31 },
|
||||
|
||||
{ 31, 31 },
|
||||
};
|
||||
|
||||
uint8 SPC7110Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; }
|
||||
uint8 SPC7110Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; }
|
||||
uint8 SPC7110Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; }
|
||||
bool SPC7110Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; }
|
||||
|
||||
unsigned SPC7110Decomp::morton_2x8(unsigned data) {
|
||||
//reverse morton lookup: de-interleave two 8-bit values
|
||||
//15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8
|
||||
//14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0
|
||||
return morton16[0][(data >> 0) & 255] + morton16[1][(data >> 8) & 255];
|
||||
}
|
||||
|
||||
unsigned SPC7110Decomp::morton_4x8(unsigned data) {
|
||||
//reverse morton lookup: de-interleave four 8-bit values
|
||||
//31, 27, 23, 19, 15, 11, 7, 3 -> 31-24
|
||||
//30, 26, 22, 18, 14, 10, 6, 2 -> 23-16
|
||||
//29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8
|
||||
//28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0
|
||||
return morton32[0][(data >> 0) & 255] + morton32[1][(data >> 8) & 255]
|
||||
+ morton32[2][(data >> 16) & 255] + morton32[3][(data >> 24) & 255];
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void SPC7110Decomp::reset() {
|
||||
//mode 3 is invalid; this is treated as a special case to always return 0x00
|
||||
//set to mode 3 so that reading decomp port before starting first decomp will return 0x00
|
||||
decomp_mode = 3;
|
||||
|
||||
decomp_buffer_rdoffset = 0;
|
||||
decomp_buffer_wroffset = 0;
|
||||
decomp_buffer_length = 0;
|
||||
}
|
||||
|
||||
SPC7110Decomp::SPC7110Decomp() {
|
||||
decomp_buffer = new uint8_t[decomp_buffer_size];
|
||||
reset();
|
||||
|
||||
//initialize reverse morton lookup tables
|
||||
for(unsigned i = 0; i < 256; i++) {
|
||||
#define map(x, y) (((i >> x) & 1) << y)
|
||||
//2x8-bit
|
||||
morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6)
|
||||
+ map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4);
|
||||
morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2)
|
||||
+ map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0);
|
||||
//4x8-bit
|
||||
morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7)
|
||||
+ map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6);
|
||||
morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5)
|
||||
+ map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4);
|
||||
morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3)
|
||||
+ map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2);
|
||||
morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1)
|
||||
+ map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0);
|
||||
#undef map
|
||||
}
|
||||
}
|
||||
|
||||
SPC7110Decomp::~SPC7110Decomp() {
|
||||
delete[] decomp_buffer;
|
||||
}
|
||||
|
||||
#endif
|
45
src/chip/spc7110/decomp.h
Normal file
45
src/chip/spc7110/decomp.h
Normal file
@@ -0,0 +1,45 @@
|
||||
class SPC7110Decomp {
|
||||
public:
|
||||
uint8 read();
|
||||
void init(unsigned mode, unsigned offset, unsigned index);
|
||||
void reset();
|
||||
|
||||
SPC7110Decomp();
|
||||
~SPC7110Decomp();
|
||||
|
||||
private:
|
||||
unsigned decomp_mode;
|
||||
unsigned decomp_offset;
|
||||
|
||||
//read() will spool chunks half the size of decomp_buffer_size
|
||||
enum { decomp_buffer_size = 64 }; //must be >= 64, and must be a power of two
|
||||
uint8 *decomp_buffer;
|
||||
unsigned decomp_buffer_rdoffset;
|
||||
unsigned decomp_buffer_wroffset;
|
||||
unsigned decomp_buffer_length;
|
||||
|
||||
void write(uint8 data);
|
||||
uint8 dataread();
|
||||
|
||||
void mode0(bool init);
|
||||
void mode1(bool init);
|
||||
void mode2(bool init);
|
||||
|
||||
static const uint8 evolution_table[53][4];
|
||||
static const uint8 mode2_context_table[32][2];
|
||||
|
||||
struct ContextState {
|
||||
uint8 index;
|
||||
uint8 invert;
|
||||
} context[32];
|
||||
|
||||
uint8 probability(unsigned n);
|
||||
uint8 next_lps(unsigned n);
|
||||
uint8 next_mps(unsigned n);
|
||||
bool toggle_invert(unsigned n);
|
||||
|
||||
unsigned morton16[2][256];
|
||||
unsigned morton32[4][256];
|
||||
unsigned morton_2x8(unsigned data);
|
||||
unsigned morton_4x8(unsigned data);
|
||||
};
|
658
src/chip/spc7110/spc7110.cpp
Normal file
658
src/chip/spc7110/spc7110.cpp
Normal file
@@ -0,0 +1,658 @@
|
||||
#include "../../base.h"
|
||||
#define SPC7110_CPP
|
||||
|
||||
#include "decomp.cpp"
|
||||
|
||||
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
void SPC7110::init() {}
|
||||
|
||||
void SPC7110::enable() {
|
||||
uint16_t limit = (cartridge.info.spc7110rtc ? 0x4842 : 0x483f);
|
||||
for(uint16_t i = 0x4800; i <= limit; i++) memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
void SPC7110::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SPC7110::reset() {
|
||||
r4801 = 0x00;
|
||||
r4802 = 0x00;
|
||||
r4803 = 0x00;
|
||||
r4804 = 0x00;
|
||||
r4805 = 0x00;
|
||||
r4806 = 0x00;
|
||||
r4807 = 0x00;
|
||||
r4808 = 0x00;
|
||||
r4809 = 0x00;
|
||||
r480a = 0x00;
|
||||
r480b = 0x00;
|
||||
r480c = 0x00;
|
||||
|
||||
decomp.reset();
|
||||
|
||||
r4811 = 0x00;
|
||||
r4812 = 0x00;
|
||||
r4813 = 0x00;
|
||||
r4814 = 0x00;
|
||||
r4815 = 0x00;
|
||||
r4816 = 0x00;
|
||||
r4817 = 0x00;
|
||||
r4818 = 0x00;
|
||||
|
||||
r481x = 0x00;
|
||||
r4814_latch = false;
|
||||
r4815_latch = false;
|
||||
|
||||
r4820 = 0x00;
|
||||
r4821 = 0x00;
|
||||
r4822 = 0x00;
|
||||
r4823 = 0x00;
|
||||
r4824 = 0x00;
|
||||
r4825 = 0x00;
|
||||
r4826 = 0x00;
|
||||
r4827 = 0x00;
|
||||
r4828 = 0x00;
|
||||
r4829 = 0x00;
|
||||
r482a = 0x00;
|
||||
r482b = 0x00;
|
||||
r482c = 0x00;
|
||||
r482d = 0x00;
|
||||
r482e = 0x00;
|
||||
r482f = 0x00;
|
||||
|
||||
r4830 = 0x00;
|
||||
mmio_write(0x4831, 0);
|
||||
mmio_write(0x4832, 1);
|
||||
mmio_write(0x4833, 2);
|
||||
r4834 = 0x00;
|
||||
|
||||
r4840 = 0x00;
|
||||
r4841 = 0x00;
|
||||
r4842 = 0x00;
|
||||
|
||||
if(cartridge.info.spc7110rtc) {
|
||||
rtc_state = RTCS_Inactive;
|
||||
rtc_mode = RTCM_Linear;
|
||||
rtc_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned SPC7110::datarom_addr(unsigned addr) {
|
||||
unsigned size = memory::cartrom.size() - 0x100000;
|
||||
while(addr >= size) addr -= size;
|
||||
return addr + 0x100000;
|
||||
}
|
||||
|
||||
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
|
||||
unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); }
|
||||
unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); }
|
||||
void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; }
|
||||
void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; }
|
||||
|
||||
void SPC7110::update_time(int offset) {
|
||||
time_t rtc_time;
|
||||
rtc_time = memory::cartrtc.read(16);
|
||||
rtc_time |= memory::cartrtc.read(17) << 8;
|
||||
rtc_time |= memory::cartrtc.read(18) << 16;
|
||||
rtc_time |= memory::cartrtc.read(19) << 24;
|
||||
|
||||
bool update = true;
|
||||
if(memory::cartrtc.read(13) & 1) update = false; //do not update if CR0 timer disable flag is set
|
||||
if(memory::cartrtc.read(15) & 3) update = false; //do not update if CR2 timer disable flags are set
|
||||
|
||||
time_t current_time = time(0) - offset;
|
||||
if(update && current_time > rtc_time) {
|
||||
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||
unsigned minute = memory::cartrtc.read( 2) + memory::cartrtc.read( 3) * 10;
|
||||
unsigned hour = memory::cartrtc.read( 4) + memory::cartrtc.read( 5) * 10;
|
||||
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||
unsigned month = memory::cartrtc.read( 8) + memory::cartrtc.read( 9) * 10;
|
||||
unsigned year = memory::cartrtc.read(10) + memory::cartrtc.read(11) * 10;
|
||||
unsigned weekday = memory::cartrtc.read(12);
|
||||
|
||||
day--;
|
||||
month--;
|
||||
year += (year >= 90) ? 1900 : 2000; //range = 1990-2089
|
||||
|
||||
second += (unsigned)(current_time - rtc_time);
|
||||
while(second >= 60) {
|
||||
second -= 60;
|
||||
|
||||
minute++;
|
||||
if(minute < 60) continue;
|
||||
minute = 0;
|
||||
|
||||
hour++;
|
||||
if(hour < 24) continue;
|
||||
hour = 0;
|
||||
|
||||
day++;
|
||||
weekday = (weekday + 1) % 7;
|
||||
unsigned days = months[month % 12];
|
||||
if(days == 28) {
|
||||
bool leapyear = false;
|
||||
if((year % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((year % 100) == 0 && (year % 400) != 0) leapyear = false;
|
||||
}
|
||||
if(leapyear) days++;
|
||||
}
|
||||
if(day < days) continue;
|
||||
day = 0;
|
||||
|
||||
month++;
|
||||
if(month < 12) continue;
|
||||
month = 0;
|
||||
|
||||
year++;
|
||||
}
|
||||
|
||||
day++;
|
||||
month++;
|
||||
year %= 100;
|
||||
|
||||
memory::cartrtc.write( 0, second % 10);
|
||||
memory::cartrtc.write( 1, second / 10);
|
||||
memory::cartrtc.write( 2, minute % 10);
|
||||
memory::cartrtc.write( 3, minute / 10);
|
||||
memory::cartrtc.write( 4, hour % 10);
|
||||
memory::cartrtc.write( 5, hour / 10);
|
||||
memory::cartrtc.write( 6, day % 10);
|
||||
memory::cartrtc.write( 7, day / 10);
|
||||
memory::cartrtc.write( 8, month % 10);
|
||||
memory::cartrtc.write( 9, month / 10);
|
||||
memory::cartrtc.write(10, year % 10);
|
||||
memory::cartrtc.write(11, (year / 10) % 10);
|
||||
memory::cartrtc.write(12, weekday % 7);
|
||||
}
|
||||
|
||||
memory::cartrtc.write(16, current_time);
|
||||
memory::cartrtc.write(17, current_time >> 8);
|
||||
memory::cartrtc.write(18, current_time >> 16);
|
||||
memory::cartrtc.write(19, current_time >> 24);
|
||||
}
|
||||
|
||||
uint8 SPC7110::mmio_read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
|
||||
case 0x4800: {
|
||||
uint16 counter = (r4809 + (r480a << 8));
|
||||
counter--;
|
||||
r4809 = counter;
|
||||
r480a = counter >> 8;
|
||||
return decomp.read();
|
||||
}
|
||||
case 0x4801: return r4801;
|
||||
case 0x4802: return r4802;
|
||||
case 0x4803: return r4803;
|
||||
case 0x4804: return r4804;
|
||||
case 0x4805: return r4805;
|
||||
case 0x4806: return r4806;
|
||||
case 0x4807: return r4807;
|
||||
case 0x4808: return r4808;
|
||||
case 0x4809: return r4809;
|
||||
case 0x480a: return r480a;
|
||||
case 0x480b: return r480b;
|
||||
case 0x480c: {
|
||||
uint8 status = r480c;
|
||||
r480c &= 0x7f;
|
||||
return status;
|
||||
}
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
|
||||
case 0x4810: {
|
||||
if(r481x != 0x07) return 0x00;
|
||||
|
||||
unsigned addr = data_pointer();
|
||||
unsigned adjust = data_adjust();
|
||||
if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend
|
||||
|
||||
unsigned adjustaddr = addr;
|
||||
if(r4818 & 2) {
|
||||
adjustaddr += adjust;
|
||||
set_data_adjust(adjust + 1);
|
||||
}
|
||||
|
||||
uint8 data = memory::cartrom.read(datarom_addr(adjustaddr));
|
||||
if(!(r4818 & 2)) {
|
||||
unsigned increment = (r4818 & 1) ? data_increment() : 1;
|
||||
if(r4818 & 4) increment = (int16)increment; //16-bit sign extend
|
||||
|
||||
if((r4818 & 16) == 0) {
|
||||
set_data_pointer(addr + increment);
|
||||
} else {
|
||||
set_data_adjust(adjust + increment);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
case 0x4811: return r4811;
|
||||
case 0x4812: return r4812;
|
||||
case 0x4813: return r4813;
|
||||
case 0x4814: return r4814;
|
||||
case 0x4815: return r4815;
|
||||
case 0x4816: return r4816;
|
||||
case 0x4817: return r4817;
|
||||
case 0x4818: return r4818;
|
||||
case 0x481a: {
|
||||
if(r481x != 0x07) return 0x00;
|
||||
|
||||
unsigned addr = data_pointer();
|
||||
unsigned adjust = data_adjust();
|
||||
if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend
|
||||
|
||||
uint8 data = memory::cartrom.read(datarom_addr(addr + adjust));
|
||||
if((r4818 & 0x60) == 0x60) {
|
||||
if((r4818 & 16) == 0) {
|
||||
set_data_pointer(addr + adjust);
|
||||
} else {
|
||||
set_data_adjust(adjust + adjust);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
|
||||
case 0x4820: return r4820;
|
||||
case 0x4821: return r4821;
|
||||
case 0x4822: return r4822;
|
||||
case 0x4823: return r4823;
|
||||
case 0x4824: return r4824;
|
||||
case 0x4825: return r4825;
|
||||
case 0x4826: return r4826;
|
||||
case 0x4827: return r4827;
|
||||
case 0x4828: return r4828;
|
||||
case 0x4829: return r4829;
|
||||
case 0x482a: return r482a;
|
||||
case 0x482b: return r482b;
|
||||
case 0x482c: return r482c;
|
||||
case 0x482d: return r482d;
|
||||
case 0x482e: return r482e;
|
||||
case 0x482f: {
|
||||
uint8 status = r482f;
|
||||
r482f &= 0x7f;
|
||||
return status;
|
||||
}
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
|
||||
case 0x4830: return r4830;
|
||||
case 0x4831: return r4831;
|
||||
case 0x4832: return r4832;
|
||||
case 0x4833: return r4833;
|
||||
case 0x4834: return r4834;
|
||||
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
|
||||
case 0x4840: return r4840;
|
||||
case 0x4841: {
|
||||
if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00;
|
||||
|
||||
r4842 = 0x80;
|
||||
uint8 data = memory::cartrtc.read(rtc_index);
|
||||
rtc_index = (rtc_index + 1) & 15;
|
||||
return data;
|
||||
}
|
||||
case 0x4842: {
|
||||
uint8 status = r4842;
|
||||
r4842 &= 0x7f;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void SPC7110::mmio_write(uint addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
|
||||
case 0x4801: r4801 = data; break;
|
||||
case 0x4802: r4802 = data; break;
|
||||
case 0x4803: r4803 = data; break;
|
||||
case 0x4804: r4804 = data; break;
|
||||
case 0x4805: r4805 = data; break;
|
||||
case 0x4806: {
|
||||
r4806 = data;
|
||||
|
||||
unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16));
|
||||
unsigned index = (r4804 << 2);
|
||||
unsigned length = (r4809 + (r480a << 8));
|
||||
unsigned addr = datarom_addr(table + index);
|
||||
unsigned mode = (memory::cartrom.read(addr + 0));
|
||||
unsigned offset = (memory::cartrom.read(addr + 1) << 16)
|
||||
+ (memory::cartrom.read(addr + 2) << 8)
|
||||
+ (memory::cartrom.read(addr + 3) << 0);
|
||||
|
||||
decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode);
|
||||
r480c = 0x80;
|
||||
} break;
|
||||
|
||||
case 0x4807: r4807 = data; break;
|
||||
case 0x4808: r4808 = data; break;
|
||||
case 0x4809: r4809 = data; break;
|
||||
case 0x480a: r480a = data; break;
|
||||
case 0x480b: r480b = data; break;
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
|
||||
case 0x4811: r4811 = data; r481x |= 0x01; break;
|
||||
case 0x4812: r4812 = data; r481x |= 0x02; break;
|
||||
case 0x4813: r4813 = data; r481x |= 0x04; break;
|
||||
case 0x4814: {
|
||||
r4814 = data;
|
||||
r4814_latch = true;
|
||||
if(!r4815_latch) break;
|
||||
if(!(r4818 & 2)) break;
|
||||
if(r4818 & 0x10) break;
|
||||
|
||||
if((r4818 & 0x60) == 0x20) {
|
||||
unsigned increment = data_adjust() & 0xff;
|
||||
if(r4818 & 8) increment = (int8)increment; //8-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
} else if((r4818 & 0x60) == 0x40) {
|
||||
unsigned increment = data_adjust();
|
||||
if(r4818 & 8) increment = (int16)increment; //16-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
}
|
||||
} break;
|
||||
case 0x4815: {
|
||||
r4815 = data;
|
||||
r4815_latch = true;
|
||||
if(!r4814_latch) break;
|
||||
if(!(r4818 & 2)) break;
|
||||
if(r4818 & 0x10) break;
|
||||
|
||||
if((r4818 & 0x60) == 0x20) {
|
||||
unsigned increment = data_adjust() & 0xff;
|
||||
if(r4818 & 8) increment = (int8)increment; //8-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
} else if((r4818 & 0x60) == 0x40) {
|
||||
unsigned increment = data_adjust();
|
||||
if(r4818 & 8) increment = (int16)increment; //16-bit sign extend
|
||||
set_data_pointer(data_pointer() + increment);
|
||||
}
|
||||
} break;
|
||||
case 0x4816: r4816 = data; break;
|
||||
case 0x4817: r4817 = data; break;
|
||||
case 0x4818: {
|
||||
if(r481x != 0x07) break;
|
||||
|
||||
r4818 = data;
|
||||
r4814_latch = r4815_latch = false;
|
||||
} break;
|
||||
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
|
||||
case 0x4820: r4820 = data; break;
|
||||
case 0x4821: r4821 = data; break;
|
||||
case 0x4822: r4822 = data; break;
|
||||
case 0x4823: r4823 = data; break;
|
||||
case 0x4824: r4824 = data; break;
|
||||
case 0x4825: {
|
||||
r4825 = data;
|
||||
|
||||
if(r482e & 1) {
|
||||
//signed 16-bit x 16-bit multiplication
|
||||
int16 r0 = (int16)(r4824 + (r4825 << 8));
|
||||
int16 r1 = (int16)(r4820 + (r4821 << 8));
|
||||
|
||||
signed result = r0 * r1;
|
||||
r4828 = result;
|
||||
r4829 = result >> 8;
|
||||
r482a = result >> 16;
|
||||
r482b = result >> 24;
|
||||
} else {
|
||||
//unsigned 16-bit x 16-bit multiplication
|
||||
uint16 r0 = (uint16)(r4824 + (r4825 << 8));
|
||||
uint16 r1 = (uint16)(r4820 + (r4821 << 8));
|
||||
|
||||
unsigned result = r0 * r1;
|
||||
r4828 = result;
|
||||
r4829 = result >> 8;
|
||||
r482a = result >> 16;
|
||||
r482b = result >> 24;
|
||||
}
|
||||
|
||||
r482f = 0x80;
|
||||
} break;
|
||||
case 0x4826: r4826 = data; break;
|
||||
case 0x4827: {
|
||||
r4827 = data;
|
||||
|
||||
if(r482e & 1) {
|
||||
//signed 32-bit x 16-bit division
|
||||
int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24));
|
||||
int16 divisor = (int16)(r4826 + (r4827 << 8));
|
||||
|
||||
int32 quotient;
|
||||
int16 remainder;
|
||||
|
||||
if(divisor) {
|
||||
quotient = (int32)(dividend / divisor);
|
||||
remainder = (int32)(dividend % divisor);
|
||||
} else {
|
||||
//illegal division by zero
|
||||
quotient = 0;
|
||||
remainder = dividend & 0xffff;
|
||||
}
|
||||
|
||||
r4828 = quotient;
|
||||
r4829 = quotient >> 8;
|
||||
r482a = quotient >> 16;
|
||||
r482b = quotient >> 24;
|
||||
|
||||
r482c = remainder;
|
||||
r482d = remainder >> 8;
|
||||
} else {
|
||||
//unsigned 32-bit x 16-bit division
|
||||
uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24));
|
||||
uint16 divisor = (uint16)(r4826 + (r4827 << 8));
|
||||
|
||||
uint32 quotient;
|
||||
uint16 remainder;
|
||||
|
||||
if(divisor) {
|
||||
quotient = (uint32)(dividend / divisor);
|
||||
remainder = (uint16)(dividend % divisor);
|
||||
} else {
|
||||
//illegal division by zero
|
||||
quotient = 0;
|
||||
remainder = dividend & 0xffff;
|
||||
}
|
||||
|
||||
r4828 = quotient;
|
||||
r4829 = quotient >> 8;
|
||||
r482a = quotient >> 16;
|
||||
r482b = quotient >> 24;
|
||||
|
||||
r482c = remainder;
|
||||
r482d = remainder >> 8;
|
||||
}
|
||||
|
||||
r482f = 0x80;
|
||||
} break;
|
||||
|
||||
case 0x482e: {
|
||||
//reset math unit
|
||||
r4820 = r4821 = r4822 = r4823 = 0;
|
||||
r4824 = r4825 = r4826 = r4827 = 0;
|
||||
r4828 = r4829 = r482a = r482b = 0;
|
||||
r482c = r482d = 0;
|
||||
|
||||
r482e = data;
|
||||
} break;
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
|
||||
case 0x4830: r4830 = data; break;
|
||||
|
||||
case 0x4831: {
|
||||
r4831 = data;
|
||||
dx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4832: {
|
||||
r4832 = data;
|
||||
ex_offset = datarom_addr((data & 7) * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4833: {
|
||||
r4833 = data;
|
||||
fx_offset = datarom_addr((data & 7) * 0x100000);
|
||||
} break;
|
||||
|
||||
case 0x4834: r4834 = data; break;
|
||||
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
|
||||
case 0x4840: {
|
||||
r4840 = data;
|
||||
if(!(r4840 & 1)) {
|
||||
//disable RTC
|
||||
rtc_state = RTCS_Inactive;
|
||||
update_time();
|
||||
} else {
|
||||
//enable RTC
|
||||
r4842 = 0x80;
|
||||
rtc_state = RTCS_ModeSelect;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x4841: {
|
||||
r4841 = data;
|
||||
|
||||
switch(rtc_state) {
|
||||
case RTCS_ModeSelect: {
|
||||
if(data == RTCM_Linear || data == RTCM_Indexed) {
|
||||
r4842 = 0x80;
|
||||
rtc_state = RTCS_IndexSelect;
|
||||
rtc_mode = (RTC_Mode)data;
|
||||
rtc_index = 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
case RTCS_IndexSelect: {
|
||||
r4842 = 0x80;
|
||||
rtc_index = data & 15;
|
||||
if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write;
|
||||
} break;
|
||||
|
||||
case RTCS_Write: {
|
||||
r4842 = 0x80;
|
||||
|
||||
//control register 0
|
||||
if(rtc_index == 13) {
|
||||
//increment second counter
|
||||
if(data & 2) update_time(+1);
|
||||
|
||||
//round minute counter
|
||||
if(data & 8) {
|
||||
update_time();
|
||||
|
||||
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||
//clear seconds
|
||||
memory::cartrtc.write(0, 0);
|
||||
memory::cartrtc.write(1, 0);
|
||||
|
||||
if(second >= 30) update_time(+60);
|
||||
}
|
||||
}
|
||||
|
||||
//control register 2
|
||||
if(rtc_index == 15) {
|
||||
//disable timer and clear second counter
|
||||
if((data & 1) && !(memory::cartrtc.read(15) & 1)) {
|
||||
update_time();
|
||||
|
||||
//clear seconds
|
||||
memory::cartrtc.write(0, 0);
|
||||
memory::cartrtc.write(1, 0);
|
||||
}
|
||||
|
||||
//disable timer
|
||||
if((data & 2) && !(memory::cartrtc.read(15) & 2)) {
|
||||
update_time();
|
||||
}
|
||||
}
|
||||
|
||||
memory::cartrtc.write(rtc_index, data & 15);
|
||||
rtc_index = (rtc_index + 1) & 15;
|
||||
} break;
|
||||
} //switch(rtc_state)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 SPC7110::read(uint addr) {
|
||||
//$[00-0f|80-8f]:[8000-ffff], $[c0-cf]:[0000-ffff] mapped directly to memory::cartrom
|
||||
|
||||
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
|
||||
//$[00|30]:[6000-7fff]
|
||||
return memory::cartram.read(addr & 0x1fff);
|
||||
}
|
||||
|
||||
if((addr & 0xff0000) == 0x500000) {
|
||||
//$[50]:[0000-ffff]
|
||||
return mmio_read(0x4800);
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xd00000) {
|
||||
//$[d0-df]:[0000-ffff]
|
||||
return memory::cartrom.read(dx_offset + (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xe00000) {
|
||||
//$[e0-ef]:[0000-ffff]
|
||||
return memory::cartrom.read(ex_offset + (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
if((addr & 0xf00000) == 0xf00000) {
|
||||
//$[f0-ff]:[0000-ffff]
|
||||
return memory::cartrom.read(fx_offset + (addr & 0x0fffff));
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
void SPC7110::write(uint addr, uint8 data) {
|
||||
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
|
||||
//$[00|30]:[6000-7fff]
|
||||
if(r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SPC7110::SPC7110() {
|
||||
}
|
133
src/chip/spc7110/spc7110.h
Normal file
133
src/chip/spc7110/spc7110.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*****
|
||||
* SPC7110 emulator - version 0.03 (2008-08-10)
|
||||
* Copyright (c) 2008, byuu and neviksti
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* The software is provided "as is" and the author disclaims all warranties
|
||||
* with regard to this software including all implied warranties of
|
||||
* merchantibility and fitness, in no event shall the author be liable for
|
||||
* any special, direct, indirect, or consequential damages or any damages
|
||||
* whatsoever resulting from loss of use, data or profits, whether in an
|
||||
* action of contract, negligence or other tortious action, arising out of
|
||||
* or in connection with the use or performance of this software.
|
||||
*****/
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
class SPC7110 : public MMIO, public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
unsigned datarom_addr(unsigned addr);
|
||||
|
||||
unsigned data_pointer();
|
||||
unsigned data_adjust();
|
||||
unsigned data_increment();
|
||||
void set_data_pointer(unsigned addr);
|
||||
void set_data_adjust(unsigned addr);
|
||||
|
||||
void update_time(int offset = 0);
|
||||
time_t create_time();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
uint8 read (uint addr);
|
||||
void write(uint addr, uint8 data);
|
||||
|
||||
//spc7110decomp
|
||||
void decomp_init();
|
||||
uint8 decomp_read();
|
||||
|
||||
SPC7110();
|
||||
|
||||
private:
|
||||
//==================
|
||||
//decompression unit
|
||||
//==================
|
||||
uint8 r4801; //compression table low
|
||||
uint8 r4802; //compression table high
|
||||
uint8 r4803; //compression table bank
|
||||
uint8 r4804; //compression table index
|
||||
uint8 r4805; //decompression buffer index low
|
||||
uint8 r4806; //decompression buffer index high
|
||||
uint8 r4807; //???
|
||||
uint8 r4808; //???
|
||||
uint8 r4809; //compression length low
|
||||
uint8 r480a; //compression length high
|
||||
uint8 r480b; //decompression control register
|
||||
uint8 r480c; //decompression status
|
||||
|
||||
SPC7110Decomp decomp;
|
||||
|
||||
//==============
|
||||
//data port unit
|
||||
//==============
|
||||
uint8 r4811; //data pointer low
|
||||
uint8 r4812; //data pointer high
|
||||
uint8 r4813; //data pointer bank
|
||||
uint8 r4814; //data adjust low
|
||||
uint8 r4815; //data adjust high
|
||||
uint8 r4816; //data increment low
|
||||
uint8 r4817; //data increment high
|
||||
uint8 r4818; //data port control register
|
||||
|
||||
uint8 r481x;
|
||||
|
||||
bool r4814_latch;
|
||||
bool r4815_latch;
|
||||
|
||||
//=========
|
||||
//math unit
|
||||
//=========
|
||||
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||
uint8 r4822; //32-bit dividend B2
|
||||
uint8 r4823; //32-bit dividend B3
|
||||
uint8 r4824; //16-bit multiplier B0
|
||||
uint8 r4825; //16-bit multiplier B1
|
||||
uint8 r4826; //16-bit divisor B0
|
||||
uint8 r4827; //16-bit divisor B1
|
||||
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||
uint8 r482c; //16-bit remainder B0
|
||||
uint8 r482d; //16-bit remainder B1
|
||||
uint8 r482e; //math control register
|
||||
uint8 r482f; //math status
|
||||
|
||||
//===================
|
||||
//memory mapping unit
|
||||
//===================
|
||||
uint8 r4830; //SRAM write enable
|
||||
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||
uint8 r4834; //???
|
||||
|
||||
unsigned dx_offset;
|
||||
unsigned ex_offset;
|
||||
unsigned fx_offset;
|
||||
|
||||
//====================
|
||||
//real-time clock unit
|
||||
//====================
|
||||
uint8 r4840; //RTC latch
|
||||
uint8 r4841; //RTC index/data port
|
||||
uint8 r4842; //RTC status
|
||||
|
||||
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state;
|
||||
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode;
|
||||
unsigned rtc_index;
|
||||
|
||||
static const unsigned months[12];
|
||||
};
|
||||
|
||||
extern SPC7110 spc7110;
|
@@ -1,189 +1,213 @@
|
||||
/*
|
||||
S-RTC chip emulation
|
||||
Used by Hudson Soft in Dai Kaijuu Monogatari II and Far East of Eden Zero.
|
||||
Currently, only the former is supported by bsnes.
|
||||
|
||||
Original S-RTC emulation code via John Weidman/SNES9x
|
||||
Rewritten for compatibility with bsnes via byuu
|
||||
|
||||
The S-RTC is a real-time clock chip that was added to the above two carts
|
||||
to allow the games to maintain the current time, even when the game was not
|
||||
powered on. Thus allowing special events at certain times, and on certain
|
||||
dates. Hudson Soft called this the PLG (Player's Life Gameplay System).
|
||||
|
||||
This chip is a special case to the term 'emulation' itself.
|
||||
There are a few different ways to go about emulating this chip, and each
|
||||
result in a different style of emulation.
|
||||
|
||||
The first is to simply return the current PC system time when the S-RTC is
|
||||
read from. This emulates the original S-RTC in the sense that it always
|
||||
returns the true current time, ignoring the speed that the SNES itself is
|
||||
running at. The downside to this method is that you lose the ability to set
|
||||
the time to whatever you choose inside the game itself. It will always return
|
||||
the true time, regardless. This can be overcome by changing the PC system time,
|
||||
which actually adds a greater degree of control over event timing, very useful
|
||||
for emulation. It also has a timeshifting flaw discussed below.
|
||||
|
||||
The second is to run the S-RTC relative to the SNES speed. This means that
|
||||
if the emulator is sped up (via fast forward key, frameskipping, etc), or
|
||||
slowed down (via slowdown key, system bottlenecking, etc); the time increments
|
||||
slower, thus ~60 frames on the SNES equal one second. Without this, timeshifting
|
||||
will occur between the S-RTC and the real SNES.
|
||||
|
||||
The third and final method is to save a copy of the local system time when the
|
||||
S-RTC is initially set, and compare the current system time against this value
|
||||
when setting the S-RTC time. This overcomes the first methods' shortcoming of
|
||||
not allowing the player to set the time in-game, however a new problem arises.
|
||||
You now have to save the time when the RTC was initially set to both savestates
|
||||
and to save-game data. This would require an extra file, or the breaking of
|
||||
perhaps the only standard format (.srm savegame backups) in the entire SNES
|
||||
emulation scene. You also give up the control of being able to override the
|
||||
RTC clock at will via the PC system time outside of emulation.
|
||||
The first method has another advantage over the third: Dai Kaijuu Monogatari II
|
||||
only allows dates in the range of the years 1996-2199. The first method gets
|
||||
around this limitation. But who knows, maybe it will break something in the
|
||||
game if the date exceeds 2199... I guess we'll worry about that in two hundred
|
||||
years from now.
|
||||
|
||||
For my implementation, I chose to go with the first method. Both for simplicity
|
||||
and because I did not wish to create a new method for saving the system time
|
||||
whenever the RTC is set.
|
||||
*/
|
||||
|
||||
#include "../../base.h"
|
||||
|
||||
void SRTC::set_time() {
|
||||
time_t rawtime;
|
||||
tm *t;
|
||||
::time(&rawtime);
|
||||
t = localtime(&rawtime);
|
||||
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
//see srtc.h for format of srtc.data[]
|
||||
srtc.data[0] = t->tm_sec % 10;
|
||||
srtc.data[1] = t->tm_sec / 10;
|
||||
srtc.data[2] = t->tm_min % 10;
|
||||
srtc.data[3] = t->tm_min / 10;
|
||||
srtc.data[4] = t->tm_hour % 10;
|
||||
srtc.data[5] = t->tm_hour / 10;
|
||||
srtc.data[6] = t->tm_mday % 10;
|
||||
srtc.data[7] = t->tm_mday / 10;
|
||||
srtc.data[8] = t->tm_mon + 1;
|
||||
srtc.data[9] = t->tm_year % 10;
|
||||
srtc.data[10] = (t->tm_year / 10) % 10;
|
||||
srtc.data[11] = 9 + (t->tm_year / 100);
|
||||
srtc.data[12] = t->tm_wday;
|
||||
void SRTC::init() {
|
||||
}
|
||||
|
||||
void SRTC::init() {}
|
||||
|
||||
void SRTC::enable() {
|
||||
memory::mmio.map(0x2800, *this);
|
||||
memory::mmio.map(0x2801, *this);
|
||||
}
|
||||
|
||||
void SRTC::power() {
|
||||
memset(&srtc, 0, sizeof(srtc));
|
||||
reset();
|
||||
}
|
||||
|
||||
void SRTC::reset() {
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READ;
|
||||
rtc_mode = RTCM_Read;
|
||||
rtc_index = -1;
|
||||
update_time();
|
||||
}
|
||||
|
||||
void SRTC::update_time() {
|
||||
time_t rtc_time;
|
||||
rtc_time = memory::cartrtc.read(16);
|
||||
rtc_time |= memory::cartrtc.read(17) << 8;
|
||||
rtc_time |= memory::cartrtc.read(18) << 16;
|
||||
rtc_time |= memory::cartrtc.read(19) << 24;
|
||||
|
||||
time_t current_time = time(0);
|
||||
if(current_time > rtc_time) {
|
||||
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||
unsigned minute = memory::cartrtc.read( 2) + memory::cartrtc.read( 3) * 10;
|
||||
unsigned hour = memory::cartrtc.read( 4) + memory::cartrtc.read( 5) * 10;
|
||||
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||
unsigned month = memory::cartrtc.read( 8);
|
||||
unsigned year = memory::cartrtc.read( 9) + memory::cartrtc.read(10) * 10 + memory::cartrtc.read(11) * 100;
|
||||
unsigned weekday = memory::cartrtc.read(12);
|
||||
|
||||
day--;
|
||||
month--;
|
||||
year += 1000;
|
||||
|
||||
second += (unsigned)(current_time - rtc_time);
|
||||
|
||||
while(second >= 60) {
|
||||
second -= 60;
|
||||
|
||||
minute++;
|
||||
if(minute < 60) continue;
|
||||
minute = 0;
|
||||
|
||||
hour++;
|
||||
if(hour < 24) continue;
|
||||
hour = 0;
|
||||
|
||||
day++;
|
||||
weekday = (weekday + 1) % 7;
|
||||
unsigned days = months[month % 12];
|
||||
if(days == 28) {
|
||||
bool leapyear = false;
|
||||
if((year % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((year % 100) == 0 && (year % 400) != 0) leapyear = false;
|
||||
}
|
||||
if(leapyear) days++;
|
||||
}
|
||||
if(day < days) continue;
|
||||
day = 0;
|
||||
|
||||
month++;
|
||||
if(month < 12) continue;
|
||||
month = 0;
|
||||
|
||||
year++;
|
||||
}
|
||||
|
||||
day++;
|
||||
month++;
|
||||
year -= 1000;
|
||||
|
||||
memory::cartrtc.write( 0, second % 10);
|
||||
memory::cartrtc.write( 1, second / 10);
|
||||
memory::cartrtc.write( 2, minute % 10);
|
||||
memory::cartrtc.write( 3, minute / 10);
|
||||
memory::cartrtc.write( 4, hour % 10);
|
||||
memory::cartrtc.write( 5, hour / 10);
|
||||
memory::cartrtc.write( 6, day % 10);
|
||||
memory::cartrtc.write( 7, day / 10);
|
||||
memory::cartrtc.write( 8, month);
|
||||
memory::cartrtc.write( 9, year % 10);
|
||||
memory::cartrtc.write(10, (year / 10) % 10);
|
||||
memory::cartrtc.write(11, year / 100);
|
||||
memory::cartrtc.write(12, weekday % 7);
|
||||
}
|
||||
|
||||
memory::cartrtc.write(16, current_time);
|
||||
memory::cartrtc.write(17, current_time >> 8);
|
||||
memory::cartrtc.write(18, current_time >> 16);
|
||||
memory::cartrtc.write(19, current_time >> 24);
|
||||
}
|
||||
|
||||
//returns day of week for specified date
|
||||
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
||||
//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008
|
||||
unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
|
||||
unsigned y = 1900, m = 1; //epoch is 1900-01-01
|
||||
unsigned sum = 0; //number of days passed since epoch
|
||||
|
||||
year = max(1900, year);
|
||||
month = max(1, min(12, month));
|
||||
day = max(1, min(31, day));
|
||||
|
||||
while(y < year) {
|
||||
bool leapyear = false;
|
||||
if((y % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
|
||||
}
|
||||
sum += leapyear ? 366 : 365;
|
||||
y++;
|
||||
}
|
||||
|
||||
while(m < month) {
|
||||
unsigned days = months[m - 1];
|
||||
if(days == 28) {
|
||||
bool leapyear = false;
|
||||
if((y % 4) == 0) {
|
||||
leapyear = true;
|
||||
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
|
||||
}
|
||||
if(leapyear) days++;
|
||||
}
|
||||
sum += days;
|
||||
m++;
|
||||
}
|
||||
|
||||
sum += day - 1;
|
||||
return (sum + 1) % 7; //1900-01-01 was a Monday
|
||||
}
|
||||
|
||||
uint8 SRTC::mmio_read(uint addr) {
|
||||
switch(addr & 0xffff) {
|
||||
addr &= 0xffff;
|
||||
|
||||
case 0x2800: {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
if(srtc.index < 0) {
|
||||
set_time();
|
||||
srtc.index++;
|
||||
return 0x0f; //send start message
|
||||
} else if(srtc.index > MAX_SRTC_INDEX) {
|
||||
srtc.index = -1;
|
||||
return 0x0f; //send finished message
|
||||
if(addr == 0x2800) {
|
||||
if(rtc_mode != RTCM_Read) return 0x00;
|
||||
|
||||
if(rtc_index < 0) {
|
||||
update_time();
|
||||
rtc_index++;
|
||||
return 0x0f;
|
||||
} else if(rtc_index > 12) {
|
||||
rtc_index = -1;
|
||||
return 0x0f;
|
||||
} else {
|
||||
return srtc.data[srtc.index++];
|
||||
return memory::cartrtc.read(rtc_index++);
|
||||
}
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 0x2801: {
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return cpu.regs.mdr;
|
||||
}
|
||||
|
||||
//Please see notes above about the implementation of the S-RTC
|
||||
//Writes are stored the srtc.data[] array, but they are ignored
|
||||
//as reads will refresh the data array with the current system
|
||||
//time. The write method is only here for the sake of faux
|
||||
//emulation of the real hardware.
|
||||
void SRTC::mmio_write(uint addr, uint8 data) {
|
||||
switch(addr & 0xffff) {
|
||||
addr &= 0xffff;
|
||||
|
||||
case 0x2800: {
|
||||
} break;
|
||||
|
||||
case 0x2801: {
|
||||
if(addr == 0x2801) {
|
||||
data &= 0x0f; //only the low four bits are used
|
||||
|
||||
if(data >= 0x0d) {
|
||||
switch(data) {
|
||||
case 0x0d:
|
||||
srtc.mode = SRTC_READ;
|
||||
srtc.index = -1;
|
||||
break;
|
||||
case 0x0e:
|
||||
srtc.mode = SRTC_COMMAND;
|
||||
break;
|
||||
case 0x0f:
|
||||
//unknown behaviour
|
||||
break;
|
||||
}
|
||||
if(data == 0x0d) {
|
||||
rtc_mode = RTCM_Read;
|
||||
rtc_index = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(srtc.mode == SRTC_WRITE) {
|
||||
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
|
||||
srtc.data[srtc.index++] = data;
|
||||
if(data == 0x0e) {
|
||||
rtc_mode = RTCM_Command;
|
||||
return;
|
||||
}
|
||||
|
||||
if(srtc.index == MAX_SRTC_INDEX) {
|
||||
//all S-RTC data has been loaded by program
|
||||
srtc.data[srtc.index++] = 0x00; //day_of_week
|
||||
if(data == 0x0f) return; //unknown behavior
|
||||
|
||||
if(rtc_mode == RTCM_Write) {
|
||||
if(rtc_index >= 0 && rtc_index < 12) {
|
||||
memory::cartrtc.write(rtc_index++, data);
|
||||
|
||||
if(rtc_index == 12) {
|
||||
//day of week is automatically calculated and written
|
||||
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||
unsigned month = memory::cartrtc.read( 8);
|
||||
unsigned year = memory::cartrtc.read( 9) + memory::cartrtc.read(10) * 10 + memory::cartrtc.read(11) * 100;
|
||||
year += 1000;
|
||||
|
||||
memory::cartrtc.write(rtc_index++, weekday(year, month, day));
|
||||
}
|
||||
}
|
||||
} else if(srtc.mode == SRTC_COMMAND) {
|
||||
switch(data) {
|
||||
case SRTC_COMMAND_CLEAR:
|
||||
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
|
||||
srtc.index = -1;
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
case SRTC_COMMAND_WRITE:
|
||||
srtc.index = 0;
|
||||
srtc.mode = SRTC_WRITE;
|
||||
break;
|
||||
default:
|
||||
//unknown behaviour
|
||||
srtc.mode = SRTC_READY;
|
||||
break;
|
||||
}
|
||||
} else if(rtc_mode == RTCM_Command) {
|
||||
if(data == 0) {
|
||||
rtc_mode = RTCM_Write;
|
||||
rtc_index = 0;
|
||||
} else if(data == 4) {
|
||||
rtc_mode = RTCM_Ready;
|
||||
rtc_index = -1;
|
||||
for(unsigned i = 0; i < 13; i++) memory::cartrtc.write(i, 0);
|
||||
} else {
|
||||
if(srtc.mode == SRTC_READ) {
|
||||
//ignore writes while in read mode
|
||||
} else if(srtc.mode == SRTC_READY) {
|
||||
//unknown behaviour
|
||||
//unknown behavior
|
||||
rtc_mode = RTCM_Ready;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
SRTC::SRTC() {}
|
||||
SRTC::SRTC() {
|
||||
}
|
||||
|
@@ -1,43 +1,8 @@
|
||||
class SRTC : public MMIO {
|
||||
public:
|
||||
enum { MAX_SRTC_INDEX = 0x0c };
|
||||
void update_time();
|
||||
unsigned weekday(unsigned year, unsigned month, unsigned day);
|
||||
|
||||
enum {
|
||||
SRTC_READ = 0,
|
||||
SRTC_WRITE,
|
||||
SRTC_COMMAND,
|
||||
SRTC_READY
|
||||
};
|
||||
|
||||
enum {
|
||||
SRTC_COMMAND_WRITE = 0,
|
||||
SRTC_COMMAND_CLEAR = 4
|
||||
};
|
||||
|
||||
/******************************
|
||||
[srtc.data structure]
|
||||
Index Description Range
|
||||
----- ----------- -----
|
||||
0 Seconds low 0-9
|
||||
1 Seconds high 0-5
|
||||
2 Minutes low 0-9
|
||||
3 Minutes high 0-5
|
||||
4 Hour low 0-9
|
||||
5 Hour high 0-2
|
||||
6 Day low 0-9
|
||||
7 Day high 0-3
|
||||
8 Month 1-12
|
||||
9 Year ones 0-9
|
||||
10 Year tens 0-9
|
||||
11 Year hundreds 9-11 (9=19xx, 10=20xx, 11=21xx)
|
||||
12 Day of week 0-6 (0=Sunday, ...)
|
||||
******************************/
|
||||
struct {
|
||||
int8 index;
|
||||
uint8 mode;
|
||||
uint8 data[MAX_SRTC_INDEX + 1];
|
||||
} srtc;
|
||||
void set_time();
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
@@ -47,6 +12,11 @@ struct {
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
SRTC();
|
||||
|
||||
private:
|
||||
static const unsigned months[12];
|
||||
enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode;
|
||||
signed rtc_index;
|
||||
};
|
||||
|
||||
extern SRTC srtc;
|
||||
|
@@ -1,4 +1,6 @@
|
||||
#include "../../base.h"
|
||||
#define ST010_CPP
|
||||
|
||||
#include "st010_data.h"
|
||||
#include "st010_op.cpp"
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef ST010_CPP
|
||||
|
||||
//ST-010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
|
||||
//bsnes port - Copyright (C) 2007 byuu
|
||||
|
||||
@@ -255,3 +257,5 @@ int16 x1, y1;
|
||||
writew(0x0010, x1);
|
||||
writew(0x0012, y1);
|
||||
}
|
||||
|
||||
#endif //ifdef ST010_CPP
|
||||
|
@@ -1,3 +0,0 @@
|
||||
void op_unknown() {}
|
||||
|
||||
void op_00();
|
@@ -1,7 +0,0 @@
|
||||
//STOP
|
||||
void SuperFX::op_00() {
|
||||
regs.sfr.g = 0;
|
||||
regs.sfr.b = 0;
|
||||
regs.sfr.alt1 = 0;
|
||||
regs.sfr.alt2 = 0;
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
uint8 SuperFX::mmio_read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
case 0x3000: return regs.r0.l;
|
||||
case 0x3001: return regs.r0.h;
|
||||
case 0x3002: return regs.r1.l;
|
||||
case 0x3003: return regs.r1.h;
|
||||
case 0x3004: return regs.r2.l;
|
||||
case 0x3005: return regs.r2.h;
|
||||
case 0x3006: return regs.r3.l;
|
||||
case 0x3007: return regs.r3.h;
|
||||
case 0x3008: return regs.r4.l;
|
||||
case 0x3009: return regs.r4.h;
|
||||
case 0x300a: return regs.r5.l;
|
||||
case 0x300b: return regs.r5.h;
|
||||
case 0x300c: return regs.r6.l;
|
||||
case 0x300d: return regs.r6.h;
|
||||
case 0x300e: return regs.r7.l;
|
||||
case 0x300f: return regs.r7.h;
|
||||
|
||||
case 0x3010: return regs.r8.l;
|
||||
case 0x3011: return regs.r8.h;
|
||||
case 0x3012: return regs.r9.l;
|
||||
case 0x3013: return regs.r9.h;
|
||||
case 0x3014: return regs.r10.l;
|
||||
case 0x3015: return regs.r10.h;
|
||||
case 0x3016: return regs.r11.l;
|
||||
case 0x3017: return regs.r11.h;
|
||||
case 0x3018: return regs.r12.l;
|
||||
case 0x3019: return regs.r12.h;
|
||||
case 0x301a: return regs.r13.l;
|
||||
case 0x301b: return regs.r13.h;
|
||||
case 0x301c: return regs.r14.l;
|
||||
case 0x301d: return regs.r14.h;
|
||||
case 0x301e: return regs.r15.l;
|
||||
case 0x301f: return regs.r15.h;
|
||||
|
||||
//0x3020 - 0x302f unused
|
||||
|
||||
case 0x3030: return regs.sfr;
|
||||
case 0x3031: return regs.sfr >> 8;
|
||||
case 0x3032: return 0x00; //unused
|
||||
case 0x3033: return 0x00; //BRAMR (write only)
|
||||
case 0x3034: return regs.pbr;
|
||||
case 0x3035: return 0x00; //unused
|
||||
case 0x3036: return regs.rombr;
|
||||
case 0x3037: return 0x00; //CFGR (write only)
|
||||
case 0x3038: return 0x00; //SCBR (write only)
|
||||
case 0x3039: return 0x00; //CLSR (write only)
|
||||
case 0x303a: return 0x00; //SCMR (write only)
|
||||
case 0x303b: return regs.vcr;
|
||||
case 0x303c: return regs.rambr;
|
||||
case 0x303d: return 0x00; //unused
|
||||
case 0x303e: return regs.cbr;
|
||||
case 0x303f: return regs.cbr >> 8;
|
||||
|
||||
//0x3040 - 0x30ff unused
|
||||
}
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
return cache[addr - 0x3100];
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
void SuperFX::mmio_write(uint addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
case 0x3000: regs.r0.l = data; return;
|
||||
case 0x3001: regs.r0.h = data; return;
|
||||
case 0x3002: regs.r1.l = data; return;
|
||||
case 0x3003: regs.r1.h = data; return;
|
||||
case 0x3004: regs.r2.l = data; return;
|
||||
case 0x3005: regs.r2.h = data; return;
|
||||
case 0x3006: regs.r3.l = data; return;
|
||||
case 0x3007: regs.r3.h = data; return;
|
||||
case 0x3008: regs.r4.l = data; return;
|
||||
case 0x3009: regs.r4.h = data; return;
|
||||
case 0x300a: regs.r5.l = data; return;
|
||||
case 0x300b: regs.r5.h = data; return;
|
||||
case 0x300c: regs.r6.l = data; return;
|
||||
case 0x300d: regs.r6.h = data; return;
|
||||
case 0x300e: regs.r7.l = data; return;
|
||||
case 0x300f: regs.r7.h = data; return;
|
||||
|
||||
case 0x3010: regs.r8.l = data; return;
|
||||
case 0x3011: regs.r8.h = data; return;
|
||||
case 0x3012: regs.r9.l = data; return;
|
||||
case 0x3013: regs.r9.h = data; return;
|
||||
case 0x3014: regs.r10.l = data; return;
|
||||
case 0x3015: regs.r10.h = data; return;
|
||||
case 0x3016: regs.r11.l = data; return;
|
||||
case 0x3017: regs.r11.h = data; return;
|
||||
case 0x3018: regs.r12.l = data; return;
|
||||
case 0x3019: regs.r12.h = data; return;
|
||||
case 0x301a: regs.r13.l = data; return;
|
||||
case 0x301b: regs.r13.h = data; return;
|
||||
case 0x301c: regs.r14.l = data; return;
|
||||
case 0x301d: regs.r14.h = data; return;
|
||||
case 0x301e: regs.r15.l = data; return;
|
||||
case 0x301f: regs.r15.h = data; return;
|
||||
|
||||
//0x3020 - 0x302f unused
|
||||
|
||||
case 0x3030: regs.sfr.l = data & 0x7e; return; //mask invalid bits
|
||||
case 0x3031: regs.sfr.h = data & 0x9f; return; //mask invalid bits
|
||||
case 0x3032: return; //unused
|
||||
case 0x3033: regs.bramr = data; return;
|
||||
case 0x3034: regs.pbr = data; return;
|
||||
case 0x3035: return; //unused
|
||||
case 0x3036: return; //ROMBR (read only)
|
||||
case 0x3037: regs.cfgr = data; return;
|
||||
case 0x3038: regs.scbr = data; return;
|
||||
case 0x3039: regs.clsr = data; return;
|
||||
case 0x303a: regs.scmr = data; return;
|
||||
case 0x303b: return; //VCR (read only)
|
||||
case 0x303c: return; //RAMBR (read only)
|
||||
case 0x303d: return; //unused
|
||||
case 0x303e: return; //CBR low (read only)
|
||||
case 0x303f: return; //CBR high (read only)
|
||||
|
||||
//0x3040 - 0x30ff unused
|
||||
}
|
||||
|
||||
if(addr >= 0x3100 && addr <= 0x32ff) {
|
||||
cache[addr - 0x3100] = data;
|
||||
return;
|
||||
}
|
||||
}
|
@@ -1,174 +0,0 @@
|
||||
struct Reg16 {
|
||||
union {
|
||||
uint16 w;
|
||||
struct { uint8 order_lsb2(l, h); };
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return w; }
|
||||
inline unsigned operator=(const unsigned i) { return w = i; }
|
||||
|
||||
Reg16() : w(0) {}
|
||||
};
|
||||
|
||||
template<int bit> struct RegFlag8 {
|
||||
uint8 data;
|
||||
|
||||
inline operator bool() const { return data & bit; }
|
||||
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
|
||||
};
|
||||
|
||||
template<int bit> struct RegFlag16 {
|
||||
uint16 data;
|
||||
|
||||
inline operator bool() const { return data & bit; }
|
||||
inline bool operator=(const bool i) { i ? data |= bit : data &= ~bit; return i; }
|
||||
};
|
||||
|
||||
struct SFR {
|
||||
union {
|
||||
uint16 w;
|
||||
struct { uint8 order_lsb2(l, h); };
|
||||
RegFlag16<0x0002> z; //zero flag
|
||||
RegFlag16<0x0004> c; //carry flag
|
||||
RegFlag16<0x0008> s; //sign flag
|
||||
RegFlag16<0x0010> v; //overflow flag
|
||||
RegFlag16<0x0020> g; //go flag
|
||||
RegFlag16<0x0040> r; //ROM read using r14 flag
|
||||
RegFlag16<0x0100> alt1; //alternate instruction 1 flag
|
||||
RegFlag16<0x0200> alt2; //alternate instruction 2 flag
|
||||
RegFlag16<0x0400> il; //immediate lower 8-bit flag
|
||||
RegFlag16<0x0800> ih; //immediate upper 8-bit flag
|
||||
RegFlag16<0x1000> b; //WITH instruction flag
|
||||
RegFlag16<0x8000> irq; //interrupt flag
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return w & 0x9f7e; } //invalid flag bits always return 0 when read
|
||||
inline unsigned operator=(const unsigned i) { return w = i & 0x9f7e; }
|
||||
|
||||
SFR() : w(0) {}
|
||||
};
|
||||
|
||||
struct RAMBR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> bank;
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b & 0x01; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i & 0x01; }
|
||||
|
||||
RAMBR() : b(0) {}
|
||||
};
|
||||
|
||||
struct CBR {
|
||||
uint16 w;
|
||||
|
||||
inline operator unsigned() const { return w & 0xfff0; }
|
||||
inline unsigned operator=(const unsigned i) { return w = i & 0xfff0; }
|
||||
|
||||
CBR() : w(0) {}
|
||||
};
|
||||
|
||||
struct SCMR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> md0; //color mode low
|
||||
RegFlag8<0x02> md1; //color mode high
|
||||
RegFlag8<0x04> ht0; //height low
|
||||
RegFlag8<0x08> ran; //ram enable
|
||||
RegFlag8<0x10> ron; //rom enable
|
||||
RegFlag8<0x20> ht1; //height high
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
SCMR() : b(0) {}
|
||||
};
|
||||
|
||||
struct BRAMR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> flag;
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
BRAMR() : b(0) {}
|
||||
};
|
||||
|
||||
struct CFGR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x20> ms0; //multiplier speed selection
|
||||
RegFlag8<0x80> irq; //irq mask flag
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
CFGR() : b(0) {}
|
||||
};
|
||||
|
||||
struct CLSR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> flag;
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
CLSR() : b(0) {}
|
||||
};
|
||||
|
||||
struct POR {
|
||||
union {
|
||||
uint8 b;
|
||||
RegFlag8<0x01> transparent; //transparent flag
|
||||
RegFlag8<0x02> dither; //dither flag
|
||||
RegFlag8<0x04> highnibble; //high nibble flag
|
||||
RegFlag8<0x08> freezehigh; //freeze high flag
|
||||
RegFlag8<0x10> obj; //OBJ flag
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return b; }
|
||||
inline unsigned operator=(const unsigned i) { return b = i; }
|
||||
|
||||
POR() : b(0) {}
|
||||
};
|
||||
|
||||
struct Regs {
|
||||
Reg16 r0; //default source/destination register
|
||||
Reg16 r1; //pixel plot X position register
|
||||
Reg16 r2; //pixel plot Y position register
|
||||
Reg16 r3;
|
||||
Reg16 r4; //lower 16-bit result of lmult
|
||||
Reg16 r5;
|
||||
Reg16 r6; //multiplier for fmult and lmult
|
||||
Reg16 r7; //fixed point texel X position for merge
|
||||
Reg16 r8; //fixed point texel Y position for merge
|
||||
Reg16 r9;
|
||||
Reg16 r10;
|
||||
Reg16 r11; //return address set by link
|
||||
Reg16 r12; //loop counter
|
||||
Reg16 r13; //loop point address
|
||||
Reg16 r14; //rom address for getb, getbh, getbl, getbs
|
||||
Reg16 r15; //program counter
|
||||
|
||||
SFR sfr; //status/flag register
|
||||
uint8 pbr; //program bank register
|
||||
uint8 rombr; //rom bank register
|
||||
RAMBR rambr; //ram bank register
|
||||
CBR cbr; //cache base register
|
||||
uint8 scbr; //screen base register
|
||||
SCMR scmr; //screen mode register
|
||||
BRAMR bramr; //backup ram register
|
||||
uint8 vcr; //version code register
|
||||
CFGR cfgr; //config register
|
||||
CLSR clsr; //clock select register
|
||||
|
||||
uint8 colr; //color register
|
||||
POR por; //plot option register
|
||||
} regs;
|
@@ -1,42 +0,0 @@
|
||||
#include "../../base.h"
|
||||
|
||||
#include "core/op0x.cpp"
|
||||
|
||||
#include "memory/read.cpp"
|
||||
#include "memory/write.cpp"
|
||||
|
||||
void SuperFX::init() {
|
||||
}
|
||||
|
||||
void SuperFX::enable() {
|
||||
for(uint i = 0x3000; i <= 0x32ff; i++) {
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void SuperFX::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void SuperFX::reset() {
|
||||
regs.r0 = 0;
|
||||
regs.r1 = 0;
|
||||
regs.r2 = 0;
|
||||
regs.r3 = 0;
|
||||
regs.r4 = 0;
|
||||
regs.r5 = 0;
|
||||
regs.r6 = 0;
|
||||
regs.r7 = 0;
|
||||
regs.r8 = 0;
|
||||
regs.r9 = 0;
|
||||
regs.r10 = 0;
|
||||
regs.r11 = 0;
|
||||
regs.r12 = 0;
|
||||
regs.r13 = 0;
|
||||
regs.r14 = 0;
|
||||
regs.r15 = 0;
|
||||
|
||||
regs.sfr = 0;
|
||||
|
||||
memset(cache, 0, sizeof cache);
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
class SuperFX : public MMIO { public:
|
||||
#include "core/core.h"
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 mmio_read (uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
private:
|
||||
#include "regs.h"
|
||||
uint8 cache[512]; //cache RAM
|
||||
};
|
||||
|
||||
extern SuperFX superfx;
|
@@ -1,2 +1 @@
|
||||
@make PLATFORM=win-mingw-x86 clean
|
||||
::@make PLATFORM=win-visualc-x86 clean
|
||||
@make platform=win compiler=mingw32-gcc clean
|
||||
|
@@ -1 +1 @@
|
||||
make PLATFORM=x-gcc-x86 clean
|
||||
make platform=x compiler=gcc clean
|
||||
|
@@ -1,16 +1,32 @@
|
||||
namespace config {
|
||||
|
||||
Config& config() {
|
||||
static Config config;
|
||||
configuration& config() {
|
||||
static configuration config;
|
||||
return config;
|
||||
}
|
||||
|
||||
integral_setting File::autodetect_type(config(), "file.autodetect_type",
|
||||
"Auto-detect file type by inspecting file header, rather than by file extension.\n"
|
||||
"In other words, if a .zip file is renamed to .smc, it will still be correctly\n"
|
||||
"identified as a .zip file. However, there is an infinitesimal (1:~500,000,000)\n"
|
||||
"chance of a false detection when loading an uncompressed image file, if this\n"
|
||||
"option is enabled.",
|
||||
integral_setting::boolean, false);
|
||||
|
||||
integral_setting File::bypass_patch_crc32(config(), "file.bypass_patch_crc32",
|
||||
"UPS patches contain CRC32s to validate that a patch was applied successfully.\n"
|
||||
"By default, if this validation fails, said patch will not be applied.\n"
|
||||
"Setting this option to true will bypass the validation,\n"
|
||||
"which may or may not result in a working image.\n"
|
||||
"Enabling this option is strongly discouraged.",
|
||||
integral_setting::boolean, false);
|
||||
|
||||
string file_updatepath(const char *req_file, const char *req_path) {
|
||||
string file(req_file);
|
||||
string file(req_file);
|
||||
replace(file, "\\", "/");
|
||||
if(!req_path || strlen(req_path) == 0) { return file; }
|
||||
|
||||
string path(req_path);
|
||||
string path(req_path);
|
||||
replace(path, "\\", "/");
|
||||
if(!strend(path, "/")) { strcat(path, "/"); }
|
||||
|
||||
@@ -22,54 +38,36 @@ string path(req_path);
|
||||
strcpy(path, temp);
|
||||
}
|
||||
|
||||
lstring part;
|
||||
lstring part;
|
||||
split(part, "/", file);
|
||||
strcat(path, part[count(part) - 1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
StringSetting Path::base(0, "path.base",
|
||||
"Path that bsnes resides in", "");
|
||||
StringSetting Path::rom(&config(), "path.rom",
|
||||
string_setting Path::base("path.base", "Path that bsnes resides in", "");
|
||||
string_setting Path::user("path.user", "Path to user folder", "");
|
||||
|
||||
string_setting Path::rom(config(), "path.rom",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
StringSetting Path::save(&config(), "path.save",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
StringSetting Path::bsx(&config(), "path.bsx", "", "");
|
||||
StringSetting Path::st(&config(), "path.st", "", "");
|
||||
string_setting Path::patch(config(), "path.patch",
|
||||
"Default path for all UPS patch files (\"\" = use current directory)", "");
|
||||
string_setting Path::save(config(), "path.save",
|
||||
"Default path for all save RAM files (\"\" = use current directory)", "");
|
||||
string_setting Path::cheat(config(), "path.cheat",
|
||||
"Default path for all cheat files (\"\" = use current directory)", "");
|
||||
string_setting Path::bsx(config(), "path.bsx", "", "");
|
||||
string_setting Path::st(config(), "path.st", "", "");
|
||||
|
||||
IntegerSetting SNES::gamma_ramp(&config(), "snes.colorfilter.gamma_ramp",
|
||||
"Use precalculated TV-style gamma ramp", IntegerSetting::Boolean, true);
|
||||
IntegerSetting SNES::sepia(&config(), "snes.colorfilter.sepia",
|
||||
"Convert color to sepia tone", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::grayscale(&config(), "snes.colorfilter.grayscale",
|
||||
"Convert color to grayscale tone", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::invert(&config(), "snes.colorfilter.invert",
|
||||
"Invert output image colors", IntegerSetting::Boolean, false);
|
||||
IntegerSetting SNES::contrast(&config(), "snes.colorfilter.contrast",
|
||||
"Contrast", IntegerSetting::Decimal, 0);
|
||||
IntegerSetting SNES::brightness(&config(), "snes.colorfilter.brightness",
|
||||
"Brightness", IntegerSetting::Decimal, 0);
|
||||
IntegerSetting SNES::gamma(&config(), "snes.colorfilter.gamma",
|
||||
"Gamma", IntegerSetting::Decimal, 80);
|
||||
integral_setting SNES::controller_port1(config(), "snes.controller_port1",
|
||||
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||
integral_setting SNES::controller_port2(config(), "snes.controller_port2",
|
||||
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||
|
||||
IntegerSetting SNES::ntsc_merge_fields(&config(), "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"
|
||||
"", IntegerSetting::Boolean, true);
|
||||
|
||||
IntegerSetting SNES::mute(&config(), "snes.mute", "Mutes SNES audio output when enabled",
|
||||
IntegerSetting::Boolean, false);
|
||||
|
||||
IntegerSetting SNES::controller_port0(&config(), "snes.controller_port_1",
|
||||
"Controller attached to SNES port 1", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD1);
|
||||
IntegerSetting SNES::controller_port1(&config(), "snes.controller_port_2",
|
||||
"Controller attached to SNES port 2", IntegerSetting::Decimal, ::SNES::DEVICEID_JOYPAD2);
|
||||
|
||||
IntegerSetting CPU::ntsc_clock_rate(&config(), "cpu.ntsc_clock_rate",
|
||||
"NTSC S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21477272);
|
||||
IntegerSetting CPU::pal_clock_rate(&config(), "cpu.pal_clock_rate",
|
||||
"PAL S-CPU clock rate (in hz)", IntegerSetting::Decimal, 21281370);
|
||||
IntegerSetting CPU::wram_init_value(&config(), "cpu.wram_init_value",
|
||||
integral_setting CPU::ntsc_clock_rate(config(), "cpu.ntsc_clock_rate",
|
||||
"NTSC S-CPU clock rate (in hz)", integral_setting::decimal, 21477272);
|
||||
integral_setting CPU::pal_clock_rate(config(), "cpu.pal_clock_rate",
|
||||
"PAL S-CPU clock rate (in hz)", integral_setting::decimal, 21281370);
|
||||
integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
||||
"Value to initialize 128k WRAM to upon power cycle.\n"
|
||||
"Note that on real hardware, this value is undefined; meaning it can vary\n"
|
||||
"per power-on, and per SNES unit. Such randomness is undesirable for an\n"
|
||||
@@ -81,52 +79,49 @@ IntegerSetting CPU::wram_init_value(&config(), "cpu.wram_init_value",
|
||||
"which executed on these copiers. Using 0x00 will therefore fix many homebrew\n"
|
||||
"programs, but *will* break some poorly programmed commercial software titles,\n"
|
||||
"which do not properly initialize WRAM upon power cycle.\n",
|
||||
IntegerSetting::Hex, 0x55);
|
||||
integral_setting::hex, 0x55);
|
||||
|
||||
IntegerSetting CPU::hdma_enable(0, "cpu.hdma_enable",
|
||||
"Enable HDMA effects", IntegerSetting::Boolean, true);
|
||||
integral_setting SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 768);
|
||||
integral_setting SMP::pal_clock_rate(config(), "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 768);
|
||||
|
||||
IntegerSetting SMP::ntsc_clock_rate(&config(), "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
||||
IntegerSetting SMP::pal_clock_rate(&config(), "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", IntegerSetting::Decimal, 24606720);
|
||||
|
||||
IntegerSetting PPU::Hack::render_scanline_position(&config(), "ppu.hack.render_scanline_position",
|
||||
integral_setting PPU::Hack::render_scanline_position(config(), "ppu.hack.render_scanline_position",
|
||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||
IntegerSetting::Decimal, 512);
|
||||
IntegerSetting PPU::Hack::obj_cache(&config(), "ppu.hack.obj_cache",
|
||||
integral_setting::decimal, 512);
|
||||
integral_setting PPU::Hack::obj_cache(config(), "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);
|
||||
IntegerSetting PPU::Hack::oam_address_invalidation(&config(), "ppu.hack.oam_address_invalidation",
|
||||
integral_setting::boolean, false);
|
||||
integral_setting PPU::Hack::oam_address_invalidation(config(), "ppu.hack.oam_address_invalidation",
|
||||
"OAM access address changes during active display, as the S-PPU reads\n"
|
||||
"data to render the display. Thusly, the address retrieved when accessing\n"
|
||||
"OAM during active display is unpredictable. Unfortunately, the exact\n"
|
||||
"algorithm for this is completely unknown at this time. It is more hardware\n"
|
||||
"accurate to enable this setting, but one must *not* rely on the actual\n"
|
||||
"address to match hardware under emulation.",
|
||||
IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::Hack::cgram_address_invalidation(&config(), "ppu.hack.cgram_address_invalidation",
|
||||
integral_setting::boolean, true);
|
||||
integral_setting PPU::Hack::cgram_address_invalidation(config(), "ppu.hack.cgram_address_invalidation",
|
||||
"CGRAM access address changes during active display (excluding hblank), as\n"
|
||||
"the S-PPU reads data to render the display. Thusly, as with OAM, the access\n"
|
||||
"address is unpredictable. Again, enabling this setting is more hardware\n"
|
||||
"accurate, but one must *not* rely on the actual address to match hardware\n"
|
||||
"under emulation.",
|
||||
IntegerSetting::Boolean, true);
|
||||
integral_setting::boolean, true);
|
||||
|
||||
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);
|
||||
integral_setting PPU::opt_enable("ppu.opt_enable", "Enable offset-per-tile effects", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg1_pri0_enable("ppu.bg1_pri0_enable", "Enable BG1 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg1_pri1_enable("ppu.bg1_pri1_enable", "Enable BG1 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg2_pri0_enable("ppu.bg2_pri0_enable", "Enable BG2 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg2_pri1_enable("ppu.bg2_pri1_enable", "Enable BG2 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg3_pri0_enable("ppu.bg3_pri0_enable", "Enable BG3 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg3_pri1_enable("ppu.bg3_pri1_enable", "Enable BG3 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg4_pri0_enable("ppu.bg4_pri0_enable", "Enable BG4 Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::bg4_pri1_enable("ppu.bg4_pri1_enable", "Enable BG4 Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri0_enable("ppu.oam_pri0_enable", "Enable OAM Priority 0", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri1_enable("ppu.oam_pri1_enable", "Enable OAM Priority 1", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri2_enable("ppu.oam_pri2_enable", "Enable OAM Priority 2", integral_setting::boolean, true);
|
||||
integral_setting PPU::oam_pri3_enable("ppu.oam_pri3_enable", "Enable OAM Priority 3", integral_setting::boolean, true);
|
||||
|
||||
};
|
||||
} //namespace config
|
||||
|
@@ -1,47 +1,48 @@
|
||||
namespace config {
|
||||
|
||||
extern Config& config();
|
||||
extern configuration& config();
|
||||
|
||||
string file_updatepath(const char *, const char *);
|
||||
string file_updatepath(const char*, const char*);
|
||||
|
||||
extern struct File {
|
||||
static integral_setting autodetect_type;
|
||||
static integral_setting bypass_patch_crc32;
|
||||
} file;
|
||||
|
||||
extern struct Path {
|
||||
static StringSetting base, rom, save;
|
||||
static StringSetting bsx, st;
|
||||
static string_setting base, user, rom, patch, save, cheat;
|
||||
static string_setting bsx, st;
|
||||
} path;
|
||||
|
||||
extern struct SNES {
|
||||
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;
|
||||
static integral_setting controller_port1;
|
||||
static integral_setting controller_port2;
|
||||
} snes;
|
||||
|
||||
extern struct CPU {
|
||||
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
|
||||
static IntegerSetting wram_init_value;
|
||||
static IntegerSetting hdma_enable;
|
||||
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||
static integral_setting wram_init_value;
|
||||
} cpu;
|
||||
|
||||
extern struct SMP {
|
||||
static IntegerSetting ntsc_clock_rate, pal_clock_rate;
|
||||
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||
} smp;
|
||||
|
||||
extern struct PPU {
|
||||
struct Hack {
|
||||
static IntegerSetting render_scanline_position;
|
||||
static IntegerSetting obj_cache;
|
||||
static IntegerSetting oam_address_invalidation;
|
||||
static IntegerSetting cgram_address_invalidation;
|
||||
static integral_setting render_scanline_position;
|
||||
static integral_setting obj_cache;
|
||||
static integral_setting oam_address_invalidation;
|
||||
static integral_setting cgram_address_invalidation;
|
||||
} hack;
|
||||
|
||||
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;
|
||||
static integral_setting opt_enable;
|
||||
static integral_setting bg1_pri0_enable, bg1_pri1_enable;
|
||||
static integral_setting bg2_pri0_enable, bg2_pri1_enable;
|
||||
static integral_setting bg3_pri0_enable, bg3_pri1_enable;
|
||||
static integral_setting bg4_pri0_enable, bg4_pri1_enable;
|
||||
static integral_setting oam_pri0_enable, oam_pri1_enable;
|
||||
static integral_setting oam_pri2_enable, oam_pri3_enable;
|
||||
} ppu;
|
||||
|
||||
};
|
||||
|
@@ -1,8 +1,10 @@
|
||||
#include "../base.h"
|
||||
#define CPU_CPP
|
||||
|
||||
#include "dcpu.cpp"
|
||||
|
||||
CPU::CPU() {
|
||||
cpu_version = 1;
|
||||
cpu_version = 2;
|
||||
}
|
||||
|
||||
CPU::~CPU() {
|
||||
|
@@ -4,41 +4,36 @@ class CPU : public MMIO {
|
||||
public:
|
||||
virtual void enter() = 0;
|
||||
|
||||
public:
|
||||
//CPU version number
|
||||
//* 1 and 2 are known
|
||||
//* reported by $4210
|
||||
//* affects DRAM refresh behavior
|
||||
uint8 cpu_version;
|
||||
//CPU version number
|
||||
//* 1 and 2 are known
|
||||
//* reported by $4210
|
||||
//* affects DRAM refresh behavior
|
||||
uint8 cpu_version;
|
||||
|
||||
//timing
|
||||
//timing
|
||||
virtual uint16 vcounter() = 0;
|
||||
virtual uint16 hcounter() = 0;
|
||||
virtual uint16 hclock() = 0;
|
||||
virtual bool interlace() = 0;
|
||||
virtual bool interlace_field() = 0;
|
||||
virtual bool overscan() = 0;
|
||||
virtual uint16 region_scanlines() = 0;
|
||||
virtual void set_interlace(bool r) = 0;
|
||||
virtual void set_overscan (bool r) = 0;
|
||||
virtual uint16 hdot() = 0;
|
||||
|
||||
CPURegs regs;
|
||||
virtual uint8 port_read (uint8 port) = 0;
|
||||
virtual uint8 pio() = 0;
|
||||
virtual bool joylatch() = 0;
|
||||
virtual uint8 port_read(uint8 port) = 0;
|
||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||
|
||||
CPURegs regs;
|
||||
enum {
|
||||
FLAG_N = 0x80, FLAG_V = 0x40,
|
||||
FLAG_M = 0x20, FLAG_X = 0x10,
|
||||
FLAG_D = 0x08, FLAG_I = 0x04,
|
||||
FLAG_Z = 0x02, FLAG_C = 0x01
|
||||
};
|
||||
virtual uint8 pio_status() = 0;
|
||||
|
||||
virtual void scanline() = 0;
|
||||
virtual void frame() = 0;
|
||||
virtual void power() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
/*****
|
||||
/*****
|
||||
* in opcode-based CPU emulators, the main emulation routine
|
||||
* will only be able to call the disassemble_opcode() function
|
||||
* on clean opcode edges. but with cycle-based CPU emulators,
|
||||
@@ -53,10 +48,10 @@ CPURegs regs;
|
||||
*****/
|
||||
virtual bool in_opcode() { return false; }
|
||||
|
||||
/*****
|
||||
/*****
|
||||
* opcode disassembler
|
||||
*****/
|
||||
enum {
|
||||
enum {
|
||||
OPTYPE_DP = 0, //dp
|
||||
OPTYPE_DPX, //dp,x
|
||||
OPTYPE_DPY, //dp,y
|
||||
@@ -78,7 +73,7 @@ enum {
|
||||
OPTYPE_IADDR_PC, //pbr:(addr)
|
||||
OPTYPE_RELB, //relb
|
||||
OPTYPE_RELW, //relw
|
||||
};
|
||||
};
|
||||
|
||||
void disassemble_opcode(char *output);
|
||||
uint8 dreadb(uint32 addr);
|
||||
|
@@ -1,75 +1,88 @@
|
||||
class CPURegFlags {
|
||||
public:
|
||||
union {
|
||||
uint8 data;
|
||||
struct {
|
||||
bool order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
|
||||
};
|
||||
template<int mask>
|
||||
struct CPUFlag {
|
||||
uint8 &data;
|
||||
|
||||
inline operator bool() const { return data & mask; }
|
||||
inline CPUFlag& operator=(bool i) { data = (data & ~mask) | (-i & mask); return *this; }
|
||||
|
||||
CPUFlag(uint8 &data_) : data(data_) {}
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return data; }
|
||||
template<typename T> inline unsigned operator = (const T i) { data = i; return data; }
|
||||
template<typename T> inline unsigned operator |= (const T i) { data |= i; return data; }
|
||||
template<typename T> inline unsigned operator ^= (const T i) { data ^= i; return data; }
|
||||
template<typename T> inline unsigned operator &= (const T i) { data &= i; return data; }
|
||||
class CPURegFlags {
|
||||
public:
|
||||
uint8 data;
|
||||
CPUFlag<0x80> n;
|
||||
CPUFlag<0x40> v;
|
||||
CPUFlag<0x20> m;
|
||||
CPUFlag<0x10> x;
|
||||
CPUFlag<0x08> d;
|
||||
CPUFlag<0x04> i;
|
||||
CPUFlag<0x02> z;
|
||||
CPUFlag<0x01> c;
|
||||
|
||||
CPURegFlags() : data(0) {}
|
||||
inline operator unsigned() const { return data; }
|
||||
inline unsigned operator = (unsigned i) { data = i; return data; }
|
||||
inline unsigned operator |= (unsigned i) { data |= i; return data; }
|
||||
inline unsigned operator ^= (unsigned i) { data ^= i; return data; }
|
||||
inline unsigned operator &= (unsigned i) { data &= i; return data; }
|
||||
|
||||
CPURegFlags() : data(0), n(data), v(data), m(data), x(data), d(data), i(data), z(data), c(data) {}
|
||||
};
|
||||
|
||||
class CPUReg16 {
|
||||
public:
|
||||
union {
|
||||
union {
|
||||
uint16 w;
|
||||
struct { uint8 order_lsb2(l, h); };
|
||||
};
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return w; }
|
||||
template<typename T> inline unsigned operator = (const T i) { w = i; return w; }
|
||||
template<typename T> inline unsigned operator |= (const T i) { w |= i; return w; }
|
||||
template<typename T> inline unsigned operator ^= (const T i) { w ^= i; return w; }
|
||||
template<typename T> inline unsigned operator &= (const T i) { w &= i; return w; }
|
||||
template<typename T> inline unsigned operator <<= (const T i) { w <<= i; return w; }
|
||||
template<typename T> inline unsigned operator >>= (const T i) { w >>= i; return w; }
|
||||
template<typename T> inline unsigned operator += (const T i) { w += i; return w; }
|
||||
template<typename T> inline unsigned operator -= (const T i) { w -= i; return w; }
|
||||
template<typename T> inline unsigned operator *= (const T i) { w *= i; return w; }
|
||||
template<typename T> inline unsigned operator /= (const T i) { w /= i; return w; }
|
||||
template<typename T> inline unsigned operator %= (const T i) { w %= i; return w; }
|
||||
inline unsigned operator = (unsigned i) { w = i; return w; }
|
||||
inline unsigned operator |= (unsigned i) { w |= i; return w; }
|
||||
inline unsigned operator ^= (unsigned i) { w ^= i; return w; }
|
||||
inline unsigned operator &= (unsigned i) { w &= i; return w; }
|
||||
inline unsigned operator <<= (unsigned i) { w <<= i; return w; }
|
||||
inline unsigned operator >>= (unsigned i) { w >>= i; return w; }
|
||||
inline unsigned operator += (unsigned i) { w += i; return w; }
|
||||
inline unsigned operator -= (unsigned i) { w -= i; return w; }
|
||||
inline unsigned operator *= (unsigned i) { w *= i; return w; }
|
||||
inline unsigned operator /= (unsigned i) { w /= i; return w; }
|
||||
inline unsigned operator %= (unsigned i) { w %= i; return w; }
|
||||
|
||||
CPUReg16() : w(0) {}
|
||||
};
|
||||
|
||||
class CPUReg24 {
|
||||
public:
|
||||
union {
|
||||
union {
|
||||
uint32 d;
|
||||
struct { uint16 order_lsb2(w, wh); };
|
||||
struct { uint8 order_lsb4(l, h, b, bh); };
|
||||
};
|
||||
};
|
||||
|
||||
inline operator unsigned() const { return d; }
|
||||
template<typename T> inline unsigned operator = (const T i) { d = uclip<24>(i); return d; }
|
||||
template<typename T> inline unsigned operator |= (const T i) { d = uclip<24>(d | i); return d; }
|
||||
template<typename T> inline unsigned operator ^= (const T i) { d = uclip<24>(d ^ i); return d; }
|
||||
template<typename T> inline unsigned operator &= (const T i) { d = uclip<24>(d & i); return d; }
|
||||
template<typename T> inline unsigned operator <<= (const T i) { d = uclip<24>(d << i); return d; }
|
||||
template<typename T> inline unsigned operator >>= (const T i) { d = uclip<24>(d >> i); return d; }
|
||||
template<typename T> inline unsigned operator += (const T i) { d = uclip<24>(d + i); return d; }
|
||||
template<typename T> inline unsigned operator -= (const T i) { d = uclip<24>(d - i); return d; }
|
||||
template<typename T> inline unsigned operator *= (const T i) { d = uclip<24>(d * i); return d; }
|
||||
template<typename T> inline unsigned operator /= (const T i) { d = uclip<24>(d / i); return d; }
|
||||
template<typename T> inline unsigned operator %= (const T i) { d = uclip<24>(d % i); return d; }
|
||||
inline unsigned operator = (unsigned i) { d = uclip<24>(i); return d; }
|
||||
inline unsigned operator |= (unsigned i) { d = uclip<24>(d | i); return d; }
|
||||
inline unsigned operator ^= (unsigned i) { d = uclip<24>(d ^ i); return d; }
|
||||
inline unsigned operator &= (unsigned i) { d = uclip<24>(d & i); return d; }
|
||||
inline unsigned operator <<= (unsigned i) { d = uclip<24>(d << i); return d; }
|
||||
inline unsigned operator >>= (unsigned i) { d = uclip<24>(d >> i); return d; }
|
||||
inline unsigned operator += (unsigned i) { d = uclip<24>(d + i); return d; }
|
||||
inline unsigned operator -= (unsigned i) { d = uclip<24>(d - i); return d; }
|
||||
inline unsigned operator *= (unsigned i) { d = uclip<24>(d * i); return d; }
|
||||
inline unsigned operator /= (unsigned i) { d = uclip<24>(d / i); return d; }
|
||||
inline unsigned operator %= (unsigned i) { d = uclip<24>(d % i); return d; }
|
||||
|
||||
CPUReg24() : d(0) {}
|
||||
};
|
||||
|
||||
class CPURegs {
|
||||
public:
|
||||
CPUReg24 pc;
|
||||
CPUReg16 a, x, y, s, d;
|
||||
CPURegFlags p;
|
||||
uint8 db;
|
||||
uint8 mdr;
|
||||
bool e;
|
||||
CPURegs() : db(0), mdr(0x00), e(false) {}
|
||||
CPUReg24 pc;
|
||||
CPUReg16 a, x, y, s, d;
|
||||
CPURegFlags p;
|
||||
uint8 db;
|
||||
uint8 mdr;
|
||||
bool e;
|
||||
CPURegs() : db(0), mdr(0), e(false) {}
|
||||
};
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef CPU_CPP
|
||||
|
||||
uint8 CPU::dreadb(uint32 addr) {
|
||||
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
|
||||
//$[00-3f|80-bf]:[2000-5fff]
|
||||
@@ -423,7 +425,7 @@ uint8 op2 = dreadb(pc.d);
|
||||
strcat(s, t);
|
||||
strcat(s, " ");
|
||||
|
||||
sprintf(t, "V:%3d H:%4d", vcounter(), hclock());
|
||||
sprintf(t, "V:%3d H:%4d", vcounter(), hcounter());
|
||||
strcat(s, t);
|
||||
}
|
||||
|
||||
@@ -473,3 +475,5 @@ static uint8 op_len_tbl[256] = {
|
||||
if(len == 6)return (regs.e || regs.p.x) ? 2 : 3;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif //ifdef CPU_CPP
|
||||
|
@@ -1,3 +0,0 @@
|
||||
cl /nologo /O2 scpugen.cpp
|
||||
@pause
|
||||
@del *.obj
|
4
src/cpu/scpu/core/cc.sh
Normal file
4
src/cpu/scpu/core/cc.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
g++ -c scpugen.cpp -I../../../lib
|
||||
g++ -c ../../../lib/nall/string.cpp -I../../../lib
|
||||
g++ -o scpugen scpugen.o string.o
|
||||
rm *.o
|
@@ -1 +0,0 @@
|
||||
@del *.exe
|
1
src/cpu/scpu/core/clean.sh
Normal file
1
src/cpu/scpu/core/clean.sh
Normal file
@@ -0,0 +1 @@
|
||||
rm scpugen
|
@@ -1,10 +1,6 @@
|
||||
#include "opfn.cpp"
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
#include "op_read.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
#include "opfn.cpp"
|
||||
|
||||
void sCPU::enter() { loop:
|
||||
if(event.irq) {
|
||||
@@ -22,7 +18,13 @@ void sCPU::enter() { loop:
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
(this->*optbl[op_readpc()])();
|
||||
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;
|
||||
|
||||
goto loop;
|
||||
@@ -43,7 +45,22 @@ void sCPU::op_irq() {
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
//
|
||||
//immediate, 2-cycle opcodes with I/O cycle will become bus read
|
||||
//when an IRQ is to be triggered immediately after opcode completion
|
||||
//this affects the following opcodes:
|
||||
// clc, cld, cli, clv, sec, sed, sei,
|
||||
// tax, tay, txa, txy, tya, tyx,
|
||||
// tcd, tcs, tdc, tsc, tsx, tcs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
alwaysinline void sCPU::op_io_irq() {
|
||||
if(event.irq) {
|
||||
//IRQ pending, modify I/O cycle to bus read cycle, do not increment PC
|
||||
op_read(regs.pc.d);
|
||||
} else {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond2() {
|
||||
if(regs.d.l != 0x00) {
|
||||
@@ -62,3 +79,5 @@ alwaysinline void sCPU::op_io_cond6(uint16 addr) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,13 +1,11 @@
|
||||
void (sCPU::*optbl[256])();
|
||||
|
||||
CPUReg24 aa, rd;
|
||||
uint8 dp, sp;
|
||||
CPUReg24 aa, rd;
|
||||
uint8_t dp, sp;
|
||||
|
||||
void op_irq();
|
||||
|
||||
inline bool in_opcode() { return status.in_opcode; }
|
||||
|
||||
//op_read
|
||||
//op_read
|
||||
void op_adc_b();
|
||||
void op_adc_w();
|
||||
void op_and_b();
|
||||
@@ -32,7 +30,7 @@ uint8 dp, sp;
|
||||
void op_ora_w();
|
||||
void op_sbc_b();
|
||||
void op_sbc_w();
|
||||
//op_rmw
|
||||
//op_rmw
|
||||
void op_inc_b();
|
||||
void op_inc_w();
|
||||
void op_dec_b();
|
||||
@@ -50,8 +48,7 @@ uint8 dp, sp;
|
||||
void op_tsb_b();
|
||||
void op_tsb_w();
|
||||
|
||||
void op_io_irq();
|
||||
void op_io_cond2();
|
||||
void op_io_cond4(uint16 x, uint16 y);
|
||||
void op_io_cond6(uint16 addr);
|
||||
|
||||
#include "op.h"
|
||||
|
@@ -1,256 +0,0 @@
|
||||
void op_adc_const();
|
||||
void op_and_const();
|
||||
void op_cmp_const();
|
||||
void op_cpx_const();
|
||||
void op_cpy_const();
|
||||
void op_eor_const();
|
||||
void op_lda_const();
|
||||
void op_ldx_const();
|
||||
void op_ldy_const();
|
||||
void op_ora_const();
|
||||
void op_sbc_const();
|
||||
void op_adc_addr();
|
||||
void op_and_addr();
|
||||
void op_bit_addr();
|
||||
void op_cmp_addr();
|
||||
void op_cpx_addr();
|
||||
void op_cpy_addr();
|
||||
void op_eor_addr();
|
||||
void op_lda_addr();
|
||||
void op_ldx_addr();
|
||||
void op_ldy_addr();
|
||||
void op_ora_addr();
|
||||
void op_sbc_addr();
|
||||
void op_adc_addrx();
|
||||
void op_and_addrx();
|
||||
void op_bit_addrx();
|
||||
void op_cmp_addrx();
|
||||
void op_eor_addrx();
|
||||
void op_lda_addrx();
|
||||
void op_ldy_addrx();
|
||||
void op_ora_addrx();
|
||||
void op_sbc_addrx();
|
||||
void op_adc_addry();
|
||||
void op_and_addry();
|
||||
void op_cmp_addry();
|
||||
void op_eor_addry();
|
||||
void op_lda_addry();
|
||||
void op_ldx_addry();
|
||||
void op_ora_addry();
|
||||
void op_sbc_addry();
|
||||
void op_adc_long();
|
||||
void op_and_long();
|
||||
void op_cmp_long();
|
||||
void op_eor_long();
|
||||
void op_lda_long();
|
||||
void op_ora_long();
|
||||
void op_sbc_long();
|
||||
void op_adc_longx();
|
||||
void op_and_longx();
|
||||
void op_cmp_longx();
|
||||
void op_eor_longx();
|
||||
void op_lda_longx();
|
||||
void op_ora_longx();
|
||||
void op_sbc_longx();
|
||||
void op_adc_dp();
|
||||
void op_and_dp();
|
||||
void op_bit_dp();
|
||||
void op_cmp_dp();
|
||||
void op_cpx_dp();
|
||||
void op_cpy_dp();
|
||||
void op_eor_dp();
|
||||
void op_lda_dp();
|
||||
void op_ldx_dp();
|
||||
void op_ldy_dp();
|
||||
void op_ora_dp();
|
||||
void op_sbc_dp();
|
||||
void op_adc_dpx();
|
||||
void op_and_dpx();
|
||||
void op_bit_dpx();
|
||||
void op_cmp_dpx();
|
||||
void op_eor_dpx();
|
||||
void op_lda_dpx();
|
||||
void op_ldy_dpx();
|
||||
void op_ora_dpx();
|
||||
void op_sbc_dpx();
|
||||
void op_ldx_dpy();
|
||||
void op_adc_idp();
|
||||
void op_and_idp();
|
||||
void op_cmp_idp();
|
||||
void op_eor_idp();
|
||||
void op_lda_idp();
|
||||
void op_ora_idp();
|
||||
void op_sbc_idp();
|
||||
void op_adc_idpx();
|
||||
void op_and_idpx();
|
||||
void op_cmp_idpx();
|
||||
void op_eor_idpx();
|
||||
void op_lda_idpx();
|
||||
void op_ora_idpx();
|
||||
void op_sbc_idpx();
|
||||
void op_adc_idpy();
|
||||
void op_and_idpy();
|
||||
void op_cmp_idpy();
|
||||
void op_eor_idpy();
|
||||
void op_lda_idpy();
|
||||
void op_ora_idpy();
|
||||
void op_sbc_idpy();
|
||||
void op_adc_ildp();
|
||||
void op_and_ildp();
|
||||
void op_cmp_ildp();
|
||||
void op_eor_ildp();
|
||||
void op_lda_ildp();
|
||||
void op_ora_ildp();
|
||||
void op_sbc_ildp();
|
||||
void op_adc_ildpy();
|
||||
void op_and_ildpy();
|
||||
void op_cmp_ildpy();
|
||||
void op_eor_ildpy();
|
||||
void op_lda_ildpy();
|
||||
void op_ora_ildpy();
|
||||
void op_sbc_ildpy();
|
||||
void op_adc_sr();
|
||||
void op_and_sr();
|
||||
void op_cmp_sr();
|
||||
void op_eor_sr();
|
||||
void op_lda_sr();
|
||||
void op_ora_sr();
|
||||
void op_sbc_sr();
|
||||
void op_adc_isry();
|
||||
void op_and_isry();
|
||||
void op_cmp_isry();
|
||||
void op_eor_isry();
|
||||
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();
|
||||
void op_dec();
|
||||
void op_dex();
|
||||
void op_dey();
|
||||
void op_asl();
|
||||
void op_lsr();
|
||||
void op_rol();
|
||||
void op_ror();
|
||||
void op_inc_addr();
|
||||
void op_dec_addr();
|
||||
void op_asl_addr();
|
||||
void op_lsr_addr();
|
||||
void op_rol_addr();
|
||||
void op_ror_addr();
|
||||
void op_trb_addr();
|
||||
void op_tsb_addr();
|
||||
void op_inc_addrx();
|
||||
void op_dec_addrx();
|
||||
void op_asl_addrx();
|
||||
void op_lsr_addrx();
|
||||
void op_rol_addrx();
|
||||
void op_ror_addrx();
|
||||
void op_inc_dp();
|
||||
void op_dec_dp();
|
||||
void op_asl_dp();
|
||||
void op_lsr_dp();
|
||||
void op_rol_dp();
|
||||
void op_ror_dp();
|
||||
void op_trb_dp();
|
||||
void op_tsb_dp();
|
||||
void op_inc_dpx();
|
||||
void op_dec_dpx();
|
||||
void op_asl_dpx();
|
||||
void op_lsr_dpx();
|
||||
void op_rol_dpx();
|
||||
void op_ror_dpx();
|
||||
void op_bcc();
|
||||
void op_bcs();
|
||||
void op_bne();
|
||||
void op_beq();
|
||||
void op_bpl();
|
||||
void op_bmi();
|
||||
void op_bvc();
|
||||
void op_bvs();
|
||||
void op_bra();
|
||||
void op_brl();
|
||||
void op_jmp_addr();
|
||||
void op_jmp_long();
|
||||
void op_jmp_iaddr();
|
||||
void op_jmp_iaddrx();
|
||||
void op_jmp_iladdr();
|
||||
void op_jsr_addr();
|
||||
void op_jsr_long();
|
||||
void op_jsr_iaddrx();
|
||||
void op_rti();
|
||||
void op_rts();
|
||||
void op_rtl();
|
||||
void op_nop();
|
||||
void op_wdm();
|
||||
void op_xba();
|
||||
void op_mvn();
|
||||
void op_mvp();
|
||||
void op_brk();
|
||||
void op_cop();
|
||||
void op_stp();
|
||||
void op_wai();
|
||||
void op_xce();
|
||||
void op_clc();
|
||||
void op_cld();
|
||||
void op_cli();
|
||||
void op_clv();
|
||||
void op_sec();
|
||||
void op_sed();
|
||||
void op_sei();
|
||||
void op_rep();
|
||||
void op_sep();
|
||||
void op_tax();
|
||||
void op_tay();
|
||||
void op_txa();
|
||||
void op_txy();
|
||||
void op_tya();
|
||||
void op_tyx();
|
||||
void op_tcd();
|
||||
void op_tcs();
|
||||
void op_tdc();
|
||||
void op_tsc();
|
||||
void op_tsx();
|
||||
void op_txs();
|
||||
void op_pha();
|
||||
void op_phx();
|
||||
void op_phy();
|
||||
void op_phd();
|
||||
void op_phb();
|
||||
void op_phk();
|
||||
void op_php();
|
||||
void op_pla();
|
||||
void op_plx();
|
||||
void op_ply();
|
||||
void op_pld();
|
||||
void op_plb();
|
||||
void op_plp();
|
||||
void op_pea();
|
||||
void op_pei();
|
||||
void op_per();
|
@@ -1,6 +1,6 @@
|
||||
nop(0xea) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
}
|
||||
|
||||
wdm(0x42) {
|
||||
@@ -36,34 +36,33 @@ mvp(0x44, --) {
|
||||
}
|
||||
6:last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
}
|
||||
|
||||
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
|
||||
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
||||
1:op_readpc();
|
||||
2:if(!regs.e)op_writestack(regs.pc.b);
|
||||
2:if(!regs.e) 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);
|
||||
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);
|
||||
rd.h = op_readlong(regs.e ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
while(1) { op_io(); }
|
||||
while(true) op_io();
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
//last_cycle() will set event.wai to false
|
||||
//once an NMI / IRQ edge is reached
|
||||
//last_cycle() will clear event.wai once an NMI / IRQ edge is reached
|
||||
1:event.wai = true;
|
||||
while(event.wai) {
|
||||
last_cycle();
|
||||
@@ -74,8 +73,8 @@ wai(0xcb) {
|
||||
|
||||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
bool carry = regs.p.c;
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
@@ -96,7 +95,7 @@ sec(0x38, regs.p.c = 1),
|
||||
sed(0xf8, regs.p.d = 1),
|
||||
sei(0x78, regs.p.i = 1) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
$1;
|
||||
}
|
||||
|
||||
@@ -106,7 +105,7 @@ sep(0xe2, |=) {
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.p $1 rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
@@ -120,7 +119,7 @@ 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();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l = regs.$3.l;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
@@ -134,7 +133,7 @@ tyx(0xbb, regs.p.x, x, y) {
|
||||
|
||||
tcd(0x5b) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
@@ -142,14 +141,14 @@ tcd(0x5b) {
|
||||
|
||||
tcs(0x1b) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
tdc(0x7b) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
@@ -157,7 +156,7 @@ tdc(0x7b) {
|
||||
|
||||
tsc(0x3b) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
@@ -170,7 +169,7 @@ tsc(0x3b) {
|
||||
|
||||
tsx(0xba) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
@@ -184,7 +183,7 @@ tsx(0xba) {
|
||||
|
||||
txs(0x9a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
@@ -206,7 +205,7 @@ phd(0x0b) {
|
||||
2:op_writestackn(regs.d.h);
|
||||
3:last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
phb(0x8b, regs.db),
|
||||
@@ -243,7 +242,7 @@ pld(0x2b) {
|
||||
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;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
plb(0xab) {
|
||||
@@ -260,7 +259,7 @@ plp(0x28) {
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
@@ -273,7 +272,7 @@ pea(0xf4) {
|
||||
3:op_writestackn(aa.h);
|
||||
4:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
pei(0xd4) {
|
||||
@@ -284,7 +283,7 @@ pei(0xd4) {
|
||||
5:op_writestackn(aa.h);
|
||||
6:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
per(0x62) {
|
||||
@@ -295,5 +294,5 @@ per(0x62) {
|
||||
4:op_writestackn(rd.h);
|
||||
5:last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
@@ -1,14 +1,17 @@
|
||||
void sCPU::op_nop() {
|
||||
//nop
|
||||
case 0xea: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
op_io_irq();
|
||||
} break;
|
||||
|
||||
void sCPU::op_wdm() {
|
||||
//wdm
|
||||
case 0x42: {
|
||||
last_cycle();
|
||||
op_readpc();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_xba() {
|
||||
//xba
|
||||
case 0xeb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_io();
|
||||
@@ -17,9 +20,10 @@ void sCPU::op_xba() {
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_mvn() {
|
||||
//mvn
|
||||
case 0x54: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
@@ -35,10 +39,11 @@ void sCPU::op_mvn() {
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
}
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
void sCPU::op_mvp() {
|
||||
//mvp
|
||||
case 0x44: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
@@ -54,60 +59,64 @@ void sCPU::op_mvp() {
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--)regs.pc.w -= 3;
|
||||
}
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
void sCPU::op_brk() {
|
||||
//brk
|
||||
case 0x00: {
|
||||
op_readpc();
|
||||
if(!regs.e)op_writestack(regs.pc.b);
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong((regs.e) ? 0xfffe : 0xffe6);
|
||||
rd.l = op_readlong(regs.e ? 0xfffe : 0xffe6);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? 0xffff : 0xffe7);
|
||||
rd.h = op_readlong(regs.e ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_cop() {
|
||||
//cop
|
||||
case 0x02: {
|
||||
op_readpc();
|
||||
if(!regs.e)op_writestack(regs.pc.b);
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.p);
|
||||
rd.l = op_readlong((regs.e) ? 0xfff4 : 0xffe4);
|
||||
rd.l = op_readlong(regs.e ? 0xfff4 : 0xffe4);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong((regs.e) ? 0xfff5 : 0xffe5);
|
||||
rd.h = op_readlong(regs.e ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stp() {
|
||||
//stp
|
||||
case 0xdb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
while(1) { op_io(); }
|
||||
}
|
||||
while(true) op_io();
|
||||
} break;
|
||||
|
||||
void sCPU::op_wai() {
|
||||
//last_cycle() will set event.wai to false
|
||||
//once an NMI / IRQ edge is reached
|
||||
//wai
|
||||
case 0xcb: {
|
||||
//last_cycle() will clear event.wai once an NMI / IRQ edge is reached
|
||||
event.wai = true;
|
||||
while(event.wai) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_xce() {
|
||||
//xce
|
||||
case 0xfb: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
bool carry = regs.p.c;
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
@@ -118,77 +127,87 @@ bool carry = regs.p.c;
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_clc() {
|
||||
//clc
|
||||
case 0x18: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.c = 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_cld() {
|
||||
//cld
|
||||
case 0xd8: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.d = 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_cli() {
|
||||
//cli
|
||||
case 0x58: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.i = 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_clv() {
|
||||
//clv
|
||||
case 0xb8: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.v = 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sec() {
|
||||
//sec
|
||||
case 0x38: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.c = 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sed() {
|
||||
//sed
|
||||
case 0xf8: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.d = 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sei() {
|
||||
//sei
|
||||
case 0x78: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.p.i = 1;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_rep() {
|
||||
//rep
|
||||
case 0xc2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p &=~ rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sep() {
|
||||
//sep
|
||||
case 0xe2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p |= rd.l;
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tax() {
|
||||
//tax
|
||||
case 0xaa: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
@@ -198,11 +217,12 @@ void sCPU::op_tax() {
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tay() {
|
||||
//tay
|
||||
case 0xa8: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
@@ -212,11 +232,12 @@ void sCPU::op_tay() {
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_txa() {
|
||||
//txa
|
||||
case 0x8a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
@@ -226,11 +247,12 @@ void sCPU::op_txa() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_txy() {
|
||||
//txy
|
||||
case 0x9b: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
@@ -240,11 +262,12 @@ void sCPU::op_txy() {
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tya() {
|
||||
//tya
|
||||
case 0x98: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
@@ -254,11 +277,12 @@ void sCPU::op_tya() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tyx() {
|
||||
//tyx
|
||||
case 0xbb: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
@@ -268,34 +292,38 @@ void sCPU::op_tyx() {
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tcd() {
|
||||
//tcd
|
||||
case 0x5b: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tcs() {
|
||||
//tcs
|
||||
case 0x1b: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_tdc() {
|
||||
//tdc
|
||||
case 0x7b: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tsc() {
|
||||
//tsc
|
||||
case 0x3b: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
@@ -304,11 +332,12 @@ void sCPU::op_tsc() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_tsx() {
|
||||
//tsx
|
||||
case 0xba: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
@@ -318,66 +347,75 @@ void sCPU::op_tsx() {
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_txs() {
|
||||
//txs
|
||||
case 0x9a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_pha() {
|
||||
//pha
|
||||
case 0x48: {
|
||||
op_io();
|
||||
if(!regs.p.m)op_writestack(regs.a.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.a.l);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_phx() {
|
||||
//phx
|
||||
case 0xda: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.x.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.x.l);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_phy() {
|
||||
//phy
|
||||
case 0x5a: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.y.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.y.l);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_phd() {
|
||||
//phd
|
||||
case 0x0b: {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_phb() {
|
||||
//phb
|
||||
case 0x8b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.db);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_phk() {
|
||||
//phk
|
||||
case 0x4b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.b);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_php() {
|
||||
//php
|
||||
case 0x08: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.p);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_pla() {
|
||||
//pla
|
||||
case 0x68: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
@@ -385,15 +423,16 @@ void sCPU::op_pla() {
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.a.h = op_readstack();
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_plx() {
|
||||
//plx
|
||||
case 0xfa: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
@@ -401,15 +440,16 @@ void sCPU::op_plx() {
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.x.h = op_readstack();
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_ply() {
|
||||
//ply
|
||||
case 0x7a: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
@@ -417,15 +457,16 @@ void sCPU::op_ply() {
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.y.h = op_readstack();
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_pld() {
|
||||
//pld
|
||||
case 0x2b: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
@@ -433,40 +474,44 @@ void sCPU::op_pld() {
|
||||
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;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_plb() {
|
||||
//plb
|
||||
case 0xab: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_plp() {
|
||||
//plp
|
||||
case 0x28: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_pea() {
|
||||
//pea
|
||||
case 0xf4: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_pei() {
|
||||
//pei
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
@@ -474,10 +519,11 @@ void sCPU::op_pei() {
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_per() {
|
||||
//per
|
||||
case 0x62: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
@@ -485,6 +531,6 @@ void sCPU::op_per() {
|
||||
op_writestackn(rd.h);
|
||||
last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
|
@@ -6,7 +6,7 @@ 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();
|
||||
1:if(!$1) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($1) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
@@ -102,7 +102,7 @@ jsr_long(0x22) {
|
||||
7:last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
@@ -115,20 +115,20 @@ jsr_iaddrx(0xfc) {
|
||||
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;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
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();
|
||||
5:if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
@@ -159,5 +159,5 @@ rtl(0x6b) {
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
@@ -1,157 +1,171 @@
|
||||
void sCPU::op_bcc() {
|
||||
if(!!regs.p.c)last_cycle();
|
||||
//bcc
|
||||
case 0x90: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bcs() {
|
||||
if(!regs.p.c)last_cycle();
|
||||
//bcs
|
||||
case 0xb0: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bne() {
|
||||
if(!!regs.p.z)last_cycle();
|
||||
//bne
|
||||
case 0xd0: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_beq() {
|
||||
if(!regs.p.z)last_cycle();
|
||||
//beq
|
||||
case 0xf0: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bpl() {
|
||||
if(!!regs.p.n)last_cycle();
|
||||
//bpl
|
||||
case 0x10: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bmi() {
|
||||
if(!regs.p.n)last_cycle();
|
||||
//bmi
|
||||
case 0x30: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bvc() {
|
||||
if(!!regs.p.v)last_cycle();
|
||||
//bvc
|
||||
case 0x50: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bvs() {
|
||||
if(!regs.p.v)last_cycle();
|
||||
//bvs
|
||||
case 0x70: {
|
||||
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 {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_bra() {
|
||||
//bra
|
||||
case 0x80: {
|
||||
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;
|
||||
|
||||
void sCPU::op_brl() {
|
||||
//brl
|
||||
case 0x82: {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_jmp_addr() {
|
||||
//jmp_addr
|
||||
case 0x4c: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_jmp_long() {
|
||||
//jmp_long
|
||||
case 0x5c: {
|
||||
rd.l = op_readpc();
|
||||
rd.h = op_readpc();
|
||||
last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_jmp_iaddr() {
|
||||
//jmp_iaddr
|
||||
case 0x6c: {
|
||||
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;
|
||||
|
||||
void sCPU::op_jmp_iaddrx() {
|
||||
//jmp_iaddrx
|
||||
case 0x7c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
@@ -159,9 +173,10 @@ void sCPU::op_jmp_iaddrx() {
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_jmp_iladdr() {
|
||||
//jmp_iladdr
|
||||
case 0xdc: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
@@ -169,9 +184,10 @@ void sCPU::op_jmp_iladdr() {
|
||||
last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_jsr_addr() {
|
||||
//jsr_addr
|
||||
case 0x20: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
@@ -180,9 +196,10 @@ void sCPU::op_jsr_addr() {
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_jsr_long() {
|
||||
//jsr_long
|
||||
case 0x22: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
@@ -193,10 +210,11 @@ void sCPU::op_jsr_long() {
|
||||
last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_jsr_iaddrx() {
|
||||
//jsr_iaddrx
|
||||
case 0xfc: {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
@@ -206,31 +224,33 @@ void sCPU::op_jsr_iaddrx() {
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
void sCPU::op_rti() {
|
||||
//rti
|
||||
case 0x40: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e)regs.p |= 0x30;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
rd.l = op_readstack();
|
||||
if(regs.e)last_cycle();
|
||||
if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_rts() {
|
||||
//rts
|
||||
case 0x60: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
@@ -239,9 +259,10 @@ void sCPU::op_rts() {
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_rtl() {
|
||||
//rtl
|
||||
case 0x6b: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
@@ -250,6 +271,6 @@ void sCPU::op_rtl() {
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e)regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
|
@@ -9,7 +9,7 @@ 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();
|
||||
1:if($2) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($2) { op_$1_b(); end; }
|
||||
2:last_cycle();
|
||||
@@ -31,7 +31,7 @@ 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();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
@@ -51,7 +51,7 @@ 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);
|
||||
4:if($2)last_cycle();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
@@ -70,7 +70,7 @@ 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);
|
||||
4:if($2)last_cycle();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
@@ -88,7 +88,7 @@ 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();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
@@ -106,7 +106,7 @@ 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();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
@@ -128,7 +128,7 @@ 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();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
@@ -148,7 +148,7 @@ sbc_dpx(0xf5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2)last_cycle();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
@@ -160,7 +160,7 @@ ldx_dpy(0xb6, ldx, regs.p.x) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2)last_cycle();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
@@ -179,7 +179,7 @@ sbc_idp(0xf2, sbc, regs.p.m) {
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if($2)last_cycle();
|
||||
5:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
6:last_cycle();
|
||||
@@ -199,7 +199,7 @@ sbc_idpx(0xe1, sbc, regs.p.m) {
|
||||
3:op_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();
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
@@ -219,7 +219,7 @@ sbc_idpy(0xf1, sbc, regs.p.m) {
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
6:if($2)last_cycle();
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
@@ -239,7 +239,7 @@ sbc_ildp(0xe7, sbc, regs.p.m) {
|
||||
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();
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
@@ -259,7 +259,7 @@ sbc_ildpy(0xf7, sbc, regs.p.m) {
|
||||
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();
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
@@ -276,7 +276,7 @@ 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();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readsp(sp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
@@ -296,7 +296,7 @@ sbc_isry(0xf3, sbc) {
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m)last_cycle();
|
||||
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();
|
||||
@@ -305,7 +305,7 @@ sbc_isry(0xf3, sbc) {
|
||||
}
|
||||
|
||||
bit_const(0x89) {
|
||||
1:if(regs.p.m)last_cycle();
|
||||
1:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.m) {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ inc(0x1a, regs.p.m, a),
|
||||
inx(0xe8, regs.p.x, x),
|
||||
iny(0xc8, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
@@ -18,7 +18,7 @@ dec(0x3a, regs.p.m, a),
|
||||
dex(0xca, regs.p.x, x),
|
||||
dey(0x88, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
@@ -32,7 +32,7 @@ dey(0x88, regs.p.x, y) {
|
||||
|
||||
asl(0x0a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
@@ -48,7 +48,7 @@ asl(0x0a) {
|
||||
|
||||
lsr(0x4a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
@@ -64,7 +64,7 @@ lsr(0x4a) {
|
||||
|
||||
rol(0x2a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
@@ -83,17 +83,17 @@ rol(0x2a) {
|
||||
|
||||
ror(0x6a) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = (regs.p.c)?0x80:0;
|
||||
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;
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
@@ -113,7 +113,7 @@ tsb_addr(0x0c, tsb) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readdbr(aa.w);
|
||||
4:if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
4:if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
5:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
@@ -132,7 +132,7 @@ 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.p.m)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.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
@@ -152,7 +152,7 @@ tsb_dp(0x04, tsb) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:rd.l = op_readdp(dp);
|
||||
4:if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
4:if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
@@ -171,7 +171,7 @@ ror_dpx(0x76, ror) {
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:rd.l = op_readdp(dp + regs.x.w);
|
||||
5:if(!regs.p.m)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.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
void sCPU::op_inc() {
|
||||
//inc
|
||||
case 0x1a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l++;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
@@ -10,11 +11,12 @@ void sCPU::op_inc() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_inx() {
|
||||
//inx
|
||||
case 0xe8: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l++;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
@@ -24,11 +26,12 @@ void sCPU::op_inx() {
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_iny() {
|
||||
//iny
|
||||
case 0xc8: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l++;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
@@ -38,11 +41,12 @@ void sCPU::op_iny() {
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_dec() {
|
||||
//dec
|
||||
case 0x3a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l--;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
@@ -52,11 +56,12 @@ void sCPU::op_dec() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_dex() {
|
||||
//dex
|
||||
case 0xca: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l--;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
@@ -66,11 +71,12 @@ void sCPU::op_dex() {
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_dey() {
|
||||
//dey
|
||||
case 0x88: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l--;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
@@ -80,11 +86,12 @@ void sCPU::op_dey() {
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_asl() {
|
||||
//asl
|
||||
case 0x0a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
@@ -96,11 +103,12 @@ void sCPU::op_asl() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_lsr() {
|
||||
//lsr
|
||||
case 0x4a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
@@ -112,11 +120,12 @@ void sCPU::op_lsr() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_rol() {
|
||||
//rol
|
||||
case 0x2a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
@@ -131,402 +140,431 @@ void sCPU::op_rol() {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_ror() {
|
||||
//ror
|
||||
case 0x6a: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = (regs.p.c)?0x80:0;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_inc_addr() {
|
||||
//inc_addr
|
||||
case 0xee: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_dec_addr() {
|
||||
//dec_addr
|
||||
case 0xce: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_asl_addr() {
|
||||
//asl_addr
|
||||
case 0x0e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_lsr_addr() {
|
||||
//lsr_addr
|
||||
case 0x4e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_rol_addr() {
|
||||
//rol_addr
|
||||
case 0x2e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_ror_addr() {
|
||||
//ror_addr
|
||||
case 0x6e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_trb_addr() {
|
||||
//trb_addr
|
||||
case 0x1c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_tsb_addr() {
|
||||
//tsb_addr
|
||||
case 0x0c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if(!regs.p.m)rd.h = op_readdbr(aa.w + 1);
|
||||
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_inc_addrx() {
|
||||
//inc_addrx
|
||||
case 0xfe: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_dec_addrx() {
|
||||
//dec_addrx
|
||||
case 0xde: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_asl_addrx() {
|
||||
//asl_addrx
|
||||
case 0x1e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_lsr_addrx() {
|
||||
//lsr_addrx
|
||||
case 0x5e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_rol_addrx() {
|
||||
//rol_addrx
|
||||
case 0x3e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_ror_addrx() {
|
||||
//ror_addrx
|
||||
case 0x7e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_inc_dp() {
|
||||
//inc_dp
|
||||
case 0xe6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_dec_dp() {
|
||||
//dec_dp
|
||||
case 0xc6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_asl_dp() {
|
||||
//asl_dp
|
||||
case 0x06: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_lsr_dp() {
|
||||
//lsr_dp
|
||||
case 0x46: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_rol_dp() {
|
||||
//rol_dp
|
||||
case 0x26: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_ror_dp() {
|
||||
//ror_dp
|
||||
case 0x66: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_trb_dp() {
|
||||
//trb_dp
|
||||
case 0x14: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_tsb_dp() {
|
||||
//tsb_dp
|
||||
case 0x04: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
rd.l = op_readdp(dp);
|
||||
if(!regs.p.m)rd.h = op_readdp(dp + 1);
|
||||
if(!regs.p.m) rd.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
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;
|
||||
|
||||
void sCPU::op_inc_dpx() {
|
||||
//inc_dpx
|
||||
case 0xf6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_dec_dpx() {
|
||||
//dec_dpx
|
||||
case 0xd6: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_asl_dpx() {
|
||||
//asl_dpx
|
||||
case 0x16: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_lsr_dpx() {
|
||||
//lsr_dpx
|
||||
case 0x56: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_rol_dpx() {
|
||||
//rol_dpx
|
||||
case 0x36: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
void sCPU::op_ror_dpx() {
|
||||
//ror_dpx
|
||||
case 0x76: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if(!regs.p.m)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.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;
|
||||
|
||||
|
@@ -4,9 +4,9 @@ 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();
|
||||
3:if($1) last_cycle();
|
||||
op_writedbr(aa.w, $2);
|
||||
if($1)end;
|
||||
if($1) end;
|
||||
4:last_cycle();
|
||||
op_writedbr(aa.w + 1, $2 >> 8);
|
||||
}
|
||||
@@ -16,9 +16,9 @@ stz_addrx(0x9e, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if($1)last_cycle();
|
||||
4:if($1) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, $2);
|
||||
if($1)end;
|
||||
if($1) end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
@@ -27,9 +27,9 @@ sta_addry(0x99) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if(regs.p.m)last_cycle();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
@@ -49,9 +49,9 @@ 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();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -62,9 +62,9 @@ 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();
|
||||
3:if($1) last_cycle();
|
||||
op_writedp(dp, $2);
|
||||
if($1)end;
|
||||
if($1) end;
|
||||
4:last_cycle();
|
||||
op_writedp(dp + 1, $2 >> 8);
|
||||
}
|
||||
@@ -75,9 +75,9 @@ stz_dpx(0x74, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($1)last_cycle();
|
||||
4:if($1) last_cycle();
|
||||
op_writedp(dp + regs.x.w, $2);
|
||||
if($1)end;
|
||||
if($1) end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
@@ -86,9 +86,9 @@ stx_dpy(0x96) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if(regs.p.x)last_cycle();
|
||||
4:if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x)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.p.m)last_cycle();
|
||||
5:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
3:if(regs.p.m) last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m)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.p.m)last_cycle();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)end;
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
@@ -1,266 +1,290 @@
|
||||
void sCPU::op_sta_addr() {
|
||||
//sta_addr
|
||||
case 0x8d: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.w);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stx_addr() {
|
||||
//stx_addr
|
||||
case 0x8e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.x)last_cycle();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedbr(aa.w, regs.x.w);
|
||||
if(regs.p.x)return;
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.x.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sty_addr() {
|
||||
//sty_addr
|
||||
case 0x8c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.x)last_cycle();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedbr(aa.w, regs.y.w);
|
||||
if(regs.p.x)return;
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.y.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stz_addr() {
|
||||
//stz_addr
|
||||
case 0x9c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, 0x0000);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, 0x0000 >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_addrx() {
|
||||
//sta_addrx
|
||||
case 0x9d: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stz_addrx() {
|
||||
//stz_addrx
|
||||
case 0x9e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, 0x0000);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_addry() {
|
||||
//sta_addry
|
||||
case 0x99: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_long() {
|
||||
//sta_long
|
||||
case 0x8f: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_longx() {
|
||||
//sta_longx
|
||||
case 0x9f: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_dp() {
|
||||
//sta_dp
|
||||
case 0x85: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp, regs.a.w);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.a.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stx_dp() {
|
||||
//stx_dp
|
||||
case 0x86: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.x)last_cycle();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp, regs.x.w);
|
||||
if(regs.p.x)return;
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.x.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sty_dp() {
|
||||
//sty_dp
|
||||
case 0x84: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.x)last_cycle();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp, regs.y.w);
|
||||
if(regs.p.x)return;
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.y.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stz_dp() {
|
||||
//stz_dp
|
||||
case 0x64: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp, 0x0000);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, 0x0000 >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_dpx() {
|
||||
//sta_dpx
|
||||
case 0x95: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.a.w);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sty_dpx() {
|
||||
//sty_dpx
|
||||
case 0x94: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.y.w);
|
||||
if(regs.p.x)return;
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stz_dpx() {
|
||||
//stz_dpx
|
||||
case 0x74: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp + regs.x.w, 0x0000);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_stx_dpy() {
|
||||
//stx_dpy
|
||||
case 0x96: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x)return;
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_idp() {
|
||||
//sta_idp
|
||||
case 0x92: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_ildp() {
|
||||
//sta_ildp
|
||||
case 0x87: {
|
||||
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.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_idpx() {
|
||||
//sta_idpx
|
||||
case 0x81: {
|
||||
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.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_idpy() {
|
||||
//sta_idpy
|
||||
case 0x91: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_ildpy() {
|
||||
//sta_ildpy
|
||||
case 0x97: {
|
||||
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.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_sr() {
|
||||
//sta_sr
|
||||
case 0x83: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
void sCPU::op_sta_isry() {
|
||||
//sta_isry
|
||||
case 0x93: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
aa.l = op_readsp(sp);
|
||||
aa.h = op_readsp(sp + 1);
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m)return;
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@@ -1,206 +1,202 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//op_read
|
||||
inline void sCPU::op_adc_b() {
|
||||
int32 r = regs.a.l + rd.l + regs.p.c;
|
||||
int 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;
|
||||
n0 += (rd.l & 15) + regs.p.c;
|
||||
if(n0 > 9) {
|
||||
n0 -= 10;
|
||||
n0 &= 15;
|
||||
n0 = (n0 - 10) & 15;
|
||||
n1++;
|
||||
}
|
||||
n1 += ((rd.l >> 4) & 15);
|
||||
if(n1 > 9) {
|
||||
n1 -= 10;
|
||||
n1 &= 15;
|
||||
n1 = (n1 - 10) & 15;
|
||||
regs.p.c = 1;
|
||||
} else {
|
||||
regs.p.c = 0;
|
||||
}
|
||||
r = (n1 << 4) | (n0);
|
||||
r = (n1 << 4) | n0;
|
||||
} else {
|
||||
r = regs.a.l + rd.l + regs.p.c;
|
||||
regs.p.c = (r > 0xff);
|
||||
regs.p.c = r > 0xff;
|
||||
}
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.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 sCPU::op_adc_w() {
|
||||
int32 r;
|
||||
int 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;
|
||||
n0 += (rd.w & 15) + regs.p.c;
|
||||
if(n0 > 9) {
|
||||
n0 -= 10;
|
||||
n0 &= 15;
|
||||
n0 = (n0 - 10) & 15;
|
||||
n1++;
|
||||
}
|
||||
n1 += ((rd.w >> 4) & 15);
|
||||
if(n1 > 9) {
|
||||
n1 -= 10;
|
||||
n1 &= 15;
|
||||
n1 = (n1 - 10) & 15;
|
||||
n2++;
|
||||
}
|
||||
n2 += ((rd.w >> 8) & 15);
|
||||
if(n2 > 9) {
|
||||
n2 -= 10;
|
||||
n2 &= 15;
|
||||
n2 = (n2 - 10) & 15;
|
||||
n3++;
|
||||
}
|
||||
n3 += ((rd.w >> 12) & 15);
|
||||
if(n3 > 9) {
|
||||
n3 -= 10;
|
||||
n3 &= 15;
|
||||
n3 = (n3 - 10) & 15;
|
||||
regs.p.c = 1;
|
||||
} else {
|
||||
regs.p.c = 0;
|
||||
}
|
||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
||||
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.c = r > 0xffff;
|
||||
}
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.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 = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
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 = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
regs.p.n = regs.a.w & 0x8000;
|
||||
regs.p.z = regs.a.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_b() {
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.v = !!(rd.l & 0x40);
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
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 = !!(rd.w & 0x8000);
|
||||
regs.p.v = !!(rd.w & 0x4000);
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
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 = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
int r = regs.a.l - rd.l;
|
||||
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 = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
int r = regs.a.w - rd.w;
|
||||
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 = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
int r = regs.x.l - rd.l;
|
||||
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 = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
int r = regs.x.w - rd.w;
|
||||
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 = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
int r = regs.y.l - rd.l;
|
||||
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 = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
int r = regs.y.w - rd.w;
|
||||
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 = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
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 = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
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 = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
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 = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
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 = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
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 = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
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 = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
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 = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
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 = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
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 = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
regs.p.n = regs.a.w & 0x8000;
|
||||
regs.p.z = regs.a.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_sbc_b() {
|
||||
int32 r;
|
||||
int r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.l ) & 15;
|
||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||
@@ -219,16 +215,16 @@ int32 r;
|
||||
r = (n1 << 4) | (n0);
|
||||
} else {
|
||||
r = regs.a.l - rd.l - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
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.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 sCPU::op_sbc_w() {
|
||||
int32 r;
|
||||
int r;
|
||||
if(regs.p.d) {
|
||||
uint8 n0 = (regs.a.w ) & 15;
|
||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||
@@ -259,115 +255,117 @@ int32 r;
|
||||
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.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.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 sCPU::op_inc_b() {
|
||||
rd.l++;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_inc_w() {
|
||||
rd.w++;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_b() {
|
||||
rd.l--;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_w() {
|
||||
rd.w--;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_b() {
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
regs.p.c = rd.l & 0x80;
|
||||
rd.l <<= 1;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_w() {
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
regs.p.c = rd.w & 0x8000;
|
||||
rd.w <<= 1;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
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 = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
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 = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_b() {
|
||||
uint16 carry = (uint16)regs.p.c;
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
unsigned carry = (unsigned)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);
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_w() {
|
||||
uint16 carry = (uint16)regs.p.c;
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
unsigned carry = (unsigned)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);
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_b() {
|
||||
uint16 carry = (uint16)regs.p.c << 7;
|
||||
unsigned carry = (unsigned)regs.p.c << 7;
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l = carry | (rd.l >> 1);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
regs.p.n = rd.l & 0x80;
|
||||
regs.p.z = rd.l == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_w() {
|
||||
uint16 carry = (uint16)regs.p.c << 15;
|
||||
unsigned carry = (unsigned)regs.p.c << 15;
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w = carry | (rd.w >> 1);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
regs.p.n = rd.w & 0x8000;
|
||||
regs.p.z = rd.w == 0;
|
||||
}
|
||||
|
||||
inline void sCPU::op_trb_b() {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||
rd.l &= ~regs.a.l;
|
||||
}
|
||||
|
||||
inline void sCPU::op_trb_w() {
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||
rd.w &= ~regs.a.w;
|
||||
}
|
||||
|
||||
inline void sCPU::op_tsb_b() {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||
rd.l |= regs.a.l;
|
||||
}
|
||||
|
||||
inline void sCPU::op_tsb_w() {
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||
rd.w |= regs.a.w;
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,256 +0,0 @@
|
||||
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,18 +1,12 @@
|
||||
#define CLASS_NAME "sCPU"
|
||||
#include "../../../lib/opgen_so.cpp"
|
||||
#include <tool/opgen_switch.cpp>
|
||||
|
||||
int main() {
|
||||
fph = fopen("op.h", "wb");
|
||||
fpt = fopen("optable.cpp", "wb");
|
||||
|
||||
generate("op_read.cpp", "op_read.b");
|
||||
generate("op_write.cpp", "op_write.b");
|
||||
generate("op_rmw.cpp", "op_rmw.b");
|
||||
generate("op_pc.cpp", "op_pc.b");
|
||||
generate("op_misc.cpp", "op_misc.b");
|
||||
|
||||
fclose(fph);
|
||||
fclose(fpt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,40 +1,55 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
void sCPU::dma_add_clocks(uint clocks) {
|
||||
status.dma_clocks += clocks;
|
||||
add_clocks(clocks);
|
||||
}
|
||||
|
||||
/*****
|
||||
* used by both DMA and HDMA
|
||||
*
|
||||
* DMA address bus A cannot read from or write to the following addresses :
|
||||
* $[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>
|
||||
* WRAM<>WRAM transfers via $2180
|
||||
*****/
|
||||
bool sCPU::dma_addr_valid(uint32 abus) {
|
||||
//reads from B-bus or S-CPU registers are invalid
|
||||
if((abus & 0x40ff00) == 0x2100) return false; //$[00-3f|80-bf]:[2100-21ff]
|
||||
if((abus & 0x40fe00) == 0x4000) return false; //$[00-3f|80-bf]:[4000-41ff]
|
||||
if((abus & 0x40ffe0) == 0x4200) return false; //$[00-3f|80-bf]:[4200-421f]
|
||||
if((abus & 0x40ff80) == 0x4300) return false; //$[00-3f|80-bf]:[4300-437f]
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 sCPU::dma_read(uint32 abus) {
|
||||
if(dma_addr_valid(abus) == false) return 0x00; //does not return S-CPU MDR
|
||||
return bus.read(abus);
|
||||
}
|
||||
|
||||
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
|
||||
uint8 r;
|
||||
if(direction == 0) { //a->b
|
||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
||||
r = regs.mdr;
|
||||
if(direction == 0) {
|
||||
//a->b transfer (to $21xx)
|
||||
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||
//illegal WRAM->WRAM transfer (bus conflict)
|
||||
//read most likely occurs; no write occurs
|
||||
//read is irrelevent, as it cannot be observed by software
|
||||
dma_add_clocks(8);
|
||||
} else {
|
||||
r = bus.read(abus);
|
||||
dma_add_clocks(4);
|
||||
uint8 data = dma_read(abus);
|
||||
dma_add_clocks(4);
|
||||
bus.write(0x2100 | bbus, data);
|
||||
}
|
||||
bus.write(0x2100 | bbus, r);
|
||||
} else { //b->a
|
||||
if(bbus == 0x80 && ((abus & 0x7e0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||
//prevent WRAM->WRAM transfers
|
||||
r = regs.mdr;
|
||||
} else {
|
||||
r = bus.read(0x2100 | bbus);
|
||||
//b->a transfer (from $21xx)
|
||||
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||
//illegal WRAM->WRAM transfer (bus conflict)
|
||||
//no read occurs; write does occur
|
||||
dma_add_clocks(8);
|
||||
bus.write(abus, 0x00); //does not write S-CPU MDR
|
||||
} else {
|
||||
dma_add_clocks(4);
|
||||
uint8 data = bus.read(0x2100 | bbus);
|
||||
dma_add_clocks(4);
|
||||
if(dma_addr_valid(abus) == true) {
|
||||
bus.write(abus, data);
|
||||
}
|
||||
}
|
||||
if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300 ||
|
||||
(abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c)return;
|
||||
bus.write(abus, r);
|
||||
}
|
||||
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
@@ -43,21 +58,20 @@ uint8 r;
|
||||
*****/
|
||||
|
||||
uint8 sCPU::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]
|
||||
switch(channel[i].xfermode) { default:
|
||||
case 0: return (channel[i].destaddr); //0
|
||||
case 1: return (channel[i].destaddr + (index & 1)); //0,1
|
||||
case 2: return (channel[i].destaddr); //0,0
|
||||
case 3: return (channel[i].destaddr + ((index >> 1) & 1)); //0,0,1,1
|
||||
case 4: return (channel[i].destaddr + (index & 3)); //0,1,2,3
|
||||
case 5: return (channel[i].destaddr + (index & 1)); //0,1,0,1
|
||||
case 6: return (channel[i].destaddr); //0,0 [2]
|
||||
case 7: return (channel[i].destaddr + ((index >> 1) & 1)); //0,0,1,1 [3]
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32 sCPU::dma_addr(uint8 i) {
|
||||
uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||
uint32 r = (channel[i].srcbank << 16) | (channel[i].srcaddr);
|
||||
|
||||
if(channel[i].fixedxfer == false) {
|
||||
if(channel[i].reversexfer == false) {
|
||||
@@ -97,7 +111,7 @@ void sCPU::dma_transfertobusa(uint8 i, uint8 bbus) {
|
||||
}
|
||||
|
||||
inline void sCPU::dma_write(uint8 i, uint8 index) {
|
||||
//cannot use dma_transfer() directly, due to current S-DD1 implementation
|
||||
//cannot use dma_transfer() directly, due to current S-DD1 implementation
|
||||
if(channel[i].direction == 0) {
|
||||
dma_transfertobusb(i, index);
|
||||
} else {
|
||||
@@ -105,10 +119,22 @@ inline void sCPU::dma_write(uint8 i, uint8 index) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8 sCPU::dma_enabled_channels() {
|
||||
uint8 r = 0;
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(channel[i].dma_enabled) r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void sCPU::dma_run() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].dma_enabled == false)continue;
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(channel[i].dma_enabled == false) continue;
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
|
||||
if(cartridge.info.sdd1 == true) {
|
||||
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
|
||||
@@ -123,7 +149,7 @@ void sCPU::dma_run() {
|
||||
channel[i].xfersize, channel[i].xfersize ? channel[i].xfersize : 65536);
|
||||
}
|
||||
|
||||
uint index = 0;
|
||||
unsigned index = 0;
|
||||
do {
|
||||
dma_write(i, dma_bbus(i, index++));
|
||||
} while(channel[i].dma_enabled && channel[i].xfersize);
|
||||
@@ -143,72 +169,73 @@ inline bool sCPU::hdma_active(uint8 i) {
|
||||
}
|
||||
|
||||
inline bool sCPU::hdma_active_after(uint8 i) {
|
||||
for(int n = i + 1; n < 8; n++) {
|
||||
if(hdma_active(n) == true) { return true; }
|
||||
for(unsigned n = i + 1; n < 8; n++) {
|
||||
if(hdma_active(n) == true) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline uint8 sCPU::hdma_enabled_channels() {
|
||||
uint8 r = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].hdma_enabled)r++;
|
||||
uint8 r = 0;
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(channel[i].hdma_enabled) r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
inline uint8 sCPU::hdma_active_channels() {
|
||||
uint8 r = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(hdma_active(i) == true)r++;
|
||||
uint8 r = 0;
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(hdma_active(i) == true) r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void sCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = bus.read(hdma_addr(i));
|
||||
channel[i].hdma_line_counter = dma_read(hdma_addr(i));
|
||||
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 = bus.read(hdma_addr(i)) << 8;
|
||||
channel[i].hdma_iaddr = dma_read(hdma_addr(i)) << 8;
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= bus.read(hdma_addr(i)) << 8;
|
||||
channel[i].hdma_iaddr |= dma_read(hdma_addr(i)) << 8;
|
||||
dma_add_clocks(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::hdma_run() {
|
||||
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
|
||||
dma_add_clocks(8);
|
||||
|
||||
for(unsigned 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
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
for(int index = 0; index < xferlen; index++) {
|
||||
if(bool(config::cpu.hdma_enable) == true) {
|
||||
dma_transfer(channel[i].direction, dma_bbus(i, index),
|
||||
!channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i));
|
||||
} else {
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
static const unsigned transfer_length[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
unsigned length = transfer_length[channel[i].xfermode];
|
||||
for(unsigned index = 0; index < length; index++) {
|
||||
unsigned addr = !channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i);
|
||||
dma_transfer(channel[i].direction, dma_bbus(i, index), addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(hdma_active(i) == false) continue;
|
||||
|
||||
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);
|
||||
} else {
|
||||
dma_add_clocks(8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,15 +243,17 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||
}
|
||||
|
||||
void sCPU::hdma_init_reset() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
channel[i].hdma_completed = false;
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::hdma_init() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(!channel[i].hdma_enabled)continue;
|
||||
dma_add_clocks(8);
|
||||
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
if(!channel[i].hdma_enabled) continue;
|
||||
channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer
|
||||
|
||||
channel[i].hdma_addr = channel[i].srcaddr;
|
||||
@@ -239,7 +268,7 @@ void sCPU::hdma_init() {
|
||||
*****/
|
||||
|
||||
void sCPU::dma_power() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
channel[i].dmap = 0xff;
|
||||
channel[i].direction = 1;
|
||||
channel[i].hdma_indirect = true;
|
||||
@@ -263,7 +292,7 @@ void sCPU::dma_power() {
|
||||
}
|
||||
|
||||
void sCPU::dma_reset() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
channel[i].dma_enabled = false;
|
||||
channel[i].hdma_enabled = false;
|
||||
|
||||
@@ -271,3 +300,5 @@ void sCPU::dma_reset() {
|
||||
channel[i].hdma_do_transfer = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,11 +1,11 @@
|
||||
struct {
|
||||
//$420b
|
||||
struct {
|
||||
//$420b
|
||||
bool dma_enabled;
|
||||
|
||||
//$420c
|
||||
//$420c
|
||||
bool hdma_enabled;
|
||||
|
||||
//$43x0
|
||||
//$43x0
|
||||
uint8 dmap;
|
||||
bool direction;
|
||||
bool hdma_indirect;
|
||||
@@ -13,39 +13,41 @@ struct {
|
||||
bool fixedxfer;
|
||||
uint8 xfermode;
|
||||
|
||||
//$43x1
|
||||
//$43x1
|
||||
uint8 destaddr;
|
||||
|
||||
//$43x2-$43x3
|
||||
//$43x2-$43x3
|
||||
uint16 srcaddr;
|
||||
|
||||
//$43x4
|
||||
//$43x4
|
||||
uint8 srcbank;
|
||||
|
||||
//$43x5-$43x6
|
||||
//$43x5-$43x6
|
||||
union {
|
||||
uint16 xfersize;
|
||||
uint16 hdma_iaddr;
|
||||
};
|
||||
|
||||
//$43x7
|
||||
//$43x7
|
||||
uint8 hdma_ibank;
|
||||
|
||||
//$43x8-$43x9
|
||||
//$43x8-$43x9
|
||||
uint16 hdma_addr;
|
||||
|
||||
//$43xa
|
||||
//$43xa
|
||||
uint8 hdma_line_counter;
|
||||
|
||||
//$43xb/$43xf
|
||||
//$43xb/$43xf
|
||||
uint8 unknown;
|
||||
|
||||
//internal variables
|
||||
//internal variables
|
||||
bool hdma_completed;
|
||||
bool hdma_do_transfer;
|
||||
} channel[8];
|
||||
} channel[8];
|
||||
|
||||
void dma_add_clocks(uint clocks);
|
||||
bool dma_addr_valid(uint32 abus);
|
||||
uint8 dma_read(uint32 abus);
|
||||
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
||||
|
||||
uint8 dma_bbus(uint8 i, uint8 index);
|
||||
@@ -56,6 +58,7 @@ struct {
|
||||
void dma_transfertobusb(uint8 i, uint8 bbus);
|
||||
void dma_transfertobusa(uint8 i, uint8 bbus);
|
||||
void dma_write(uint8 i, uint8 index);
|
||||
uint8 dma_enabled_channels();
|
||||
void dma_run();
|
||||
|
||||
bool hdma_active(uint8 i);
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
/*****
|
||||
* These 3 functions control bus timing for the CPU.
|
||||
* cpu_io is an I/O cycle, and always 6 clock cycles long.
|
||||
@@ -119,3 +121,5 @@ alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
|
||||
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
|
||||
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,18 +1,18 @@
|
||||
/*****
|
||||
/*****
|
||||
* CPU<>APU communication ports
|
||||
*****/
|
||||
uint8 apu_port[4];
|
||||
uint8 port_read (uint8 port) { return apu_port[port & 3]; }
|
||||
uint8 apu_port[4];
|
||||
uint8 port_read(uint8 port) { return apu_port[port & 3]; }
|
||||
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
|
||||
|
||||
/*****
|
||||
/*****
|
||||
* core CPU bus functions
|
||||
*****/
|
||||
void op_io();
|
||||
uint8 op_read (uint32 addr);
|
||||
uint8 op_read(uint32 addr);
|
||||
void op_write(uint32 addr, uint8 data);
|
||||
|
||||
/*****
|
||||
/*****
|
||||
* helper memory addressing functions used by CPU core
|
||||
*****/
|
||||
uint8 op_readpc ();
|
||||
|
@@ -1,10 +1,11 @@
|
||||
uint8 sCPU::pio_status() {
|
||||
return status.pio;
|
||||
}
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
uint8 sCPU::pio() { return status.pio; }
|
||||
bool sCPU::joylatch() { return status.joypad_strobe_latch; }
|
||||
|
||||
//WMDATA
|
||||
uint8 sCPU::mmio_r2180() {
|
||||
uint8 r = bus.read(0x7e0000 | status.wram_addr);
|
||||
uint8 r = bus.read(0x7e0000 | status.wram_addr);
|
||||
status.wram_addr = (status.wram_addr + 1) & 0x01ffff;
|
||||
return r;
|
||||
}
|
||||
@@ -41,7 +42,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
||||
status.joypad_strobe_latch = !!(data & 1);
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
snes.poll_input();
|
||||
snes.input.poll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +53,8 @@ void sCPU::mmio_w4016(uint8 data) {
|
||||
//TODO: test whether strobe latch of zero returns
|
||||
//realtime or buffered status of joypadN.b
|
||||
uint8 sCPU::mmio_r4016() {
|
||||
uint8 r = regs.mdr & 0xfc;
|
||||
r |= (uint8)snes.port_read(0);
|
||||
uint8 r = regs.mdr & 0xfc;
|
||||
r |= snes.input.port_read(0) & 3;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -62,8 +63,8 @@ uint8 r = regs.mdr & 0xfc;
|
||||
//4-2 = Always 1 (pins are connected to GND)
|
||||
//1-0 = Joypad serial data
|
||||
uint8 sCPU::mmio_r4017() {
|
||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||
r |= (uint8)snes.port_read(1);
|
||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||
r |= snes.input.port_read(1) & 3;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -141,19 +142,16 @@ void sCPU::mmio_w420a(uint8 data) {
|
||||
|
||||
//DMAEN
|
||||
void sCPU::mmio_w420b(uint8 data) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].dma_enabled = !!(data & (1 << i));
|
||||
}
|
||||
if(data) {
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
status.dma_pending = true;
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
channel[i].dma_enabled = data & (1 << i);
|
||||
}
|
||||
if(data) status.dma_pending = true;
|
||||
}
|
||||
|
||||
//HDMAEN
|
||||
void sCPU::mmio_w420c(uint8 data) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
channel[i].hdma_enabled = !!(data & (1 << i));
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
channel[i].hdma_enabled = data & (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +165,7 @@ void sCPU::mmio_w420d(uint8 data) {
|
||||
//6-4 = MDR
|
||||
//3-0 = CPU (5a22) version
|
||||
uint8 sCPU::mmio_r4210() {
|
||||
uint8 r = (regs.mdr & 0x70);
|
||||
uint8 r = (regs.mdr & 0x70);
|
||||
r |= (uint8)(rdnmi()) << 7;
|
||||
r |= (cpu_version & 0x0f);
|
||||
return r;
|
||||
@@ -177,7 +175,7 @@ uint8 r = (regs.mdr & 0x70);
|
||||
//7 = IRQ acknowledge
|
||||
//6-0 = MDR
|
||||
uint8 sCPU::mmio_r4211() {
|
||||
uint8 r = (regs.mdr & 0x7f);
|
||||
uint8 r = (regs.mdr & 0x7f);
|
||||
r |= (uint8)(timeup()) << 7;
|
||||
return r;
|
||||
}
|
||||
@@ -188,16 +186,16 @@ uint8 r = (regs.mdr & 0x7f);
|
||||
//5-1 = MDR
|
||||
//0 = JOYPAD acknowledge
|
||||
uint8 sCPU::mmio_r4212() {
|
||||
uint8 r = (regs.mdr & 0x3e);
|
||||
uint16 vs = !overscan() ? 225 : 240;
|
||||
uint8 r = (regs.mdr & 0x3e);
|
||||
uint16 vs = ppu.overscan() == false ? 225 : 240;
|
||||
|
||||
//auto joypad polling
|
||||
//auto joypad polling
|
||||
if(status.vcounter >= vs && status.vcounter <= (vs + 2))r |= 0x01;
|
||||
|
||||
//hblank
|
||||
if(status.hclock <= 2 || status.hclock >= 1096)r |= 0x40;
|
||||
//hblank
|
||||
if(status.hcounter <= 2 || status.hcounter >= 1096)r |= 0x40;
|
||||
|
||||
//vblank
|
||||
//vblank
|
||||
if(status.vcounter >= vs)r |= 0x80;
|
||||
|
||||
return r;
|
||||
@@ -375,40 +373,40 @@ void sCPU::mmio_power() {
|
||||
}
|
||||
|
||||
void sCPU::mmio_reset() {
|
||||
//$2181-$2183
|
||||
//$2181-$2183
|
||||
status.wram_addr = 0x000000;
|
||||
|
||||
//$4016-$4017
|
||||
//$4016-$4017
|
||||
status.joypad_strobe_latch = 0;
|
||||
status.joypad1_bits = ~0;
|
||||
status.joypad2_bits = ~0;
|
||||
|
||||
//$4200
|
||||
//$4200
|
||||
status.nmi_enabled = false;
|
||||
status.hirq_enabled = false;
|
||||
status.virq_enabled = false;
|
||||
status.auto_joypad_poll = false;
|
||||
|
||||
//$4201
|
||||
//$4201
|
||||
status.pio = 0xff;
|
||||
|
||||
//$4202-$4203
|
||||
//$4202-$4203
|
||||
status.mul_a = 0xff;
|
||||
status.mul_b = 0xff;
|
||||
|
||||
//$4204-$4206
|
||||
//$4204-$4206
|
||||
status.div_a = 0xffff;
|
||||
status.div_b = 0xff;
|
||||
|
||||
//$4207-$420a
|
||||
//$4207-$420a
|
||||
status.hirq_pos = 0x01ff;
|
||||
status.virq_pos = 0x01ff;
|
||||
|
||||
//$4214-$4217
|
||||
//$4214-$4217
|
||||
status.r4214 = 0x0000;
|
||||
status.r4216 = 0x0000;
|
||||
|
||||
//$4218-$421f
|
||||
//$4218-$421f
|
||||
status.joy1l = 0x00;
|
||||
status.joy1h = 0x00;
|
||||
status.joy2l = 0x00;
|
||||
@@ -422,13 +420,13 @@ void sCPU::mmio_reset() {
|
||||
uint8 sCPU::mmio_read(uint addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
//APU
|
||||
//APU
|
||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||
scheduler.sync_cpusmp();
|
||||
return smp.port_read(addr & 3);
|
||||
}
|
||||
|
||||
//DMA
|
||||
//DMA
|
||||
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
||||
uint i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
@@ -479,14 +477,14 @@ uint8 sCPU::mmio_read(uint addr) {
|
||||
void sCPU::mmio_write(uint addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
//APU
|
||||
//APU
|
||||
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
|
||||
scheduler.sync_cpusmp();
|
||||
port_write(addr & 3, data);
|
||||
return;
|
||||
}
|
||||
|
||||
//DMA
|
||||
//DMA
|
||||
if((addr & 0xff80) == 0x4300) { //$4300-$437f
|
||||
uint i = (addr >> 4) & 7;
|
||||
switch(addr & 0xf) {
|
||||
@@ -532,3 +530,5 @@ void sCPU::mmio_write(uint addr, uint8 data) {
|
||||
case 0x420d: mmio_w420d(data); return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,9 +1,10 @@
|
||||
void mmio_power();
|
||||
void mmio_reset();
|
||||
uint8 mmio_read (uint addr);
|
||||
uint8 mmio_read(uint addr);
|
||||
void mmio_write(uint addr, uint8 data);
|
||||
|
||||
uint8 pio_status();
|
||||
uint8 pio();
|
||||
bool joylatch();
|
||||
|
||||
uint8 mmio_r2180();
|
||||
uint8 mmio_r4016();
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../../base.h"
|
||||
#define SCPU_CPP
|
||||
|
||||
#include "core/core.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
@@ -7,8 +8,6 @@
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
void sCPU::power() {
|
||||
status.region = (bool)snes.region();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
|
||||
@@ -24,7 +23,7 @@ void sCPU::reset() {
|
||||
regs.pc.l = bus.read(0xfffc);
|
||||
regs.pc.h = bus.read(0xfffd);
|
||||
|
||||
//note: some registers are not fully reset by SNES
|
||||
//note: some registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
@@ -49,7 +48,6 @@ void sCPU::reset() {
|
||||
}
|
||||
|
||||
sCPU::sCPU() {
|
||||
#include "core/optable.cpp"
|
||||
}
|
||||
|
||||
sCPU::~sCPU() {
|
||||
|
@@ -1,26 +1,27 @@
|
||||
class sCPU : public CPU { public:
|
||||
class sCPU : public CPU {
|
||||
public:
|
||||
void enter();
|
||||
|
||||
#include "core/core.h"
|
||||
#include "dma/dma.h"
|
||||
#include "memory/memory.h"
|
||||
#include "mmio/mmio.h"
|
||||
#include "timing/timing.h"
|
||||
#include "core/core.h"
|
||||
#include "dma/dma.h"
|
||||
#include "memory/memory.h"
|
||||
#include "mmio/mmio.h"
|
||||
#include "timing/timing.h"
|
||||
|
||||
struct {
|
||||
struct {
|
||||
bool wai;
|
||||
bool irq;
|
||||
uint16 irq_vector;
|
||||
} event;
|
||||
} event;
|
||||
|
||||
struct {
|
||||
uint nmi_hold;
|
||||
uint irq_hold;
|
||||
struct {
|
||||
unsigned nmi_hold;
|
||||
unsigned irq_hold;
|
||||
|
||||
uint nmi_fire;
|
||||
uint irq_fire;
|
||||
uint irq_delay;
|
||||
uint hw_math;
|
||||
unsigned nmi_fire;
|
||||
unsigned irq_fire;
|
||||
unsigned irq_delay;
|
||||
unsigned hw_math;
|
||||
|
||||
alwaysinline void set(uint &ctr, uint clocks) {
|
||||
if(clocks >= ctr) { ctr = clocks; }
|
||||
@@ -33,31 +34,20 @@ struct {
|
||||
ctr = 0;
|
||||
}
|
||||
}
|
||||
} counter;
|
||||
} counter;
|
||||
|
||||
enum {
|
||||
DMASTATE_INACTIVE,
|
||||
DMASTATE_DMASYNC,
|
||||
DMASTATE_RUN,
|
||||
DMASTATE_CPUSYNC,
|
||||
};
|
||||
enum DMA_State { DMA_Inactive, DMA_Run, DMA_CPUsync };
|
||||
|
||||
struct {
|
||||
//core
|
||||
struct {
|
||||
//core
|
||||
uint8 opcode;
|
||||
bool in_opcode;
|
||||
|
||||
uint clock_count;
|
||||
unsigned clock_count;
|
||||
|
||||
//timing
|
||||
bool region;
|
||||
uint16 region_scanlines;
|
||||
uint16 vcounter, hcounter, hclock;
|
||||
bool interlace, interlace_field;
|
||||
bool overscan;
|
||||
//timing
|
||||
uint16 vcounter, hcounter;
|
||||
uint16 field_lines, line_clocks;
|
||||
uint16 prev_field_lines, prev_line_clocks;
|
||||
uint16 vblstart;
|
||||
|
||||
bool line_rendered;
|
||||
uint16 line_render_position;
|
||||
@@ -72,7 +62,6 @@ struct {
|
||||
|
||||
uint16 irq_delay;
|
||||
|
||||
uint16 vnmi_trigger_pos;
|
||||
bool nmi_valid;
|
||||
bool nmi_line;
|
||||
bool nmi_transition;
|
||||
@@ -84,52 +73,52 @@ struct {
|
||||
bool irq_transition;
|
||||
bool irq_pending;
|
||||
|
||||
//dma
|
||||
uint dma_counter;
|
||||
uint dma_clocks;
|
||||
uint dma_state;
|
||||
//dma
|
||||
unsigned dma_counter;
|
||||
unsigned dma_clocks;
|
||||
bool dma_pending;
|
||||
bool hdma_pending;
|
||||
bool hdmainit_pending;
|
||||
bool hdma_mode; //0 = init, 1 = run
|
||||
DMA_State dma_state;
|
||||
|
||||
//mmio
|
||||
//mmio
|
||||
|
||||
//$2181-$2183
|
||||
//$2181-$2183
|
||||
uint32 wram_addr;
|
||||
|
||||
//$4016-$4017
|
||||
//$4016-$4017
|
||||
bool joypad_strobe_latch;
|
||||
uint32 joypad1_bits;
|
||||
uint32 joypad2_bits;
|
||||
|
||||
//$4200
|
||||
//$4200
|
||||
bool nmi_enabled;
|
||||
bool hirq_enabled, virq_enabled;
|
||||
bool auto_joypad_poll;
|
||||
|
||||
//$4201
|
||||
//$4201
|
||||
uint8 pio;
|
||||
|
||||
//$4202-$4203
|
||||
//$4202-$4203
|
||||
uint8 mul_a, mul_b;
|
||||
|
||||
//$4204-$4206
|
||||
//$4204-$4206
|
||||
uint16 div_a;
|
||||
uint8 div_b;
|
||||
|
||||
//$4207-$420a
|
||||
//$4207-$420a
|
||||
uint16 hirq_pos, virq_pos;
|
||||
|
||||
//$4214-$4217
|
||||
//$4214-$4217
|
||||
uint16 r4214;
|
||||
uint16 r4216;
|
||||
|
||||
//$4218-$421f
|
||||
//$4218-$421f
|
||||
uint8 joy1l, joy1h;
|
||||
uint8 joy2l, joy2h;
|
||||
uint8 joy3l, joy3h;
|
||||
uint8 joy4l, joy4h;
|
||||
} status;
|
||||
} status;
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
@@ -1,60 +1,137 @@
|
||||
#include "irqtiming.cpp"
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
void sCPU::update_interrupts() {
|
||||
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() {
|
||||
uint16_t vpos, hpos;
|
||||
|
||||
//NMI hold
|
||||
if(counter.nmi_hold) {
|
||||
counter.nmi_hold -= 2;
|
||||
if(counter.nmi_hold == 0) {
|
||||
if(status.nmi_enabled == true) status.nmi_transition = true;
|
||||
}
|
||||
}
|
||||
|
||||
//NMI test
|
||||
history.query(2, vpos, hpos);
|
||||
bool nmi_valid = (vpos >= (!ppu.overscan() ? 225 : 240));
|
||||
if(status.nmi_valid == false && nmi_valid == true) {
|
||||
//0->1 edge sensitive transition
|
||||
status.nmi_line = true;
|
||||
counter.nmi_hold = 4;
|
||||
} else if(status.nmi_valid == true && nmi_valid == false) {
|
||||
//1->0 edge sensitive transition
|
||||
status.nmi_line = false;
|
||||
}
|
||||
status.nmi_valid = nmi_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;
|
||||
}
|
||||
|
||||
//IRQ test
|
||||
history.query(10, 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 = 4;
|
||||
}
|
||||
status.irq_valid = irq_valid;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool sCPU::irq_pos_valid() {
|
||||
uint vpos = status.virq_pos;
|
||||
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||
uint vlimit = region_scanlines() >> 1;
|
||||
//positions that can never be latched
|
||||
//vlimit = 262/NTSC, 312/PAL
|
||||
//PAL results are unverified on hardware
|
||||
if(vpos == 240 && hpos == 339 && interlace() == false && interlace_field() == 1)return false;
|
||||
if(vpos == (vlimit - 1) && hpos == 339 && interlace() == false)return false;
|
||||
if(vpos == vlimit && interlace() == false)return false;
|
||||
if(vpos == vlimit && hpos == 339)return false;
|
||||
if(vpos > vlimit)return false;
|
||||
if(hpos > 339)return false;
|
||||
uint vpos = status.virq_pos;
|
||||
uint hpos = (status.hirq_enabled) ? status.hirq_pos : 0;
|
||||
uint vlimit = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
||||
//positions that can never be latched
|
||||
//vlimit = 262/NTSC, 312/PAL
|
||||
//PAL results are unverified on hardware
|
||||
if(vpos == 240 && hpos == 339 && ppu.interlace() == false && ppu.field() == 1) return false;
|
||||
if(vpos == (vlimit - 1) && hpos == 339 && ppu.interlace() == false) return false;
|
||||
if(vpos == vlimit && ppu.interlace() == false) return false;
|
||||
if(vpos == vlimit && hpos == 339) return false;
|
||||
if(vpos > vlimit) return false;
|
||||
if(hpos > 339) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
bool sCPU::nmi_test() {
|
||||
if(status.nmi_transition == false) { return false; }
|
||||
alwaysinline bool sCPU::nmi_test() {
|
||||
if(status.nmi_transition == false) return false;
|
||||
status.nmi_transition = false;
|
||||
|
||||
event.wai = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
bool sCPU::irq_test() {
|
||||
if(status.irq_transition == false) { return false; }
|
||||
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;
|
||||
return regs.p.i ? false : true;
|
||||
}
|
||||
|
||||
/*
|
||||
if(status.irq_transition == 1)goto irq_trigger;
|
||||
|
||||
if(status.irq_read == 0) {
|
||||
if(status.irq_line == 1 && irq_edge()) {
|
||||
return false;
|
||||
}
|
||||
goto irq_trigger;
|
||||
}
|
||||
|
||||
if(status.irq_line == 0) {
|
||||
status.irq_line = 1;
|
||||
goto irq_trigger;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
irq_trigger:
|
||||
status.irq_transition = 0;
|
||||
event.wai = false;
|
||||
return (regs.p.i) ? false : true;
|
||||
}
|
||||
*/
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,105 +0,0 @@
|
||||
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,15 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
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;
|
||||
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
|
||||
for(unsigned i = 0; i < 16; i++) {
|
||||
uint8 port0 = snes.input.port_read(0);
|
||||
uint8 port1 = snes.input.port_read(1);
|
||||
|
||||
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;
|
||||
joy3 |= (port0 & 2) ? (0x8000 >> i) : 0;
|
||||
joy4 |= (port1 & 2) ? (0x8000 >> i) : 0;
|
||||
}
|
||||
|
||||
status.joy1l = joy1;
|
||||
@@ -11,9 +18,11 @@ uint16 joy1 = 0, joy2 = 0;
|
||||
status.joy2l = joy2;
|
||||
status.joy2h = joy2 >> 8;
|
||||
|
||||
status.joy3l = 0x00;
|
||||
status.joy3h = 0x00;
|
||||
status.joy3l = joy3;
|
||||
status.joy3h = joy3 >> 8;
|
||||
|
||||
status.joy4l = 0x00;
|
||||
status.joy4h = 0x00;
|
||||
status.joy4l = joy4;
|
||||
status.joy4h = joy4 >> 8;
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,22 +0,0 @@
|
||||
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) {
|
||||
vtime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime) {
|
||||
if(htime >= clocks) {
|
||||
htime -= clocks;
|
||||
} else {
|
||||
htime += status.prev_line_clocks - clocks;
|
||||
if(vtime > 0) {
|
||||
vtime--;
|
||||
} else {
|
||||
vtime = status.prev_field_lines - 1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,31 +1,11 @@
|
||||
#define ntsc_color_burst_phase_shift_scanline() \
|
||||
(status.region == SNES::NTSC && status.vcounter == 240 && \
|
||||
status.interlace == false && status.interlace_field == 1)
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
#include "timeshift.cpp"
|
||||
#include "irq.cpp"
|
||||
#include "joypad.cpp"
|
||||
|
||||
uint16 sCPU::vcounter() { return status.vcounter; }
|
||||
uint16 sCPU::hclock() { return status.hclock; }
|
||||
|
||||
bool sCPU::interlace() { return status.interlace; }
|
||||
bool sCPU::interlace_field() { return status.interlace_field; }
|
||||
bool sCPU::overscan() { return status.overscan; }
|
||||
uint16 sCPU::region_scanlines() { return status.region_scanlines; }
|
||||
|
||||
uint sCPU::dma_counter() { return (status.dma_counter + status.hclock) & 7; }
|
||||
|
||||
void sCPU::set_interlace(bool r) {
|
||||
status.interlace = r;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void sCPU::set_overscan (bool r) {
|
||||
status.overscan = r;
|
||||
status.vblstart = (status.overscan == false) ? 225 : 240;
|
||||
update_interrupts();
|
||||
}
|
||||
uint16 sCPU::hcounter() { return status.hcounter; }
|
||||
uint sCPU::dma_counter() { return (status.dma_counter + status.hcounter) & 7; }
|
||||
|
||||
/*****
|
||||
* One PPU dot = 4 CPU clocks
|
||||
@@ -37,16 +17,20 @@ void sCPU::set_overscan (bool r) {
|
||||
* Dot 323 range = { 1292, 1294, 1296 }
|
||||
* Dot 327 range = { 1310, 1312, 1314 }
|
||||
*****/
|
||||
uint16 sCPU::hcounter() {
|
||||
if(ntsc_color_burst_phase_shift_scanline() == true) {
|
||||
return (status.hclock >> 2);
|
||||
}
|
||||
return (status.hclock - ((status.hclock > 1292) << 1) - ((status.hclock > 1310) << 1)) >> 2;
|
||||
|
||||
#define ntsc_color_burst_phase_shift_scanline() ( \
|
||||
snes.region() == SNES::NTSC && status.vcounter == 240 && \
|
||||
ppu.interlace() == false && ppu.field() == 1 \
|
||||
)
|
||||
|
||||
uint16 sCPU::hdot() {
|
||||
if(ntsc_color_burst_phase_shift_scanline() == true) return (status.hcounter >> 2);
|
||||
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2;
|
||||
}
|
||||
|
||||
void sCPU::add_clocks(uint clocks) {
|
||||
if(status.dram_refreshed == false) {
|
||||
if(status.hclock + clocks >= status.dram_refresh_position) {
|
||||
if(status.hcounter + clocks >= status.dram_refresh_position) {
|
||||
status.dram_refreshed = true;
|
||||
clocks += 40;
|
||||
}
|
||||
@@ -57,58 +41,46 @@ void sCPU::add_clocks(uint clocks) {
|
||||
|
||||
clocks >>= 1;
|
||||
while(clocks--) {
|
||||
status.hclock += 2;
|
||||
if(status.hclock >= status.line_clocks) { scanline(); }
|
||||
history.enqueue(status.vcounter, status.hcounter);
|
||||
status.hcounter += 2;
|
||||
if(status.hcounter >= status.line_clocks) scanline();
|
||||
poll_interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::scanline() {
|
||||
status.hclock = 0;
|
||||
status.hcounter = 0;
|
||||
status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
|
||||
|
||||
if(++status.vcounter >= status.field_lines) {
|
||||
frame();
|
||||
}
|
||||
|
||||
status.prev_line_clocks = status.line_clocks;
|
||||
if(++status.vcounter >= status.field_lines) frame();
|
||||
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
|
||||
|
||||
//dram refresh occurs once every scanline
|
||||
//dram refresh occurs once every scanline
|
||||
status.dram_refreshed = false;
|
||||
if(cpu_version == 2) {
|
||||
if(ntsc_color_burst_phase_shift_scanline() == false) {
|
||||
if(status.dram_refresh_position == 534) {
|
||||
status.dram_refresh_position = 538;
|
||||
} else {
|
||||
status.dram_refresh_position = 534;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(cpu_version == 2) status.dram_refresh_position = 530 + 8 - dma_counter();
|
||||
|
||||
//hdma triggers once every visible scanline
|
||||
//hdma triggers once every visible scanline
|
||||
status.line_rendered = false;
|
||||
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
|
||||
status.hdma_triggered = (status.vcounter <= (ppu.overscan() == false ? 224 : 239)) ? false : true;
|
||||
|
||||
ppu.scanline();
|
||||
snes.scanline();
|
||||
|
||||
update_interrupts();
|
||||
|
||||
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
|
||||
snes.poll_input();
|
||||
if(status.auto_joypad_poll == true && status.vcounter == (ppu.overscan() == false ? 227 : 242)) {
|
||||
snes.input.poll();
|
||||
run_auto_joypad_poll();
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::frame() {
|
||||
ppu.frame();
|
||||
snes.frame();
|
||||
|
||||
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)
|
||||
if(status.interlace == true && status.interlace_field == 0)status.field_lines++;
|
||||
status.field_lines = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
||||
//interlaced even fields have one extra scanline (263+262=525 NTSC, 313+312=625 PAL)
|
||||
if(ppu.interlace() == true && ppu.field() == 0) status.field_lines++;
|
||||
|
||||
status.hdmainit_triggered = false;
|
||||
if(cpu_version == 1) {
|
||||
@@ -116,89 +88,88 @@ void sCPU::frame() {
|
||||
} else {
|
||||
status.hdmainit_trigger_position = 12 + dma_counter();
|
||||
}
|
||||
|
||||
ppu.frame();
|
||||
snes.frame();
|
||||
}
|
||||
|
||||
/*****
|
||||
* precycle_edge()
|
||||
*
|
||||
* Used for DMA/HDMA bus synchronization
|
||||
* Used for H/DMA bus synchronization
|
||||
*****/
|
||||
alwaysinline void sCPU::precycle_edge() {
|
||||
if(status.dma_state == DMASTATE_CPUSYNC) {
|
||||
status.dma_state = DMASTATE_INACTIVE;
|
||||
uint n = status.clock_count - (status.dma_clocks % status.clock_count);
|
||||
add_clocks(n ? n : status.clock_count);
|
||||
void sCPU::precycle_edge() {
|
||||
if(status.dma_state == DMA_CPUsync) {
|
||||
add_clocks(status.clock_count - (status.dma_clocks % status.clock_count));
|
||||
status.dma_state = DMA_Inactive;
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
* cycle_edge()
|
||||
*
|
||||
* Used to test for HDMA, which can trigger on the edge of every opcode cycle.
|
||||
* Used to test for H/DMA, which can trigger on the edge of every opcode cycle.
|
||||
*****/
|
||||
void sCPU::cycle_edge() {
|
||||
if(status.line_rendered == false) {
|
||||
if(status.hclock >= status.line_render_position) {
|
||||
if(status.hcounter >= status.line_render_position) {
|
||||
status.line_rendered = true;
|
||||
ppu.render_scanline();
|
||||
}
|
||||
}
|
||||
|
||||
switch(status.dma_state) {
|
||||
case DMASTATE_INACTIVE:
|
||||
break;
|
||||
|
||||
case DMASTATE_DMASYNC:
|
||||
status.dma_state = DMASTATE_RUN;
|
||||
break;
|
||||
|
||||
case DMASTATE_RUN:
|
||||
status.dma_state = DMASTATE_CPUSYNC;
|
||||
status.dma_clocks = 8 - dma_counter() + 8;
|
||||
add_clocks(status.dma_clocks);
|
||||
|
||||
if(status.hdmainit_pending) { hdma_init(); status.hdmainit_pending = false; }
|
||||
if(status.hdma_pending) { hdma_run(); status.hdma_pending = false; }
|
||||
if(status.dma_pending) { dma_run(); status.dma_pending = false; }
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(status.hdmainit_triggered == false) {
|
||||
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
|
||||
if(status.hcounter >= status.hdmainit_trigger_position || status.vcounter) {
|
||||
status.hdmainit_triggered = true;
|
||||
hdma_init_reset();
|
||||
if(hdma_enabled_channels()) {
|
||||
add_clocks(18);
|
||||
hdma_init();
|
||||
//if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
// status.dma_state = DMASTATE_DMASYNC;
|
||||
// status.hdmainit_pending = true;
|
||||
//} else {
|
||||
// hdma_init();
|
||||
//}
|
||||
status.hdma_pending = true;
|
||||
status.hdma_mode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(status.hdma_triggered == false) {
|
||||
if(status.hclock >= 1106) {
|
||||
if(status.hcounter >= 1104) {
|
||||
status.hdma_triggered = true;
|
||||
if(hdma_active_channels()) {
|
||||
add_clocks(18);
|
||||
hdma_run();
|
||||
//if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
// status.dma_state = DMASTATE_DMASYNC;
|
||||
// status.hdma_pending = true;
|
||||
//} else {
|
||||
// hdma_run();
|
||||
//}
|
||||
status.hdma_pending = true;
|
||||
status.hdma_mode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//H/DMA pending && DMA inactive?
|
||||
//.. Run one full CPU cycle
|
||||
//.. HDMA pending && HDMA enabled ? DMA sync + HDMA run
|
||||
//.. DMA pending && DMA enabled ? DMA sync + DMA run
|
||||
//.... HDMA during DMA && HDMA enabled ? DMA sync + HDMA run
|
||||
//.. Run one bus CPU cycle
|
||||
//.. CPU sync
|
||||
|
||||
if(status.dma_state == DMA_Run) {
|
||||
if(status.hdma_pending) {
|
||||
status.hdma_pending = false;
|
||||
if(hdma_enabled_channels()) {
|
||||
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
||||
if(!dma_enabled_channels()) status.dma_state = DMA_CPUsync;
|
||||
}
|
||||
}
|
||||
|
||||
if(status.dma_pending) {
|
||||
status.dma_pending = false;
|
||||
if(dma_enabled_channels()) {
|
||||
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||
dma_run();
|
||||
status.dma_state = DMA_CPUsync;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(status.dma_state == DMA_Inactive) {
|
||||
if(status.dma_pending || status.hdma_pending) {
|
||||
status.dma_clocks = 0;
|
||||
status.dma_state = DMA_Run;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
@@ -211,7 +182,7 @@ void sCPU::cycle_edge() {
|
||||
* trigger during certain events (immediately after DMA, writes to $4200, etc)
|
||||
*****/
|
||||
void sCPU::last_cycle() {
|
||||
if(counter.irq_delay) { return; }
|
||||
if(counter.irq_delay) return;
|
||||
|
||||
status.nmi_pending |= nmi_test();
|
||||
status.irq_pending |= irq_test();
|
||||
@@ -235,22 +206,12 @@ void sCPU::timing_reset() {
|
||||
|
||||
status.vcounter = 0;
|
||||
status.hcounter = 0;
|
||||
status.hclock = 0;
|
||||
|
||||
status.interlace = 0;
|
||||
status.interlace_field = 0;
|
||||
status.overscan = false;
|
||||
status.region_scanlines = (status.region == SNES::NTSC) ? 525 : 625;
|
||||
status.vblstart = 225;
|
||||
|
||||
status.field_lines = status.region_scanlines >> 1;
|
||||
status.field_lines = (snes.region() == SNES::NTSC ? 525 : 625) >> 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 = min(1112, (uint16)config::ppu.hack.render_scanline_position);
|
||||
status.line_render_position = min(1112U, (unsigned)config::ppu.hack.render_scanline_position);
|
||||
|
||||
status.dram_refreshed = false;
|
||||
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
||||
@@ -275,15 +236,20 @@ void sCPU::timing_reset() {
|
||||
update_interrupts();
|
||||
|
||||
status.dma_counter = 0;
|
||||
status.dma_state = DMASTATE_INACTIVE;
|
||||
status.dma_clocks = 0;
|
||||
status.dma_pending = false;
|
||||
status.hdma_pending = false;
|
||||
status.hdmainit_pending = false;
|
||||
status.hdma_mode = 0;
|
||||
status.dma_state = DMA_Inactive;
|
||||
|
||||
//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);
|
||||
history.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);
|
||||
}
|
||||
|
||||
#undef ntsc_color_burst_phase_shift_scanline
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
|
@@ -1,15 +1,6 @@
|
||||
uint16 vcounter();
|
||||
uint16 hcounter();
|
||||
uint16 hclock();
|
||||
|
||||
bool interlace();
|
||||
bool interlace_field();
|
||||
bool overscan();
|
||||
uint16 region_scanlines();
|
||||
|
||||
void set_interlace(bool r);
|
||||
void set_overscan(bool r);
|
||||
|
||||
uint16 hdot();
|
||||
uint dma_counter();
|
||||
|
||||
void add_clocks(uint clocks);
|
||||
@@ -24,12 +15,33 @@
|
||||
void timing_power();
|
||||
void timing_reset();
|
||||
|
||||
//timeshift.cpp
|
||||
void timeshift_forward (uint clocks, uint &v, uint &h);
|
||||
void timeshift_backward(uint clocks, uint &v, uint &h);
|
||||
//timeshifting -- needed by NMI and IRQ timing
|
||||
struct History {
|
||||
struct Time {
|
||||
uint16 vcounter;
|
||||
uint16 hcounter;
|
||||
} time[32];
|
||||
unsigned index;
|
||||
alwaysinline void enqueue(uint16 vcounter, uint16 hcounter) {
|
||||
Time &t = time[index++];
|
||||
index &= 31;
|
||||
t.vcounter = vcounter;
|
||||
t.hcounter = hcounter;
|
||||
}
|
||||
alwaysinline void query(unsigned offset, uint16 &vcounter, uint16 &hcounter) {
|
||||
Time &t = time[(index - (offset >> 1)) & 31];
|
||||
vcounter = t.vcounter;
|
||||
hcounter = t.hcounter;
|
||||
}
|
||||
void reset() {
|
||||
index = 0;
|
||||
for(unsigned i = 0; i < 32; i++) time[i].vcounter = time[i].hcounter = 0;
|
||||
}
|
||||
History() { reset(); }
|
||||
} history;
|
||||
|
||||
//irq.cpp
|
||||
enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
||||
//irq.cpp
|
||||
enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
||||
void update_interrupts();
|
||||
void poll_interrupts();
|
||||
void nmitimen_update(uint8 data);
|
||||
@@ -41,5 +53,5 @@ enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
||||
bool nmi_test();
|
||||
bool irq_test();
|
||||
|
||||
//joypad.cpp
|
||||
//joypad.cpp
|
||||
void run_auto_joypad_poll();
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
1034
src/data/controller.h
Normal file
1034
src/data/controller.h
Normal file
File diff suppressed because it is too large
Load Diff
41
src/data/icon48.h
Normal file
41
src/data/icon48.h
Normal file
@@ -0,0 +1,41 @@
|
||||
static char enc_icon48[] = {
|
||||
"_gAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||
"AfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB"
|
||||
"8AHwAfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHw"
|
||||
"AfAB8AHwAfD_AfAB8AHwAfAB8AHwAfABAAD_qgAD_p8VOwD_oRaI_qEWthD-oBbL"
|
||||
"CADE_qEAFaP_oBZm_p38GBU28AHwAfAB8AHwAfBfAfAB8AFQuBCoAMe0AP4twAD_"
|
||||
"BPAEIPAkAIX_-JkZCkLwAfAB8AHwAfBHAfAB8HSB_wABtABvPQQA-7DwBPAEECwA"
|
||||
"0P74oBIbTvAB8AHwAfAB8EcB8AHweEGgFWwkAv0HqPAE8MSwFdX-oRr-E1LwAfAB"
|
||||
"8AHwAfAB8Lzg6KEUMRAC96DwBPAE8P3EIKXAEVrwAfAB8AHwAfDzAfDAsBa3mPAE"
|
||||
"8ATwwED_uAE4E1rwAfAB8AHwAfAB8PG8YKIVJDjyBPAE8ATA-KAWoF7wAfAB8AHw"
|
||||
"AfB7AfD4gmmQ8ATwBPDM4-Z_XvAB8AHwAfAB8AHwwICPH_wSePQE8ATwBMClDxEB"
|
||||
"YNBERP8PPz_-oEw-Pv56CACMCACCgggAXT8__yD2BA808wHwAfDAkKMSDv6AmxwS"
|
||||
"_qQYH8QC6kjIAJTUAOug8ATwhOFDRABYUDw8_hWsAI9QPj7_8KwA_wTw_oL6BAC1"
|
||||
"PT3-MpbwjwHwAfAB8AxmpRkUFAOOkxjzBPAEoJ8PEEAQdZQAOrwA47TwBPAoAPh9"
|
||||
"yAB0hvAB8AHwAfBcsha6XFwC-KzwBPDsAOQ0EHWQAD0EAPSs8ATwBMCAn4LwAfAB"
|
||||
"8AHwXLUVakz4gwTwKACbQkL-F0wBTuac8ATwiPH-_AQATh-C8AHwAfAB8ExifwAC"
|
||||
"DcAAtbTwfKT8_qETejSAAJOc8ATwBPAUY9p9CAAIhvAB8AHwAfCEYZ4MGDWE8YCn"
|
||||
"nEs8_3oRgAD1lPAE8ATwBKBVh4LwAQAUCwDNACQEAKBNAMwAaggAewgAoH8AywBz"
|
||||
"CABbCABgNwDIAA458Nxp2IO88Hwhzf-ZEQ-0A15XjPAE8ATwhOGlfaDOVAA1oACY"
|
||||
"sADhCAD9jQgA_wTwBEDMAPQEAHq7NABjCAAcq2QRvPAW9sUMXHwAiIzwBPAE8MDg"
|
||||
"otZxIMsAGYQArQQATv6s8ATwzPAA4wQAUVcKAGQmYAR9MILpBAB3sP-qKgbgUPwC"
|
||||
"mwQAevuAAP6U8ATwBPDAYO3QANEAHIQA3JjwBPCrBPAEoPwEAGyAQVRwAeCV_qIX"
|
||||
"WPQWZNJ8AKoQgAQbSAI2hABtzAC6xAgA_aDwBPCIxOc4Ab6mjPAE8ATwBPAEAPYE"
|
||||
"AK9YZwHwAfA2QwLAAEgEAK7dqPAE8MCAx8AA5Ijw_wTwBPAE8ExCFPQB8AHwAQDQ"
|
||||
"Q0P-E5QAw6zwBPD1wECLcAC2iPAE8ATwBPD1BAD70AMqmvAB8AHwATDQODj-EpgA"
|
||||
"1LDwxPbFBAAxcCDNAOyM8ATwewTwBOCGkvAB8AHwIOM8t-AzuPC8g66UasQwyJDw"
|
||||
"VwTwBPAEIPHEBG4KAAJBDcYKAP7-LAQAT1UEAGUEAHAEAGoEAFd1BAA5BAASJAAY"
|
||||
"-8Qg_gaytPB8Yeg7O_8eUTGgvwAEyABUUAK3XZAA9aTw6OJsFdgIAIOQAM8AG_11"
|
||||
"_guUAKpgCAC1BADvDAD_BPAxBED-_vgIAEoA_nzDBAD4o0BA_lO88Lwgjuy4FPLw"
|
||||
"AYDPABCYAKpCoABtBACKBACbEACKngQAk4wnzQBXoCd3qBe5plgh4azwBPDM8P76"
|
||||
"9QQAiwwA1CjgGeQSvMD6yAQAKbHwAfAB8AHwvMC9RBH-nPAE8ATwBKDAxCFVVDXu"
|
||||
"sADzCAC9dEgEX3nwAfAB8AHwvMAxBAD8X4zwBPAE8ATwTAB-3Ewh_bQADHHwAfAB"
|
||||
"8AHwAfDAYL50iPAE8ATwBPDAQMRl8L8B8AHwAfAB8AHwcABMiPDvBPAE8ATwwECc"
|
||||
"ZfAB8AHwrwHwAfAB8HQAAnQAsIzw9wTwBPC84OQIABy1AfAB8O8B8AHwAfDs1ZUI"
|
||||
"8wTwBPD1vGDHBAAkXfAB8AHwAfCnAfAB8Mjw_zCEAJ8EAK7rpPAE8CgA9wQAvAQA"
|
||||
"_lQQAJC1AfAB8AHwAfAB8FcB8MjwkBE6BABsBACPVQQApAQArwQAqQQAl_UgAHgI"
|
||||
"AEsEANQsAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB"
|
||||
"8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_"
|
||||
"AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||
"AfD_AfAB8AHwAfAB8AHwAfAB8A8B8AHwAfABsA"
|
||||
};
|
BIN
src/doc/base.dia
BIN
src/doc/base.dia
Binary file not shown.
@@ -1,4 +1,6 @@
|
||||
#include "../../base.h"
|
||||
#define ADSP_CPP
|
||||
|
||||
#include "adsp_tables.cpp"
|
||||
|
||||
void aDSP::enter() { loop:
|
||||
@@ -578,8 +580,8 @@ int32 fir_samplel, fir_sampler;
|
||||
msampler = sclamp<16>(msampler);
|
||||
}
|
||||
|
||||
snes.audio_update(msamplel, msampler);
|
||||
scheduler.addclocks_dsp(32 * 3);
|
||||
snes.audio.update(msamplel, msampler);
|
||||
scheduler.addclocks_dsp(32 * 3 * 8);
|
||||
}
|
||||
|
||||
aDSP::aDSP() {}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user