Compare commits
41 Commits
asciiclean
...
v46
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
764c0dd2c1 | ||
|
|
a1763efe21 | ||
|
|
b3d930b143 | ||
|
|
3063b354e7 | ||
|
|
571737d59b | ||
|
|
09198f5099 | ||
|
|
8e877d38d4 | ||
|
|
7a878eab39 | ||
|
|
091b82a7ef | ||
|
|
1c30d3db56 | ||
|
|
9cf6eae076 | ||
|
|
67a25941a7 | ||
|
|
aedc6dab5b | ||
|
|
c40b9c32b6 | ||
|
|
59aad4c7a8 | ||
|
|
af48032798 | ||
|
|
d481bd5061 | ||
|
|
96c273fe89 | ||
|
|
25c1f38aed | ||
|
|
0693dbc933 | ||
|
|
500e6326c1 | ||
|
|
d229719d0c | ||
|
|
096ad71b4e | ||
|
|
aa29d483eb | ||
|
|
dc83f998c7 | ||
|
|
369667e154 | ||
|
|
4a083cbea3 | ||
|
|
edf204ac24 | ||
|
|
0c378a9f7c | ||
|
|
55e3468f74 | ||
|
|
78e9dce5ea | ||
|
|
eaf0bda3ee | ||
|
|
d58d3439ec | ||
|
|
b5f111fa41 | ||
|
|
6508530384 | ||
|
|
e4364eedb1 | ||
|
|
74312e08e1 | ||
|
|
09f42acfc8 | ||
|
|
70984ebd00 | ||
|
|
cafe5b8efd | ||
|
|
a1e89d9528 |
4
.ditz-config
Normal file
4
.ditz-config
Normal file
@@ -0,0 +1,4 @@
|
||||
--- !ditz.rubyforge.org,2008-03-06/config
|
||||
name: David
|
||||
email: david@optixx.org
|
||||
issue_dir: bugs
|
||||
Binary file not shown.
Binary file not shown.
278
bsnes/Makefile
278
bsnes/Makefile
@@ -1,278 +0,0 @@
|
||||
include lib/nall/Makefile.string
|
||||
prefix = /usr/local
|
||||
ui = ui_qt
|
||||
|
||||
################
|
||||
### compiler ###
|
||||
################
|
||||
|
||||
ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
||||
flags = -O3 -fomit-frame-pointer -Ilib
|
||||
# note: libco *requires* -fomit-frame-pointer on i386 arch
|
||||
libcoflags := $(flags) -static
|
||||
c = $(compiler)
|
||||
cpp = $(subst cc,++,$(compiler))
|
||||
obj = o
|
||||
rule = -c $< -o $@
|
||||
link = -s
|
||||
mkbin = -o$1
|
||||
mkdef = -D$1
|
||||
mkincpath = -I$1
|
||||
mklib = -l$1
|
||||
mklibpath = -L$1
|
||||
|
||||
# profile-guided optimization:
|
||||
# flags += -fprofile-generate
|
||||
# link += -lgcov
|
||||
# flags += -fprofile-use
|
||||
else ifeq ($(compiler),cl) # Visual C++
|
||||
flags = /nologo /wd4355 /wd4805 /wd4996 /Ox /GL /EHsc /Ilib
|
||||
libcoflags = $(flags)
|
||||
c = cl
|
||||
cpp = cl
|
||||
obj = obj
|
||||
rule = /c $< /Fo$@
|
||||
link = /link
|
||||
mkbin = /Fe$1
|
||||
mkdef = /D$1
|
||||
mkincpath = /I$1
|
||||
mklib = $1.lib
|
||||
mklibpath = /L$1
|
||||
else
|
||||
unknown_compiler: help;
|
||||
endif
|
||||
|
||||
##########
|
||||
### os ###
|
||||
##########
|
||||
|
||||
ifeq ($(platform),x) # X11
|
||||
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x
|
||||
delete = rm -f $1
|
||||
else ifeq ($(platform),win) # Windows
|
||||
mingw_link_flags = -mwindows
|
||||
# mingw_links_flags = -mconsole
|
||||
|
||||
# enable static linking to Qt for Windows build
|
||||
mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
|
||||
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput
|
||||
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
|
||||
link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags))
|
||||
link += $(call mklib,uuid)
|
||||
link += $(call mklib,kernel32)
|
||||
link += $(call mklib,user32)
|
||||
link += $(call mklib,gdi32)
|
||||
link += $(call mklib,shell32)
|
||||
else
|
||||
unknown_platform: help;
|
||||
endif
|
||||
|
||||
############
|
||||
### ruby ###
|
||||
############
|
||||
|
||||
rubyflags = $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
|
||||
link += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
|
||||
|
||||
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 audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple))
|
||||
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
|
||||
link += $(if $(findstring input.rawinput,$(ruby)),$(call mklib,xinput) $(call mklib,dinput8) $(call mklib,dxguid))
|
||||
|
||||
####################
|
||||
### core objects ###
|
||||
####################
|
||||
|
||||
objects = libco 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 ($(enable_gzip),true)
|
||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||
flags += $(call mkdef,GZIP_SUPPORT)
|
||||
endif
|
||||
|
||||
ifeq ($(enable_jma),true)
|
||||
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
|
||||
flags += $(call mkdef,JMA_SUPPORT)
|
||||
endif
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
######################
|
||||
|
||||
compile = \
|
||||
$(strip \
|
||||
$(if $(filter %.c,$<), \
|
||||
$(c) $(flags) $1 $(rule), \
|
||||
$(if $(filter %.cpp,$<), \
|
||||
$(cpp) $(flags) $1 $(rule) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
%.$(obj): $<; $(call compile)
|
||||
|
||||
all: build;
|
||||
|
||||
include $(ui)/Makefile
|
||||
objects := $(patsubst %,obj/%.$(obj),$(objects))
|
||||
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
|
||||
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/* lib/ruby/video/* lib/ruby/audio/* lib/ruby/input/*
|
||||
$(call compile,$(rubydef) $(rubyflags))
|
||||
obj/libco.$(obj): lib/libco/libco.c lib/libco/*
|
||||
$(c) $(libcoflags) $(rule)
|
||||
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/*
|
||||
obj/string.$(obj): lib/nall/string.cpp lib/nall/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
#################
|
||||
|
||||
obj/reader.$(obj): reader/reader.cpp reader/*
|
||||
obj/cart.$(obj) : cart/cart.cpp cart/*
|
||||
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
|
||||
obj/memory.$(obj) : memory/memory.cpp memory/*
|
||||
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||
|
||||
###########
|
||||
### cpu ###
|
||||
###########
|
||||
|
||||
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 ###
|
||||
###########
|
||||
|
||||
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 ###
|
||||
###########
|
||||
|
||||
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
|
||||
obj/ppu.$(obj) : ppu/ppu.cpp ppu/*
|
||||
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
|
||||
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
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 ###
|
||||
############
|
||||
|
||||
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 ###
|
||||
###########
|
||||
|
||||
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/*
|
||||
|
||||
###############
|
||||
### targets ###
|
||||
###############
|
||||
|
||||
build: ui_build $(objects)
|
||||
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
|
||||
|
||||
install:
|
||||
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
|
||||
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
|
||||
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
|
||||
|
||||
clean: ui_clean
|
||||
-@$(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=(os) compiler=(cc) [options]"
|
||||
@echo ""
|
||||
@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 " 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 compiler=gcc enable_gzip=true"
|
||||
@echo ""
|
||||
@@ -1,234 +0,0 @@
|
||||
#include <../base.hpp>
|
||||
#include <../chip/chip.hpp>
|
||||
#include <../reader/reader.hpp>
|
||||
#define CART_CPP
|
||||
|
||||
#include <nall/crc32.hpp>
|
||||
#include <nall/ups.hpp>
|
||||
|
||||
#include "cart.hpp"
|
||||
#include "cart_file.cpp"
|
||||
#include "cart_header.cpp"
|
||||
#include "cart_loader.cpp"
|
||||
|
||||
namespace memory {
|
||||
MappedRAM cartrom, cartram, cartrtc;
|
||||
MappedRAM bscram;
|
||||
MappedRAM stArom, stAram;
|
||||
MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
void Cartridge::load_begin(Mode cartridge_mode) {
|
||||
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 = cart.rtc_size = 0;
|
||||
bs.ram_size = 0;
|
||||
stA.rom_size = stA.ram_size = 0;
|
||||
stB.rom_size = stB.ram_size = 0;
|
||||
|
||||
set(loaded, false);
|
||||
set(bsx_flash_loaded, false);
|
||||
set(patched, false);
|
||||
set(mode, cartridge_mode);
|
||||
}
|
||||
|
||||
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);
|
||||
memory::stBrom.map(stB.rom, stB.rom_size);
|
||||
memory::stBram.map(stB.ram, stB.ram_size);
|
||||
|
||||
memory::cartrom.write_protect(true);
|
||||
memory::cartram.write_protect(false);
|
||||
memory::bscram.write_protect(true);
|
||||
memory::stArom.write_protect(true);
|
||||
memory::stAram.write_protect(false);
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
|
||||
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
|
||||
if(file::exists(cheat_file)) {
|
||||
cheat.clear();
|
||||
cheat.load(cheat_file);
|
||||
}
|
||||
|
||||
bus.load_cart();
|
||||
set(loaded, true);
|
||||
}
|
||||
|
||||
void Cartridge::unload() {
|
||||
if(loaded() == false) return;
|
||||
bus.unload_cart();
|
||||
|
||||
switch(mode()) {
|
||||
case ModeNormal: unload_normal(); break;
|
||||
case ModeBsxSlotted: unload_bsx_slotted(); break;
|
||||
case ModeBsx: unload_bsx(); break;
|
||||
case ModeSufamiTurbo: unload_sufami_turbo(); break;
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
|
||||
if(cheat.count() > 0 || file::exists(cheat_file)) {
|
||||
cheat.save(cheat_file);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
set(loaded, false);
|
||||
}
|
||||
|
||||
Cartridge::Cartridge() {
|
||||
set(loaded, false);
|
||||
}
|
||||
|
||||
Cartridge::~Cartridge() {
|
||||
if(loaded() == true) unload();
|
||||
}
|
||||
|
||||
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
|
||||
set(region, source.region);
|
||||
set(mapper, source.mapper);
|
||||
set(dsp1_mapper, source.dsp1_mapper);
|
||||
|
||||
set(has_bsx_slot, source.bsx_slot);
|
||||
set(has_superfx, source.superfx);
|
||||
set(has_sa1, source.sa1);
|
||||
set(has_srtc, source.srtc);
|
||||
set(has_sdd1, source.sdd1);
|
||||
set(has_spc7110, source.spc7110);
|
||||
set(has_spc7110rtc, source.spc7110rtc);
|
||||
set(has_cx4, source.cx4);
|
||||
set(has_dsp1, source.dsp1);
|
||||
set(has_dsp2, source.dsp2);
|
||||
set(has_dsp3, source.dsp3);
|
||||
set(has_dsp4, source.dsp4);
|
||||
set(has_obc1, source.obc1);
|
||||
set(has_st010, source.st010);
|
||||
set(has_st011, source.st011);
|
||||
set(has_st018, source.st018);
|
||||
}
|
||||
|
||||
//==========
|
||||
//cartinfo_t
|
||||
//==========
|
||||
|
||||
void Cartridge::cartinfo_t::reset() {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
region = NTSC;
|
||||
|
||||
rom_size = 0;
|
||||
ram_size = 0;
|
||||
|
||||
bsx_slot = false;
|
||||
superfx = false;
|
||||
sa1 = false;
|
||||
srtc = false;
|
||||
sdd1 = false;
|
||||
spc7110 = false;
|
||||
spc7110rtc = false;
|
||||
cx4 = false;
|
||||
dsp1 = false;
|
||||
dsp2 = false;
|
||||
dsp3 = false;
|
||||
dsp4 = false;
|
||||
obc1 = false;
|
||||
st010 = false;
|
||||
st011 = false;
|
||||
st018 = false;
|
||||
}
|
||||
|
||||
Cartridge::cartinfo_t::cartinfo_t() {
|
||||
reset();
|
||||
}
|
||||
|
||||
//=======
|
||||
//utility
|
||||
//=======
|
||||
|
||||
//ensure file path is absolute (eg resolve relative paths)
|
||||
string Cartridge::filepath(const char *filename, const char *pathname) {
|
||||
//if no pathname, return filename as-is
|
||||
string file(filename);
|
||||
file.replace("\\", "/");
|
||||
|
||||
string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname;
|
||||
//ensure path ends with trailing '/'
|
||||
path.replace("\\", "/");
|
||||
if(!strend(path, "/")) path.append("/");
|
||||
|
||||
//replace relative path with absolute path
|
||||
if(strbegin(path, "./")) {
|
||||
ltrim(path, "./");
|
||||
path = string() << snes.config.path.base << path;
|
||||
}
|
||||
|
||||
//remove folder part of filename
|
||||
lstring part;
|
||||
part.split("/", file);
|
||||
return path << part[part.size() - 1];
|
||||
}
|
||||
|
||||
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
|
||||
string Cartridge::basename(const char *filename) {
|
||||
string name(filename);
|
||||
|
||||
//remove extension
|
||||
for(signed i = strlen(name) - 1; i >= 0; i--) {
|
||||
if(name[i] == '.') {
|
||||
name[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//remove directory information
|
||||
for(signed i = strlen(name) - 1; i >= 0; i--) {
|
||||
if(name[i] == '/' || name[i] == '\\') {
|
||||
i++;
|
||||
char *output = name();
|
||||
while(true) {
|
||||
*output++ = name[i];
|
||||
if(!name[i]) break;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
//remove filename and return path only ("/foo/bar.ext" -> "/foo/bar/")
|
||||
string Cartridge::basepath(const char *filename) {
|
||||
string path(filename);
|
||||
path.replace("\\", "/");
|
||||
|
||||
//remove filename
|
||||
for(signed i = strlen(path) - 1; i >= 0; i--) {
|
||||
if(path[i] == '/') {
|
||||
path[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!strend(path, "/")) path.append("/");
|
||||
return path;
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
class Cartridge : public property {
|
||||
public:
|
||||
enum Mode {
|
||||
ModeNormal,
|
||||
ModeBsxSlotted,
|
||||
ModeBsx,
|
||||
ModeSufamiTurbo,
|
||||
};
|
||||
|
||||
enum Type {
|
||||
TypeNormal,
|
||||
TypeBsxSlotted,
|
||||
TypeBsxBios,
|
||||
TypeBsx,
|
||||
TypeSufamiTurboBios,
|
||||
TypeSufamiTurbo,
|
||||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
BSXROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
|
||||
//warning: if loaded() == false, no other property is considered valid!
|
||||
|
||||
property_t<bool> loaded; //is a base cartridge inserted?
|
||||
property_t<bool> bsx_flash_loaded; //is a BS-X flash cart connected?
|
||||
property_t<bool> patched; //has a UPS patch been applied?
|
||||
property_t<string> name; //display name (filename sans path and extension)
|
||||
|
||||
property_t<Mode> mode;
|
||||
property_t<Region> region;
|
||||
property_t<MemoryMapper> mapper;
|
||||
property_t<DSP1MemoryMapper> dsp1_mapper;
|
||||
|
||||
property_t<bool> has_bsx_slot;
|
||||
property_t<bool> has_superfx;
|
||||
property_t<bool> has_sa1;
|
||||
property_t<bool> has_srtc;
|
||||
property_t<bool> has_sdd1;
|
||||
property_t<bool> has_spc7110, has_spc7110rtc;
|
||||
property_t<bool> has_cx4;
|
||||
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
|
||||
property_t<bool> has_obc1;
|
||||
property_t<bool> has_st010, has_st011, has_st018;
|
||||
|
||||
//main interface
|
||||
bool load_normal (const char *base);
|
||||
bool load_bsx_slotted (const char *base, const char *slot = "");
|
||||
bool load_bsx (const char *base, const char *slot = "");
|
||||
bool load_sufami_turbo(const char *base, const char *slotA = "", const char *slotB = "");
|
||||
void unload();
|
||||
|
||||
//utility functions
|
||||
static string filepath(const char *filename, const char *pathname); //"./bar.ext" -> "/foo/bar.ext"
|
||||
static string basename(const char *filename); //"/foo/bar.ext" -> "bar"
|
||||
static string basepath(const char *filename); //"/foo/bar.ext" -> "/foo/bar/"
|
||||
//this function will load 'filename', decompress it if needed, and determine what type of
|
||||
//image file 'filename' refers to (eg normal cart, BS-X flash cart, Sufami Turbo cart, etc.)
|
||||
//warning: this operation is very expensive, use sparingly!
|
||||
Type detect_image_type(const char *filename) const;
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
||||
private:
|
||||
void load_begin(Mode);
|
||||
void load_end();
|
||||
void unload_normal();
|
||||
void unload_bsx_slotted();
|
||||
void unload_bsx();
|
||||
void unload_sufami_turbo();
|
||||
|
||||
struct cartinfo_t {
|
||||
Type type;
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
unsigned rom_size, ram_size;
|
||||
|
||||
bool bsx_slot;
|
||||
bool superfx;
|
||||
bool sa1;
|
||||
bool srtc;
|
||||
bool sdd1;
|
||||
bool spc7110, spc7110rtc;
|
||||
bool cx4;
|
||||
bool dsp1, dsp2, dsp3, dsp4;
|
||||
bool obc1;
|
||||
bool st010, st011, st018;
|
||||
|
||||
void reset();
|
||||
cartinfo_t();
|
||||
};
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
RomType = 0x16,
|
||||
RomSize = 0x17,
|
||||
RamSize = 0x18,
|
||||
CartRegion = 0x19,
|
||||
Company = 0x1a,
|
||||
Version = 0x1b,
|
||||
Complement = 0x1c, //inverse checksum
|
||||
Checksum = 0x1e,
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
|
||||
unsigned find_header(const uint8_t *data, unsigned size) const;
|
||||
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
|
||||
void set_cartinfo(const cartinfo_t&);
|
||||
|
||||
bool load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const;
|
||||
bool load_ram (const char *filename, uint8_t *&data, unsigned size, uint8_t init_value) const;
|
||||
|
||||
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, unsigned &size, CompressionMode compression = CompressionNone) const;
|
||||
bool save_file(const char *fn, uint8 *data, unsigned size) const;
|
||||
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size) const;
|
||||
|
||||
string modify_extension(const char *filename, const char *extension) const;
|
||||
string get_filename(const char *source, const char *extension, const char *path) const;
|
||||
|
||||
struct {
|
||||
string filename;
|
||||
uint8_t *rom, *ram, *rtc;
|
||||
unsigned rom_size, ram_size, rtc_size;
|
||||
} cart;
|
||||
|
||||
struct {
|
||||
string filename;
|
||||
uint8_t *ram;
|
||||
unsigned ram_size;
|
||||
} bs;
|
||||
|
||||
struct {
|
||||
string filename;
|
||||
uint8_t *rom, *ram;
|
||||
unsigned rom_size, ram_size;
|
||||
} stA, stB;
|
||||
};
|
||||
|
||||
namespace memory {
|
||||
extern MappedRAM cartrom, cartram, cartrtc;
|
||||
extern MappedRAM bscram;
|
||||
extern MappedRAM stArom, stAram;
|
||||
extern MappedRAM stBrom, stBram;
|
||||
};
|
||||
|
||||
extern Cartridge cartridge;
|
||||
@@ -1,109 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
#include "../reader/filereader.hpp"
|
||||
|
||||
#if defined(GZIP_SUPPORT)
|
||||
#include "../reader/gzreader.hpp"
|
||||
#include "../reader/zipreader.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(JMA_SUPPORT)
|
||||
#include "../reader/jmareader.hpp"
|
||||
#endif
|
||||
|
||||
string Cartridge::modify_extension(const char *filename_, const char *extension) const {
|
||||
string filename = filename_;
|
||||
int i;
|
||||
for(i = strlen(filename); i >= 0; i--) {
|
||||
if(filename[i] == '.') break;
|
||||
if(filename[i] == '/') break;
|
||||
if(filename[i] == '\\') break;
|
||||
}
|
||||
if(i > 0 && filename[i] == '.') filename[i] = 0;
|
||||
return filename << "." << extension;
|
||||
}
|
||||
|
||||
string Cartridge::get_filename(const char *source, const char *extension, const char *path) const {
|
||||
return filepath(modify_extension(source, extension), path);
|
||||
}
|
||||
|
||||
bool Cartridge::load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression) const {
|
||||
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, snes.config.file.autodetect_type);
|
||||
|
||||
switch(filetype) { default:
|
||||
case Reader::Normal: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) return false;
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::GZIP: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) return false;
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::ZIP: {
|
||||
ZipReader zf(fn);
|
||||
if(!zf.ready()) return false;
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) const {
|
||||
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(snes.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, unsigned size) const {
|
||||
file fp;
|
||||
if(!fp.open(fn, file::mode_write)) return false;
|
||||
fp.write(data, size);
|
||||
fp.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,244 +0,0 @@
|
||||
#ifdef CART_CPP
|
||||
|
||||
//================
|
||||
//Normal cartridge
|
||||
//================
|
||||
|
||||
bool Cartridge::load_normal(const char *base) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
bool patch_applied;
|
||||
cart.filename = base;
|
||||
|
||||
load_begin(ModeNormal);
|
||||
if(load_image(base, data, size, patch_applied) == false) return false;
|
||||
|
||||
snes.config.path.current = basepath(cart.filename);
|
||||
if(patch_applied) set(patched, true);
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
|
||||
set_cartinfo(cartinfo);
|
||||
|
||||
if(cartinfo.ram_size > 0) {
|
||||
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
|
||||
}
|
||||
|
||||
if(cartinfo.srtc || cartinfo.spc7110rtc) {
|
||||
load_ram(get_filename(base, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size = 20, 0x00);
|
||||
}
|
||||
|
||||
load_end();
|
||||
set(name, basename(base));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cartridge::unload_normal() {
|
||||
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
|
||||
if(cart.rtc) save_file(get_filename(cart.filename, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size);
|
||||
}
|
||||
|
||||
//======================
|
||||
//BS-X slotted cartridge
|
||||
//======================
|
||||
|
||||
bool Cartridge::load_bsx_slotted(const char *base, const char *slot) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
bool patch_applied;
|
||||
cart.filename = base;
|
||||
bs.filename = slot;
|
||||
|
||||
load_begin(ModeBsxSlotted);
|
||||
if(load_image(base, data, size, patch_applied) == false) return false;
|
||||
|
||||
snes.config.path.current = basepath(cart.filename);
|
||||
if(patch_applied) set(patched, true);
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
|
||||
set_cartinfo(cartinfo);
|
||||
|
||||
if(load_image(slot, data, size, patch_applied) == true) {
|
||||
set(bsx_flash_loaded, true);
|
||||
if(patch_applied) set(patched, true);
|
||||
bs.ram = data;
|
||||
bs.ram_size = size;
|
||||
}
|
||||
|
||||
if(cartinfo.ram_size > 0) {
|
||||
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
|
||||
}
|
||||
|
||||
load_end();
|
||||
string filename = basename(base);
|
||||
if(*slot) filename << " + " << basename(slot);
|
||||
set(name, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cartridge::unload_bsx_slotted() {
|
||||
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
|
||||
}
|
||||
|
||||
//====================
|
||||
//BS-X flash cartridge
|
||||
//====================
|
||||
|
||||
bool Cartridge::load_bsx(const char *base, const char *slot) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
bool patch_applied;
|
||||
cart.filename = base;
|
||||
bs.filename = slot;
|
||||
|
||||
load_begin(ModeBsx);
|
||||
if(load_image(base, data, size, patch_applied) == false) return false;
|
||||
|
||||
snes.config.path.current = basepath(cart.filename);
|
||||
if(patch_applied) set(patched, true);
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
|
||||
set_cartinfo(cartinfo);
|
||||
|
||||
cart.ram = 0;
|
||||
cart.ram_size = 0;
|
||||
|
||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||
|
||||
if(load_file(get_filename(base, "srm", snes.config.path.save), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_file(get_filename(base, "psr", snes.config.path.save), data, size, CompressionNone) == true) {
|
||||
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
if(load_image(slot, data, size, patch_applied) == true) {
|
||||
set(bsx_flash_loaded, true);
|
||||
if(patch_applied) set(patched, true);
|
||||
bs.ram = data;
|
||||
bs.ram_size = size;
|
||||
}
|
||||
|
||||
load_end();
|
||||
set(name, !*slot ? basename(base) : basename(slot));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cartridge::unload_bsx() {
|
||||
save_file(get_filename(cart.filename, "srm", snes.config.path.save), bsxcart.sram.handle (), bsxcart.sram.size ());
|
||||
save_file(get_filename(cart.filename, "psr", snes.config.path.save), bsxcart.psram.handle(), bsxcart.psram.size());
|
||||
}
|
||||
|
||||
//============================
|
||||
//Sufami Turbo flash cartridge
|
||||
//============================
|
||||
|
||||
bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const char *slotB) {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
bool patch_applied;
|
||||
cart.filename = base;
|
||||
stA.filename = slotA;
|
||||
stB.filename = slotB;
|
||||
|
||||
load_begin(ModeSufamiTurbo);
|
||||
if(load_image(base, data, size, patch_applied) == false) return false;
|
||||
|
||||
snes.config.path.current = basepath(cart.filename);
|
||||
if(patch_applied) set(patched, true);
|
||||
|
||||
cartinfo_t cartinfo;
|
||||
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
|
||||
set_cartinfo(cartinfo);
|
||||
|
||||
if(load_image(slotA, data, size, patch_applied) == true) {
|
||||
if(patch_applied) set(patched, true);
|
||||
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||
memcpy(stA.rom, data, min(size, stA.rom_size));
|
||||
delete[] data;
|
||||
|
||||
load_ram(get_filename(slotA, "srm", snes.config.path.save), stA.ram, stA.ram_size = 0x020000, 0xff);
|
||||
}
|
||||
|
||||
if(load_image(slotB, data, size, patch_applied) == true) {
|
||||
if(patch_applied) set(patched, true);
|
||||
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||
memcpy(stB.rom, data, min(size, stB.rom_size));
|
||||
delete[] data;
|
||||
|
||||
load_ram(get_filename(slotB, "srm", snes.config.path.save), stB.ram, stB.ram_size = 0x020000, 0xff);
|
||||
}
|
||||
|
||||
load_end();
|
||||
string filename;
|
||||
if(!*slotA && !*slotB) filename << basename(base);
|
||||
else if( *slotA && !*slotB) filename << basename(slotA);
|
||||
else if(!*slotA && *slotB) filename << basename(slotB);
|
||||
else filename << basename(slotA) << " + " << basename(slotB);
|
||||
set(name, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cartridge::unload_sufami_turbo() {
|
||||
if(stA.ram) save_file(get_filename(stA.filename, "srm", snes.config.path.save), stA.ram, stA.ram_size);
|
||||
if(stB.ram) save_file(get_filename(stB.filename, "srm", snes.config.path.save), stB.ram, stB.ram_size);
|
||||
}
|
||||
|
||||
//=================
|
||||
//utility functions
|
||||
//=================
|
||||
|
||||
Cartridge::Type Cartridge::detect_image_type(const char *filename) const {
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
bool patch_applied;
|
||||
if(!load_image(filename, data, size, patch_applied)) return TypeUnknown;
|
||||
|
||||
cartinfo_t info;
|
||||
read_header(info, data, size);
|
||||
delete[] data;
|
||||
return info.type;
|
||||
}
|
||||
|
||||
bool Cartridge::load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const {
|
||||
if(!filename || !*filename) return false;
|
||||
if(!load_file(filename, data, size, CompressionAuto)) return false;
|
||||
|
||||
if((size & 0x7fff) == 512) {
|
||||
//remove 512-byte header
|
||||
memmove(data, data + 512, size -= 512);
|
||||
}
|
||||
|
||||
uint8_t *pdata;
|
||||
unsigned psize;
|
||||
if(load_file(get_filename(filename, "ups", snes.config.path.patch), pdata, psize, CompressionInspect) == true) {
|
||||
apply_patch(pdata, psize, data, size);
|
||||
delete[] pdata;
|
||||
patched = true;
|
||||
} else {
|
||||
patched = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init) const {
|
||||
data = new uint8_t[size];
|
||||
memset(data, init, size);
|
||||
|
||||
uint8_t *savedata;
|
||||
unsigned savesize;
|
||||
if(load_file(filename, savedata, savesize, CompressionNone) == false) return false;
|
||||
|
||||
memcpy(data, savedata, min(size, savesize));
|
||||
delete[] savedata;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
::@mingw32-make platform=win compiler=mingw32-gcc
|
||||
@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||
@pause
|
||||
@@ -1,2 +0,0 @@
|
||||
make platform=x compiler=gcc
|
||||
#make platform=x compiler=gcc enable_gzip=true enable_jma=true
|
||||
@@ -1 +0,0 @@
|
||||
@mingw32-make platform=win compiler=mingw32-gcc clean
|
||||
@@ -1 +0,0 @@
|
||||
make platform=x compiler=gcc clean
|
||||
@@ -1,74 +0,0 @@
|
||||
class CPU : public MMIO {
|
||||
public:
|
||||
virtual void enter() = 0;
|
||||
|
||||
//CPU version number
|
||||
//* 1 and 2 are known
|
||||
//* reported by $4210
|
||||
//* affects timing (DRAM refresh, HDMA init, etc)
|
||||
uint8 cpu_version;
|
||||
|
||||
virtual uint8 pio() = 0;
|
||||
virtual bool joylatch() = 0;
|
||||
virtual uint8 port_read(uint8 port) = 0;
|
||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||
|
||||
#include "cpuregs.hpp"
|
||||
regs_t regs;
|
||||
|
||||
virtual void scanline() = 0;
|
||||
virtual void power();
|
||||
virtual void reset();
|
||||
|
||||
/*****
|
||||
* 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,
|
||||
* the CPU may be in the middle of executing an opcode when the
|
||||
* emulator (e.g. debugger) wants to disassemble an opcode. this
|
||||
* would mean that important registers may not reflect what they
|
||||
* did at the start of the opcode (especially regs.pc), so in
|
||||
* cycle-based emulators, this function should be overridden to
|
||||
* reflect whether or not an opcode has only been partially
|
||||
* executed. if not, the debugger should abort attempts to skip,
|
||||
* disable, or disassemble the current opcode.
|
||||
*****/
|
||||
virtual bool in_opcode() { return false; }
|
||||
|
||||
/*****
|
||||
* opcode disassembler
|
||||
*****/
|
||||
enum {
|
||||
OPTYPE_DP = 0, //dp
|
||||
OPTYPE_DPX, //dp,x
|
||||
OPTYPE_DPY, //dp,y
|
||||
OPTYPE_IDP, //(dp)
|
||||
OPTYPE_IDPX, //(dp,x)
|
||||
OPTYPE_IDPY, //(dp),y
|
||||
OPTYPE_ILDP, //[dp]
|
||||
OPTYPE_ILDPY, //[dp],y
|
||||
OPTYPE_ADDR, //addr
|
||||
OPTYPE_ADDRX, //addr,x
|
||||
OPTYPE_ADDRY, //addr,y
|
||||
OPTYPE_IADDRX, //(addr,x)
|
||||
OPTYPE_ILADDR, //[addr]
|
||||
OPTYPE_LONG, //long
|
||||
OPTYPE_LONGX, //long, x
|
||||
OPTYPE_SR, //sr,s
|
||||
OPTYPE_ISRY, //(sr,s),y
|
||||
OPTYPE_ADDR_PC, //pbr:addr
|
||||
OPTYPE_IADDR_PC, //pbr:(addr)
|
||||
OPTYPE_RELB, //relb
|
||||
OPTYPE_RELW, //relw
|
||||
};
|
||||
|
||||
void disassemble_opcode(char *output);
|
||||
uint8 dreadb(uint32 addr);
|
||||
uint16 dreadw(uint32 addr);
|
||||
uint32 dreadl(uint32 addr);
|
||||
uint32 decode(uint8 offset_type, uint32 addr);
|
||||
uint8 opcode_length();
|
||||
|
||||
CPU();
|
||||
virtual ~CPU();
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
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 @@
|
||||
rm scpugen
|
||||
@@ -1,90 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
#include "opfn.cpp"
|
||||
|
||||
void sCPU::enter() {
|
||||
initialize:
|
||||
//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);
|
||||
|
||||
loop:
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
if(status.nmi_pending) {
|
||||
status.nmi_pending = false;
|
||||
status.interrupt_vector = (regs.e == false ? 0xffea : 0xfffa);
|
||||
} else if(status.irq_pending) {
|
||||
status.irq_pending = false;
|
||||
status.interrupt_vector = (regs.e == false ? 0xffee : 0xfffe);
|
||||
}
|
||||
op_irq();
|
||||
}
|
||||
|
||||
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
switch(op_readpc()) {
|
||||
#include "op_read.cpp"
|
||||
#include "op_write.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_misc.cpp"
|
||||
}
|
||||
status.in_opcode = false;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void sCPU::op_irq() {
|
||||
op_read(regs.pc.d);
|
||||
op_io();
|
||||
if(!regs.e) op_writestack(regs.pc.b);
|
||||
op_writestack(regs.pc.h);
|
||||
op_writestack(regs.pc.l);
|
||||
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
||||
rd.l = op_read(status.interrupt_vector + 0);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
rd.h = op_read(status.interrupt_vector + 1);
|
||||
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, txs,
|
||||
// inc, inx, iny, dec, dex, dey,
|
||||
// asl, lsr, rol, ror, nop, xce.
|
||||
alwaysinline void sCPU::op_io_irq() {
|
||||
if(status.interrupt_pending) {
|
||||
//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) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond4(uint16 x, uint16 y) {
|
||||
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_io_cond6(uint16 addr) {
|
||||
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
|
||||
op_io();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,298 +0,0 @@
|
||||
nop(0xea) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
}
|
||||
|
||||
wdm(0x42) {
|
||||
1:last_cycle();
|
||||
op_readpc();
|
||||
}
|
||||
|
||||
xba(0xeb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
mvn(0x54, ++),
|
||||
mvp(0x44, --) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readpc();
|
||||
3:regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
4:op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
5:op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l $1;
|
||||
regs.y.l $1;
|
||||
} else {
|
||||
regs.x.w $1;
|
||||
regs.y.w $1;
|
||||
}
|
||||
6:last_cycle();
|
||||
op_io();
|
||||
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);
|
||||
3:op_writestack(regs.pc.h);
|
||||
4:op_writestack(regs.pc.l);
|
||||
5:op_writestack(regs.p);
|
||||
6:rd.l = op_readlong(regs.e ? $1 : $3);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(regs.e ? $2 : $4);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
stp(0xdb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
while(true) op_io();
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
//last_cycle() will clear status.wai_lock once an NMI / IRQ edge is reached
|
||||
1:status.wai_lock = true;
|
||||
while(status.wai_lock) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
2:op_io();
|
||||
}
|
||||
|
||||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
clc(0x18, regs.p.c = 0),
|
||||
cld(0xd8, regs.p.d = 0),
|
||||
cli(0x58, regs.p.i = 0),
|
||||
clv(0xb8, regs.p.v = 0),
|
||||
sec(0x38, regs.p.c = 1),
|
||||
sed(0xf8, regs.p.d = 1),
|
||||
sei(0x78, regs.p.i = 1) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
$1;
|
||||
}
|
||||
|
||||
rep(0xc2, &=~),
|
||||
sep(0xe2, |=) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
op_io();
|
||||
regs.p $1 rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
tax(0xaa, regs.p.x, x, a),
|
||||
tay(0xa8, regs.p.x, y, a),
|
||||
txa(0x8a, regs.p.m, a, x),
|
||||
txy(0x9b, regs.p.x, y, x),
|
||||
tya(0x98, regs.p.m, a, y),
|
||||
tyx(0xbb, regs.p.x, x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l = regs.$3.l;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w = regs.$3.w;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tcd(0x5b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
}
|
||||
|
||||
tcs(0x1b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
tdc(0x7b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
tsc(0x3b) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
tsx(0xba) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
txs(0x9a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
}
|
||||
|
||||
pha(0x48, regs.p.m, a),
|
||||
phx(0xda, regs.p.x, x),
|
||||
phy(0x5a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:if(!$1)op_writestack(regs.$2.h);
|
||||
3:last_cycle();
|
||||
op_writestack(regs.$2.l);
|
||||
}
|
||||
|
||||
phd(0x0b) {
|
||||
1:op_io();
|
||||
2:op_writestackn(regs.d.h);
|
||||
3:last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
phb(0x8b, regs.db),
|
||||
phk(0x4b, regs.pc.b),
|
||||
php(0x08, regs.p) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
op_writestack($1);
|
||||
}
|
||||
|
||||
pla(0x68, regs.p.m, a),
|
||||
plx(0xfa, regs.p.x, x),
|
||||
ply(0x7a, regs.p.x, y) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:if($1)last_cycle();
|
||||
regs.$2.l = op_readstack();
|
||||
if($1) {
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
end;
|
||||
}
|
||||
4:last_cycle();
|
||||
regs.$2.h = op_readstack();
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
|
||||
pld(0x2b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.d.l = op_readstackn();
|
||||
4:last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
plb(0xab) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.db = op_readstack();
|
||||
regs.p.n = !!(regs.db & 0x80);
|
||||
regs.p.z = (regs.db == 0);
|
||||
}
|
||||
|
||||
plp(0x28) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
pea(0xf4) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestackn(aa.h);
|
||||
4:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
pei(0xd4) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_writestackn(aa.h);
|
||||
6:last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
per(0x62) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
4:op_writestackn(rd.h);
|
||||
5:last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
@@ -1,539 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//nop
|
||||
case 0xea: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
} break;
|
||||
|
||||
//wdm
|
||||
case 0x42: {
|
||||
last_cycle();
|
||||
op_readpc();
|
||||
} break;
|
||||
|
||||
//xba
|
||||
case 0xeb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.a.h ^= regs.a.l;
|
||||
regs.a.l ^= regs.a.h;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} break;
|
||||
|
||||
//mvn
|
||||
case 0x54: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l ++;
|
||||
regs.y.l ++;
|
||||
} else {
|
||||
regs.x.w ++;
|
||||
regs.y.w ++;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
//mvp
|
||||
case 0x44: {
|
||||
dp = op_readpc();
|
||||
sp = op_readpc();
|
||||
regs.db = dp;
|
||||
rd.l = op_readlong((sp << 16) | regs.x.w);
|
||||
op_writelong((dp << 16) | regs.y.w, rd.l);
|
||||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l --;
|
||||
regs.y.l --;
|
||||
} else {
|
||||
regs.x.w --;
|
||||
regs.y.w --;
|
||||
}
|
||||
last_cycle();
|
||||
op_io();
|
||||
if(regs.a.w--) regs.pc.w -= 3;
|
||||
} break;
|
||||
|
||||
//brk
|
||||
case 0x00: {
|
||||
op_readpc();
|
||||
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);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong(regs.e ? 0xffff : 0xffe7);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//cop
|
||||
case 0x02: {
|
||||
op_readpc();
|
||||
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);
|
||||
regs.pc.b = 0x00;
|
||||
regs.p.i = 1;
|
||||
regs.p.d = 0;
|
||||
last_cycle();
|
||||
rd.h = op_readlong(regs.e ? 0xfff5 : 0xffe5);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//stp
|
||||
case 0xdb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
while(true) op_io();
|
||||
} break;
|
||||
|
||||
//wai
|
||||
case 0xcb: {
|
||||
//last_cycle() will clear status.wai_lock once an NMI / IRQ edge is reached
|
||||
status.wai_lock = true;
|
||||
while(status.wai_lock) {
|
||||
last_cycle();
|
||||
op_io();
|
||||
}
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//xce
|
||||
case 0xfb: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
}
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//clc
|
||||
case 0x18: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.c = 0;
|
||||
} break;
|
||||
|
||||
//cld
|
||||
case 0xd8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.d = 0;
|
||||
} break;
|
||||
|
||||
//cli
|
||||
case 0x58: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.i = 0;
|
||||
} break;
|
||||
|
||||
//clv
|
||||
case 0xb8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.v = 0;
|
||||
} break;
|
||||
|
||||
//sec
|
||||
case 0x38: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.c = 1;
|
||||
} break;
|
||||
|
||||
//sed
|
||||
case 0xf8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.d = 1;
|
||||
} break;
|
||||
|
||||
//sei
|
||||
case 0x78: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.p.i = 1;
|
||||
} break;
|
||||
|
||||
//rep
|
||||
case 0xc2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p &=~ rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//sep
|
||||
case 0xe2: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.p |= rd.l;
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//tax
|
||||
case 0xaa: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.a.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.a.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tay
|
||||
case 0xa8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.a.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.a.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txa
|
||||
case 0x8a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.x.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.x.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txy
|
||||
case 0x9b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l = regs.x.l;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w = regs.x.w;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tya
|
||||
case 0x98: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l = regs.y.l;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w = regs.y.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tyx
|
||||
case 0xbb: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.y.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.y.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tcd
|
||||
case 0x5b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.d.w = regs.a.w;
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
} break;
|
||||
|
||||
//tcs
|
||||
case 0x1b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.s.w = regs.a.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//tdc
|
||||
case 0x7b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.d.w;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
|
||||
//tsc
|
||||
case 0x3b: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
regs.a.w = regs.s.w;
|
||||
if(regs.e) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//tsx
|
||||
case 0xba: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l = regs.s.l;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w = regs.s.w;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//txs
|
||||
case 0x9a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.e) {
|
||||
regs.s.l = regs.x.l;
|
||||
} else {
|
||||
regs.s.w = regs.x.w;
|
||||
}
|
||||
} break;
|
||||
|
||||
//pha
|
||||
case 0x48: {
|
||||
op_io();
|
||||
if(!regs.p.m)op_writestack(regs.a.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.a.l);
|
||||
} break;
|
||||
|
||||
//phx
|
||||
case 0xda: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.x.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.x.l);
|
||||
} break;
|
||||
|
||||
//phy
|
||||
case 0x5a: {
|
||||
op_io();
|
||||
if(!regs.p.x)op_writestack(regs.y.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.y.l);
|
||||
} break;
|
||||
|
||||
//phd
|
||||
case 0x0b: {
|
||||
op_io();
|
||||
op_writestackn(regs.d.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.d.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//phb
|
||||
case 0x8b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.db);
|
||||
} break;
|
||||
|
||||
//phk
|
||||
case 0x4b: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.b);
|
||||
} break;
|
||||
|
||||
//php
|
||||
case 0x08: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
|
||||
//pla
|
||||
case 0x68: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.m)last_cycle();
|
||||
regs.a.l = op_readstack();
|
||||
if(regs.p.m) {
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.a.h = op_readstack();
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
} break;
|
||||
|
||||
//plx
|
||||
case 0xfa: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.x.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.x.h = op_readstack();
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
} break;
|
||||
|
||||
//ply
|
||||
case 0x7a: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.x)last_cycle();
|
||||
regs.y.l = op_readstack();
|
||||
if(regs.p.x) {
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
regs.y.h = op_readstack();
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
} break;
|
||||
|
||||
//pld
|
||||
case 0x2b: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.d.l = op_readstackn();
|
||||
last_cycle();
|
||||
regs.d.h = op_readstackn();
|
||||
regs.p.n = !!(regs.d.w & 0x8000);
|
||||
regs.p.z = (regs.d.w == 0);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//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;
|
||||
|
||||
//plp
|
||||
case 0x28: {
|
||||
op_io();
|
||||
op_io();
|
||||
last_cycle();
|
||||
regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
} break;
|
||||
|
||||
//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;
|
||||
} break;
|
||||
|
||||
//pei
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
aa.l = op_readdp(dp);
|
||||
aa.h = op_readdp(dp + 1);
|
||||
op_writestackn(aa.h);
|
||||
last_cycle();
|
||||
op_writestackn(aa.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//per
|
||||
case 0x62: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.w = regs.pc.d + (int16)aa.w;
|
||||
op_writestackn(rd.h);
|
||||
last_cycle();
|
||||
op_writestackn(rd.l);
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,163 +0,0 @@
|
||||
bcc(0x90, !regs.p.c),
|
||||
bcs(0xb0, regs.p.c),
|
||||
bne(0xd0, !regs.p.z),
|
||||
beq(0xf0, regs.p.z),
|
||||
bpl(0x10, !regs.p.n),
|
||||
bmi(0x30, regs.p.n),
|
||||
bvc(0x50, !regs.p.v),
|
||||
bvs(0x70, regs.p.v) {
|
||||
1:if(!$1) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($1) {
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
} else {
|
||||
end;
|
||||
}
|
||||
2:op_io_cond6(aa.w);
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
}
|
||||
|
||||
bra(0x80) {
|
||||
1:rd.l = op_readpc();
|
||||
aa.w = regs.pc.d + (int8)rd.l;
|
||||
regs.pc.w = aa.w;
|
||||
2:op_io_cond6(aa.w);
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
}
|
||||
|
||||
brl(0x82) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = regs.pc.d + (int16)rd.w;
|
||||
}
|
||||
|
||||
jmp_addr(0x4c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_long(0x5c) {
|
||||
1:rd.l = op_readpc();
|
||||
2:rd.h = op_readpc();
|
||||
3:last_cycle();
|
||||
rd.b = op_readpc();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jmp_iaddr(0x6c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:last_cycle();
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x7c) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
5:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
}
|
||||
|
||||
jmp_iladdr(0xdc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readaddr(aa.w);
|
||||
4:rd.h = op_readaddr(aa.w + 1);
|
||||
5:last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
jsr_addr(0x20) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
5:last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
}
|
||||
|
||||
jsr_long(0x22) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_writestackn(regs.pc.b);
|
||||
4:op_io();
|
||||
5:aa.b = op_readpc();
|
||||
6:regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
7:last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
jsr_iaddrx(0xfc) {
|
||||
1:aa.l = op_readpc();
|
||||
2:op_writestackn(regs.pc.h);
|
||||
3:op_writestackn(regs.pc.l);
|
||||
4:aa.h = op_readpc();
|
||||
5:op_io();
|
||||
6:rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
7:last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
|
||||
rti(0x40) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.p = op_readstack();
|
||||
if(regs.e) regs.p |= 0x30;
|
||||
if(regs.p.x) {
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
}
|
||||
4:rd.l = op_readstack();
|
||||
5:if(regs.e) last_cycle();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
end;
|
||||
}
|
||||
6:last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
}
|
||||
|
||||
rts(0x60) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstack();
|
||||
4:rd.h = op_readstack();
|
||||
5:last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
}
|
||||
|
||||
rtl(0x6b) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:rd.l = op_readstackn();
|
||||
4:rd.h = op_readstackn();
|
||||
5:last_cycle();
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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 {
|
||||
break;
|
||||
}
|
||||
op_io_cond6(aa.w);
|
||||
last_cycle();
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//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;
|
||||
|
||||
//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;
|
||||
|
||||
//jmp_addr
|
||||
case 0x4c: {
|
||||
rd.l = op_readpc();
|
||||
last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//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;
|
||||
|
||||
//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;
|
||||
|
||||
//jmp_iaddrx
|
||||
case 0x7c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
} break;
|
||||
|
||||
//jmp_iladdr
|
||||
case 0xdc: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
rd.l = op_readaddr(aa.w);
|
||||
rd.h = op_readaddr(aa.w + 1);
|
||||
last_cycle();
|
||||
rd.b = op_readaddr(aa.w + 2);
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//jsr_addr
|
||||
case 0x20: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
regs.pc.w--;
|
||||
op_writestack(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestack(regs.pc.l);
|
||||
regs.pc.w = aa.w;
|
||||
} break;
|
||||
|
||||
//jsr_long
|
||||
case 0x22: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_writestackn(regs.pc.b);
|
||||
op_io();
|
||||
aa.b = op_readpc();
|
||||
regs.pc.w--;
|
||||
op_writestackn(regs.pc.h);
|
||||
last_cycle();
|
||||
op_writestackn(regs.pc.l);
|
||||
regs.pc.d = aa.d & 0xffffff;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//jsr_iaddrx
|
||||
case 0xfc: {
|
||||
aa.l = op_readpc();
|
||||
op_writestackn(regs.pc.h);
|
||||
op_writestackn(regs.pc.l);
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
rd.l = op_readpbr(aa.w + regs.x.w);
|
||||
last_cycle();
|
||||
rd.h = op_readpbr(aa.w + regs.x.w + 1);
|
||||
regs.pc.w = rd.w;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
//rti
|
||||
case 0x40: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
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();
|
||||
rd.h = op_readstack();
|
||||
if(regs.e) {
|
||||
regs.pc.w = rd.w;
|
||||
break;
|
||||
}
|
||||
last_cycle();
|
||||
rd.b = op_readstack();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
} break;
|
||||
|
||||
//rts
|
||||
case 0x60: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstack();
|
||||
rd.h = op_readstack();
|
||||
last_cycle();
|
||||
op_io();
|
||||
regs.pc.w = rd.w;
|
||||
regs.pc.w++;
|
||||
} break;
|
||||
|
||||
//rtl
|
||||
case 0x6b: {
|
||||
op_io();
|
||||
op_io();
|
||||
rd.l = op_readstackn();
|
||||
rd.h = op_readstackn();
|
||||
last_cycle();
|
||||
rd.b = op_readstackn();
|
||||
regs.pc.d = rd.d & 0xffffff;
|
||||
regs.pc.w++;
|
||||
if(regs.e) regs.s.h = 0x01;
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,317 +0,0 @@
|
||||
adc_const(0x69, adc, regs.p.m),
|
||||
and_const(0x29, and, regs.p.m),
|
||||
cmp_const(0xc9, cmp, regs.p.m),
|
||||
cpx_const(0xe0, cpx, regs.p.x),
|
||||
cpy_const(0xc0, cpy, regs.p.x),
|
||||
eor_const(0x49, eor, regs.p.m),
|
||||
lda_const(0xa9, lda, regs.p.m),
|
||||
ldx_const(0xa2, ldx, regs.p.x),
|
||||
ldy_const(0xa0, ldy, regs.p.x),
|
||||
ora_const(0x09, ora, regs.p.m),
|
||||
sbc_const(0xe9, sbc, regs.p.m) {
|
||||
1:if($2) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if($2) { op_$1_b(); end; }
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addr(0x6d, adc, regs.p.m),
|
||||
and_addr(0x2d, and, regs.p.m),
|
||||
bit_addr(0x2c, bit, regs.p.m),
|
||||
cmp_addr(0xcd, cmp, regs.p.m),
|
||||
cpx_addr(0xec, cpx, regs.p.x),
|
||||
cpy_addr(0xcc, cpy, regs.p.x),
|
||||
eor_addr(0x4d, eor, regs.p.m),
|
||||
lda_addr(0xad, lda, regs.p.m),
|
||||
ldx_addr(0xae, ldx, regs.p.x),
|
||||
ldy_addr(0xac, ldy, regs.p.x),
|
||||
ora_addr(0x0d, ora, regs.p.m),
|
||||
sbc_addr(0xed, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addrx(0x7d, adc, regs.p.m),
|
||||
and_addrx(0x3d, and, regs.p.m),
|
||||
bit_addrx(0x3c, bit, regs.p.m),
|
||||
cmp_addrx(0xdd, cmp, regs.p.m),
|
||||
eor_addrx(0x5d, eor, regs.p.m),
|
||||
lda_addrx(0xbd, lda, regs.p.m),
|
||||
ldy_addrx(0xbc, ldy, regs.p.x),
|
||||
ora_addrx(0x1d, ora, regs.p.m),
|
||||
sbc_addrx(0xfd, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.x.w);
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_addry(0x79, adc, regs.p.m),
|
||||
and_addry(0x39, and, regs.p.m),
|
||||
cmp_addry(0xd9, cmp, regs.p.m),
|
||||
eor_addry(0x59, eor, regs.p.m),
|
||||
lda_addry(0xb9, lda, regs.p.m),
|
||||
ldx_addry(0xbe, ldx, regs.p.x),
|
||||
ora_addry(0x19, ora, regs.p.m),
|
||||
sbc_addry(0xf9, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io_cond4(aa.w, aa.w + regs.y.w);
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_long(0x6f, adc, regs.p.m),
|
||||
and_long(0x2f, and, regs.p.m),
|
||||
cmp_long(0xcf, cmp, regs.p.m),
|
||||
eor_long(0x4f, eor, regs.p.m),
|
||||
lda_long(0xaf, lda, regs.p.m),
|
||||
ora_long(0x0f, ora, regs.p.m),
|
||||
sbc_long(0xef, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_longx(0x7f, adc, regs.p.m),
|
||||
and_longx(0x3f, and, regs.p.m),
|
||||
cmp_longx(0xdf, cmp, regs.p.m),
|
||||
eor_longx(0x5f, eor, regs.p.m),
|
||||
lda_longx(0xbf, lda, regs.p.m),
|
||||
ora_longx(0x1f, ora, regs.p.m),
|
||||
sbc_longx(0xff, sbc, regs.p.m) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dp(0x65, adc, regs.p.m),
|
||||
and_dp(0x25, and, regs.p.m),
|
||||
bit_dp(0x24, bit, regs.p.m),
|
||||
cmp_dp(0xc5, cmp, regs.p.m),
|
||||
cpx_dp(0xe4, cpx, regs.p.x),
|
||||
cpy_dp(0xc4, cpy, regs.p.x),
|
||||
eor_dp(0x45, eor, regs.p.m),
|
||||
lda_dp(0xa5, lda, regs.p.m),
|
||||
ldx_dp(0xa6, ldx, regs.p.x),
|
||||
ldy_dp(0xa4, ldy, regs.p.x),
|
||||
ora_dp(0x05, ora, regs.p.m),
|
||||
sbc_dp(0xe5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readdp(dp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_dpx(0x75, adc, regs.p.m),
|
||||
and_dpx(0x35, and, regs.p.m),
|
||||
bit_dpx(0x34, bit, regs.p.m),
|
||||
cmp_dpx(0xd5, cmp, regs.p.m),
|
||||
eor_dpx(0x55, eor, regs.p.m),
|
||||
lda_dpx(0xb5, lda, regs.p.m),
|
||||
ldy_dpx(0xb4, ldy, regs.p.x),
|
||||
ora_dpx(0x15, ora, regs.p.m),
|
||||
sbc_dpx(0xf5, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.x.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.x.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
ldx_dpy(0xb6, ldx, regs.p.x) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($2) last_cycle();
|
||||
rd.l = op_readdp(dp + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
5:last_cycle();
|
||||
rd.h = op_readdp(dp + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idp(0x72, adc, regs.p.m),
|
||||
and_idp(0x32, and, regs.p.m),
|
||||
cmp_idp(0xd2, cmp, regs.p.m),
|
||||
eor_idp(0x52, eor, regs.p.m),
|
||||
lda_idp(0xb2, lda, regs.p.m),
|
||||
ora_idp(0x12, ora, regs.p.m),
|
||||
sbc_idp(0xf2, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if($2) last_cycle();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
6:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpx(0x61, adc, regs.p.m),
|
||||
and_idpx(0x21, and, regs.p.m),
|
||||
cmp_idpx(0xc1, cmp, regs.p.m),
|
||||
eor_idpx(0x41, eor, regs.p.m),
|
||||
lda_idpx(0xa1, lda, regs.p.m),
|
||||
ora_idpx(0x01, ora, regs.p.m),
|
||||
sbc_idpx(0xe1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
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();
|
||||
rd.l = op_readdbr(aa.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_idpy(0x71, adc, regs.p.m),
|
||||
and_idpy(0x31, and, regs.p.m),
|
||||
cmp_idpy(0xd1, cmp, regs.p.m),
|
||||
eor_idpy(0x51, eor, regs.p.m),
|
||||
lda_idpy(0xb1, lda, regs.p.m),
|
||||
ora_idpy(0x11, ora, regs.p.m),
|
||||
sbc_idpy(0xf1, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
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();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildp(0x67, adc, regs.p.m),
|
||||
and_ildp(0x27, and, regs.p.m),
|
||||
cmp_ildp(0xc7, cmp, regs.p.m),
|
||||
eor_ildp(0x47, eor, regs.p.m),
|
||||
lda_ildp(0xa7, lda, regs.p.m),
|
||||
ora_ildp(0x07, ora, regs.p.m),
|
||||
sbc_ildp(0xe7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_ildpy(0x77, adc, regs.p.m),
|
||||
and_ildpy(0x37, and, regs.p.m),
|
||||
cmp_ildpy(0xd7, cmp, regs.p.m),
|
||||
eor_ildpy(0x57, eor, regs.p.m),
|
||||
lda_ildpy(0xb7, lda, regs.p.m),
|
||||
ora_ildpy(0x17, ora, regs.p.m),
|
||||
sbc_ildpy(0xf7, sbc, regs.p.m) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if($2) last_cycle();
|
||||
rd.l = op_readlong(aa.d + regs.y.w);
|
||||
if($2) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readlong(aa.d + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_sr(0x63, adc, regs.p.m),
|
||||
and_sr(0x23, and, regs.p.m),
|
||||
cmp_sr(0xc3, cmp, regs.p.m),
|
||||
eor_sr(0x43, eor, regs.p.m),
|
||||
lda_sr(0xa3, lda, regs.p.m),
|
||||
ora_sr(0x03, ora, regs.p.m),
|
||||
sbc_sr(0xe3, sbc, regs.p.m) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if($2) last_cycle();
|
||||
rd.l = op_readsp(sp);
|
||||
if($2) { op_$1_b(); end; }
|
||||
4:last_cycle();
|
||||
rd.h = op_readsp(sp + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
adc_isry(0x73, adc),
|
||||
and_isry(0x33, and),
|
||||
cmp_isry(0xd3, cmp),
|
||||
eor_isry(0x53, eor),
|
||||
lda_isry(0xb3, lda),
|
||||
ora_isry(0x13, ora),
|
||||
sbc_isry(0xf3, sbc) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readdbr(aa.w + regs.y.w);
|
||||
if(regs.p.m) { op_$1_b(); end; }
|
||||
7:last_cycle();
|
||||
rd.h = op_readdbr(aa.w + regs.y.w + 1);
|
||||
op_$1_w();
|
||||
}
|
||||
|
||||
bit_const(0x89) {
|
||||
1:if(regs.p.m) last_cycle();
|
||||
rd.l = op_readpc();
|
||||
if(regs.p.m) {
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
end;
|
||||
}
|
||||
2:last_cycle();
|
||||
rd.h = op_readpc();
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,181 +0,0 @@
|
||||
inc(0x1a, regs.p.m, a),
|
||||
inx(0xe8, regs.p.x, x),
|
||||
iny(0xc8, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w++;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
dec(0x3a, regs.p.m, a),
|
||||
dex(0xca, regs.p.x, x),
|
||||
dey(0x88, regs.p.x, y) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w--;
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
asl(0x0a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
lsr(0x4a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
rol(0x2a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
ror(0x6a) {
|
||||
1:last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = regs.p.c ? 0x80 : 0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
||||
inc_addr(0xee, inc),
|
||||
dec_addr(0xce, dec),
|
||||
asl_addr(0x0e, asl),
|
||||
lsr_addr(0x4e, lsr),
|
||||
rol_addr(0x2e, rol),
|
||||
ror_addr(0x6e, ror),
|
||||
trb_addr(0x1c, trb),
|
||||
tsb_addr(0x0c, tsb) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:rd.l = op_readdbr(aa.w);
|
||||
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();
|
||||
6:op_writedbr(aa.w + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w, rd.l);
|
||||
}
|
||||
|
||||
inc_addrx(0xfe, inc),
|
||||
dec_addrx(0xde, dec),
|
||||
asl_addrx(0x1e, asl),
|
||||
lsr_addrx(0x5e, lsr),
|
||||
rol_addrx(0x3e, rol),
|
||||
ror_addrx(0x7e, ror) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3: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);
|
||||
6:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, rd.l);
|
||||
}
|
||||
|
||||
inc_dp(0xe6, inc),
|
||||
dec_dp(0xc6, dec),
|
||||
asl_dp(0x06, asl),
|
||||
lsr_dp(0x46, lsr),
|
||||
rol_dp(0x26, rol),
|
||||
ror_dp(0x66, ror),
|
||||
trb_dp(0x14, trb),
|
||||
tsb_dp(0x04, tsb) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:rd.l = op_readdp(dp);
|
||||
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();
|
||||
6:op_writedp(dp + 1, rd.h); }
|
||||
7:last_cycle();
|
||||
op_writedp(dp, rd.l);
|
||||
}
|
||||
|
||||
inc_dpx(0xf6, inc),
|
||||
dec_dpx(0xd6, dec),
|
||||
asl_dpx(0x16, asl),
|
||||
lsr_dpx(0x56, lsr),
|
||||
rol_dpx(0x36, rol),
|
||||
ror_dpx(0x76, ror) {
|
||||
1:dp = op_readpc();
|
||||
2: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);
|
||||
6:op_io();
|
||||
if(regs.p.m) { op_$1_b(); }
|
||||
else { op_$1_w();
|
||||
7:op_writedp(dp + regs.x.w + 1, rd.h); }
|
||||
8:last_cycle();
|
||||
op_writedp(dp + regs.x.w, rd.l);
|
||||
}
|
||||
@@ -1,573 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//inc
|
||||
case 0x1a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l++;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w++;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//inx
|
||||
case 0xe8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l++;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w++;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//iny
|
||||
case 0xc8: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l++;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w++;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dec
|
||||
case 0x3a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.a.l--;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w--;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dex
|
||||
case 0xca: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.x.l--;
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w--;
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//dey
|
||||
case 0x88: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.x) {
|
||||
regs.y.l--;
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w--;
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//asl
|
||||
case 0x0a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//lsr
|
||||
case 0x4a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//rol
|
||||
case 0x2a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//ror
|
||||
case 0x6a: {
|
||||
last_cycle();
|
||||
op_io_irq();
|
||||
uint16 c;
|
||||
if(regs.p.m) {
|
||||
c = regs.p.c ? 0x80 : 0;
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = regs.p.c ? 0x8000 : 0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
//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);
|
||||
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;
|
||||
|
||||
#endif
|
||||
@@ -1,181 +0,0 @@
|
||||
sta_addr(0x8d, regs.p.m, regs.a.w),
|
||||
stx_addr(0x8e, regs.p.x, regs.x.w),
|
||||
sty_addr(0x8c, regs.p.x, regs.y.w),
|
||||
stz_addr(0x9c, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:if($1) last_cycle();
|
||||
op_writedbr(aa.w, $2);
|
||||
if($1) end;
|
||||
4:last_cycle();
|
||||
op_writedbr(aa.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addrx(0x9d, regs.p.m, regs.a.w),
|
||||
stz_addrx(0x9e, regs.p.m, 0x0000) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if($1) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, $2);
|
||||
if($1) end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_addry(0x99) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:op_io();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_long(0x8f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_longx(0x9f) {
|
||||
1:aa.l = op_readpc();
|
||||
2:aa.h = op_readpc();
|
||||
3:aa.b = op_readpc();
|
||||
4:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
5:last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_dp(0x85, regs.p.m, regs.a.w),
|
||||
stx_dp(0x86, regs.p.x, regs.x.w),
|
||||
sty_dp(0x84, regs.p.x, regs.y.w),
|
||||
stz_dp(0x64, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:if($1) last_cycle();
|
||||
op_writedp(dp, $2);
|
||||
if($1) end;
|
||||
4:last_cycle();
|
||||
op_writedp(dp + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
sta_dpx(0x95, regs.p.m, regs.a.w),
|
||||
sty_dpx(0x94, regs.p.x, regs.y.w),
|
||||
stz_dpx(0x74, regs.p.m, 0x0000) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if($1) last_cycle();
|
||||
op_writedp(dp + regs.x.w, $2);
|
||||
if($1) end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, $2 >> 8);
|
||||
}
|
||||
|
||||
stx_dpy(0x96) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:op_io();
|
||||
4:if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x) end;
|
||||
5:last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
}
|
||||
|
||||
sta_idp(0x92) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
6:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_ildp(0x87) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_idpx(0x81) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
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();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_idpy(0x91) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_ildpy(0x97) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io_cond2();
|
||||
3:aa.l = op_readdp(dp);
|
||||
4:aa.h = op_readdp(dp + 1);
|
||||
5:aa.b = op_readdp(dp + 2);
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_sr(0x83) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:if(regs.p.m) last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
4:last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
}
|
||||
|
||||
sta_isry(0x93) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:aa.l = op_readsp(sp);
|
||||
4:aa.h = op_readsp(sp + 1);
|
||||
5:op_io();
|
||||
6:if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) end;
|
||||
7:last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
#ifdef SCPU_CPP
|
||||
|
||||
//sta_addr
|
||||
case 0x8d: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//stx_addr
|
||||
case 0x8e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedbr(aa.w, regs.x.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.x.w >> 8);
|
||||
} break;
|
||||
|
||||
//sty_addr
|
||||
case 0x8c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedbr(aa.w, regs.y.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_addr
|
||||
case 0x9c: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//sta_addrx
|
||||
case 0x9d: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_addrx
|
||||
case 0x9e: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//sta_addry
|
||||
case 0x99: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_long
|
||||
case 0x8f: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_longx
|
||||
case 0x9f: {
|
||||
aa.l = op_readpc();
|
||||
aa.h = op_readpc();
|
||||
aa.b = op_readpc();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writelong(aa.d + regs.x.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_dp
|
||||
case 0x85: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//stx_dp
|
||||
case 0x86: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp, regs.x.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.x.w >> 8);
|
||||
} break;
|
||||
|
||||
//sty_dp
|
||||
case 0x84: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp, regs.y.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_dp
|
||||
case 0x64: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//sta_dpx
|
||||
case 0x95: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.a.w);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
|
||||
} break;
|
||||
|
||||
//sty_dpx
|
||||
case 0x94: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.x.w, regs.y.w);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
|
||||
} break;
|
||||
|
||||
//stz_dpx
|
||||
case 0x74: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writedp(dp + regs.x.w, 0x0000);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
|
||||
} break;
|
||||
|
||||
//stx_dpy
|
||||
case 0x96: {
|
||||
dp = op_readpc();
|
||||
op_io_cond2();
|
||||
op_io();
|
||||
if(regs.p.x) last_cycle();
|
||||
op_writedp(dp + regs.y.w, regs.x.l);
|
||||
if(regs.p.x) break;
|
||||
last_cycle();
|
||||
op_writedp(dp + regs.y.w + 1, regs.x.h);
|
||||
} break;
|
||||
|
||||
//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();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//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();
|
||||
op_writelong(aa.d, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//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();
|
||||
op_writedbr(aa.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//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();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//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();
|
||||
op_writelong(aa.d + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//sta_sr
|
||||
case 0x83: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
if(regs.p.m) last_cycle();
|
||||
op_writesp(sp, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writesp(sp + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
//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();
|
||||
op_writedbr(aa.w + regs.y.w, regs.a.l);
|
||||
if(regs.p.m) break;
|
||||
last_cycle();
|
||||
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,12 +0,0 @@
|
||||
#define CLASS_NAME "sCPU"
|
||||
#include <tool/opgen_switch.cpp>
|
||||
|
||||
int main() {
|
||||
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");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
#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.
|
||||
* mem_read / mem_write indicate memory access bus cycles.
|
||||
* they are either 6, 8, or 12 bus cycles long, depending
|
||||
* both on location and the $420d.d0 FastROM enable bit.
|
||||
*****/
|
||||
|
||||
void sCPU::op_io() {
|
||||
status.clock_count = 6;
|
||||
precycle_edge();
|
||||
add_clocks(6);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
uint8 sCPU::op_read(uint32 addr) {
|
||||
status.clock_count = bus.speed(addr);
|
||||
precycle_edge();
|
||||
add_clocks(status.clock_count - 4);
|
||||
regs.mdr = bus.read(addr);
|
||||
add_clocks(4);
|
||||
cycle_edge();
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void sCPU::op_write(uint32 addr, uint8 data) {
|
||||
status.clock_count = bus.speed(addr);
|
||||
precycle_edge();
|
||||
add_clocks(status.clock_count);
|
||||
regs.mdr = data;
|
||||
bus.write(addr, regs.mdr);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline uint8 sCPU::op_readpc() {
|
||||
return op_read((regs.pc.b << 16) + regs.pc.w++);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readstack() {
|
||||
if(regs.e) {
|
||||
regs.s.l++;
|
||||
} else {
|
||||
regs.s.w++;
|
||||
}
|
||||
return op_read(regs.s.w);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readstackn() {
|
||||
return op_read(++regs.s.w);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readaddr(uint32 addr) {
|
||||
return op_read(addr & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readlong(uint32 addr) {
|
||||
return op_read(addr & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readdbr(uint32 addr) {
|
||||
return op_read(((regs.db << 16) + addr) & 0xffffff);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readpbr(uint32 addr) {
|
||||
return op_read((regs.pc.b << 16) + (addr & 0xffff));
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readdp(uint32 addr) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
|
||||
} else {
|
||||
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline uint8 sCPU::op_readsp(uint32 addr) {
|
||||
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writestack(uint8 data) {
|
||||
op_write(regs.s.w, data);
|
||||
if(regs.e) {
|
||||
regs.s.l--;
|
||||
} else {
|
||||
regs.s.w--;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writestackn(uint8 data) {
|
||||
op_write(regs.s.w--, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writeaddr(uint32 addr, uint8 data) {
|
||||
op_write(addr & 0xffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writelong(uint32 addr, uint8 data) {
|
||||
op_write(addr & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writedbr(uint32 addr, uint8 data) {
|
||||
op_write(((regs.db << 16) + addr) & 0xffffff, data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writepbr(uint32 addr, uint8 data) {
|
||||
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
|
||||
if(regs.e && regs.d.l == 0x00) {
|
||||
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
|
||||
} else {
|
||||
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
|
||||
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
|
||||
}
|
||||
|
||||
#endif //ifdef SCPU_CPP
|
||||
@@ -1,35 +0,0 @@
|
||||
/*****
|
||||
* CPU<>APU communication ports
|
||||
*****/
|
||||
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);
|
||||
void op_write(uint32 addr, uint8 data);
|
||||
|
||||
/*****
|
||||
* helper memory addressing functions used by CPU core
|
||||
*****/
|
||||
uint8 op_readpc ();
|
||||
uint8 op_readstack ();
|
||||
uint8 op_readstackn();
|
||||
uint8 op_readaddr (uint32 addr);
|
||||
uint8 op_readlong (uint32 addr);
|
||||
uint8 op_readdbr (uint32 addr);
|
||||
uint8 op_readpbr (uint32 addr);
|
||||
uint8 op_readdp (uint32 addr);
|
||||
uint8 op_readsp (uint32 addr);
|
||||
|
||||
void op_writestack (uint8 data);
|
||||
void op_writestackn(uint8 data);
|
||||
void op_writeaddr (uint32 addr, uint8 data);
|
||||
void op_writelong (uint32 addr, uint8 data);
|
||||
void op_writedbr (uint32 addr, uint8 data);
|
||||
void op_writepbr (uint32 addr, uint8 data);
|
||||
void op_writedp (uint32 addr, uint8 data);
|
||||
void op_writesp (uint32 addr, uint8 data);
|
||||
@@ -1,61 +0,0 @@
|
||||
#include <../base.hpp>
|
||||
#define SCPU_CPP
|
||||
|
||||
#include <nall/priorityqueue.hpp>
|
||||
priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu));
|
||||
|
||||
#include "core/core.cpp"
|
||||
#include "dma/dma.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "mmio/mmio.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
void sCPU::power() {
|
||||
CPU::power();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
|
||||
mmio_power();
|
||||
dma_power();
|
||||
timing_power();
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void sCPU::reset() {
|
||||
CPU::reset();
|
||||
|
||||
regs.pc.d = 0x000000;
|
||||
regs.pc.l = bus.read(0xfffc);
|
||||
regs.pc.h = bus.read(0xfffd);
|
||||
|
||||
//note: some registers are not fully reset by SNES
|
||||
regs.x.h = 0x00;
|
||||
regs.y.h = 0x00;
|
||||
regs.s.h = 0x01;
|
||||
regs.d = 0x0000;
|
||||
regs.db = 0x00;
|
||||
regs.p = 0x34;
|
||||
regs.e = 1;
|
||||
regs.mdr = 0x00;
|
||||
|
||||
status.wai_lock = false;
|
||||
status.interrupt_pending = false;
|
||||
status.interrupt_vector = 0xfffc; //reset vector address
|
||||
|
||||
mmio_reset();
|
||||
dma_reset();
|
||||
timing_reset();
|
||||
|
||||
apu_port[0] = 0x00;
|
||||
apu_port[1] = 0x00;
|
||||
apu_port[2] = 0x00;
|
||||
apu_port[3] = 0x00;
|
||||
}
|
||||
|
||||
sCPU::sCPU() {
|
||||
}
|
||||
|
||||
sCPU::~sCPU() {
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#include "cheat/cheat.hpp"
|
||||
|
||||
#include "memory/memory.hpp"
|
||||
#include "memory/smemory/smemory.hpp"
|
||||
|
||||
#include "cpu/cpu.hpp"
|
||||
#include "cpu/scpu/scpu.hpp"
|
||||
|
||||
#include "ppu/ppu.hpp"
|
||||
#include "ppu/bppu/bppu.hpp"
|
||||
|
||||
#include "smp/smp.hpp"
|
||||
#include "smp/ssmp/ssmp.hpp"
|
||||
|
||||
#include "dsp/dsp.hpp"
|
||||
#include "dsp/sdsp/sdsp.hpp"
|
||||
|
||||
extern BUSCORE bus;
|
||||
extern CPUCORE cpu;
|
||||
extern SMPCORE smp;
|
||||
extern DSPCORE dsp;
|
||||
extern PPUCORE ppu;
|
||||
|
||||
#include "snes/snes.hpp"
|
||||
@@ -1,157 +0,0 @@
|
||||
/* broken -- need to port libstring to bstring */
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libstring.h"
|
||||
#include "libstring.cpp"
|
||||
|
||||
FILE *fp, *fph, *fpt;
|
||||
|
||||
stringarray data, line, part, subpart;
|
||||
stringarray output_table, output_header, output_op;
|
||||
|
||||
struct _op_list {
|
||||
stringarray name, arg;
|
||||
} op_list[64];
|
||||
|
||||
int32 op_count, line_num;
|
||||
|
||||
void clear_op_list() {
|
||||
op_count = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
strcpy(op_list[i].name, "");
|
||||
for(int l = 0; l < 8; l++) {
|
||||
strcpy(op_list[i].arg[l], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_header() {
|
||||
int i = line_num;
|
||||
char t[4096];
|
||||
clear_op_list();
|
||||
while(1) {
|
||||
int z = op_count++;
|
||||
strcpy(part, line[i]);
|
||||
strrtrim(part, "),");
|
||||
strrtrim(part, ") {");
|
||||
split(subpart, "(", part);
|
||||
strcpy(op_list[z].name, subpart[0]);
|
||||
split(part, ", ", subpart[1]);
|
||||
for(int l = 0; l < count(part); l++) {
|
||||
strcpy(op_list[z].arg[l], part[l]);
|
||||
}
|
||||
if(strend(line[i], " {"))break;
|
||||
i++;
|
||||
}
|
||||
|
||||
sprintf(output_op, "void " CLASS_NAME "::op_$$() {\r\n switch(status.cycle_pos++) {\r\n");
|
||||
sprintf(output_header, "void op_$$();\r\n");
|
||||
sprintf(output_table, "optbl[$0] = &" CLASS_NAME "::op_$$;\r\n");
|
||||
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void update_line(int i, int n) {
|
||||
char t[4096];
|
||||
replace(line[i], "end;", "status.cycle_pos = 0;");
|
||||
replace(line[i], "skip;", "status.cycle_pos++;");
|
||||
}
|
||||
|
||||
void gen_op() {
|
||||
int i = line_num, n, c;
|
||||
char t[4096];
|
||||
while(1) {
|
||||
if(strmatch(line[i], "}"))break;
|
||||
|
||||
n = strdec(line[i]);
|
||||
sprintf(t, "%d:", n);
|
||||
strltrim(line[i], t);
|
||||
sprintf(t, " case %d: {\r\n", n);
|
||||
strcat(output_op, t);
|
||||
|
||||
update_line(i, n);
|
||||
if(!strmatch(line[i], "")) {
|
||||
strcat(output_op, " ");
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
}
|
||||
|
||||
i++;
|
||||
while(1) {
|
||||
if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || strmatch(line[i], "}"))break;
|
||||
|
||||
update_line(i, n);
|
||||
strcat(output_op, " ");
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if(strmatch(line[i], "}")) {
|
||||
strcat(output_op, " status.cycle_pos = 0;\r\n");
|
||||
}
|
||||
|
||||
strcat(output_op, " } break;\r\n");
|
||||
}
|
||||
strcat(output_op, " }\r\n}");
|
||||
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void gen_final() {
|
||||
string t;
|
||||
for(int i = 0; i < op_count; i++) {
|
||||
strcpy(t, output_op);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
replace(t, "$1", op_list[i].arg[1]);
|
||||
replace(t, "$2", op_list[i].arg[2]);
|
||||
replace(t, "$3", op_list[i].arg[3]);
|
||||
replace(t, "$4", op_list[i].arg[4]);
|
||||
replace(t, "$5", op_list[i].arg[5]);
|
||||
replace(t, "$6", op_list[i].arg[6]);
|
||||
replace(t, "$7", op_list[i].arg[7]);
|
||||
fprintf(fp, "%s\r\n\r\n", strptr(t));
|
||||
|
||||
strcpy(t, output_header);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
fprintf(fph, "%s", strptr(t));
|
||||
|
||||
strcpy(t, output_table);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
fprintf(fpt, "%s", strptr(t));
|
||||
}
|
||||
}
|
||||
|
||||
void generate(char *dest, char *src) {
|
||||
fp = fopen(src, "rb");
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
int fsize = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
char *buf = (char*)malloc(fsize + 1);
|
||||
fread(buf, 1, fsize, fp);
|
||||
fclose(fp);
|
||||
buf[fsize] = 0;
|
||||
|
||||
strcpy(data, buf);
|
||||
free(buf);
|
||||
replace(data, "\r\n", "\n");
|
||||
split(line, "\n", data);
|
||||
|
||||
fp = fopen(dest, "wb");
|
||||
|
||||
line_num = 0;
|
||||
while(line_num < count(line)) {
|
||||
while(line_num < count(line) && strmatch(line[line_num], ""))line_num++;
|
||||
if(line_num >= count(line))break;
|
||||
|
||||
gen_header();
|
||||
gen_op();
|
||||
gen_final();
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/* broken -- need to port libstring to bstring */
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libstring.h"
|
||||
#include "libstring.cpp"
|
||||
|
||||
FILE *fp, *fph, *fpt;
|
||||
|
||||
stringarray data, line, part, subpart;
|
||||
stringarray output_table, output_header, output_op;
|
||||
|
||||
struct _op_list {
|
||||
stringarray name, arg;
|
||||
} op_list[64];
|
||||
|
||||
int32 op_count, line_num;
|
||||
|
||||
void clear_op_list() {
|
||||
op_count = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
strcpy(op_list[i].name, "");
|
||||
for(int l = 0; l < 8; l++) {
|
||||
strcpy(op_list[i].arg[l], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_header() {
|
||||
int i = line_num;
|
||||
char t[4096];
|
||||
clear_op_list();
|
||||
while(1) {
|
||||
int z = op_count++;
|
||||
strcpy(part, line[i]);
|
||||
strrtrim(part, "),");
|
||||
strrtrim(part, ") {");
|
||||
split(subpart, "(", part);
|
||||
strcpy(op_list[z].name, subpart[0]);
|
||||
split(part, ", ", subpart[1]);
|
||||
for(int l = 0; l < count(part); l++) {
|
||||
strcpy(op_list[z].arg[l], part[l]);
|
||||
}
|
||||
if(strend(line[i], " {"))break;
|
||||
i++;
|
||||
}
|
||||
|
||||
sprintf(output_op, "void " CLASS_NAME "::op_$$() {\r\n");
|
||||
sprintf(output_header, "void op_$$();\r\n");
|
||||
sprintf(output_table, "optbl[$0] = &" CLASS_NAME "::op_$$;\r\n");
|
||||
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void update_line(int i) {
|
||||
char t[4096];
|
||||
replace(line[i], "end;", "return;");
|
||||
}
|
||||
|
||||
void gen_op() {
|
||||
int i = line_num, n, c;
|
||||
char t[4096];
|
||||
while(1) {
|
||||
if(!strcmp(line[i], "}"))break;
|
||||
|
||||
n = strdec(line[i]);
|
||||
sprintf(t, "%d:", n);
|
||||
strltrim(line[i], t);
|
||||
//sprintf(t, " case %d: {\r\n", n);
|
||||
//strcat(output_op, t);
|
||||
|
||||
update_line(i);
|
||||
if(strcmp(line[i], "")) {
|
||||
strcat(output_op, " ");
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
}
|
||||
|
||||
i++;
|
||||
while(1) {
|
||||
if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || !strcmp(line[i], "}"))break;
|
||||
|
||||
update_line(i);
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
strcat(output_op, "}");
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void gen_final() {
|
||||
string t;
|
||||
for(int i = 0; i < op_count; i++) {
|
||||
strcpy(t, output_op);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
replace(t, "$1", op_list[i].arg[1]);
|
||||
replace(t, "$2", op_list[i].arg[2]);
|
||||
replace(t, "$3", op_list[i].arg[3]);
|
||||
replace(t, "$4", op_list[i].arg[4]);
|
||||
replace(t, "$5", op_list[i].arg[5]);
|
||||
replace(t, "$6", op_list[i].arg[6]);
|
||||
replace(t, "$7", op_list[i].arg[7]);
|
||||
fprintf(fp, "%s\r\n\r\n", strptr(t));
|
||||
|
||||
strcpy(t, output_header);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
fprintf(fph, "%s", strptr(t));
|
||||
|
||||
strcpy(t, output_table);
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
fprintf(fpt, "%s", strptr(t));
|
||||
}
|
||||
}
|
||||
|
||||
void generate(char *dest, char *src) {
|
||||
fp = fopen(src, "rb");
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
int fsize = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
char *buf = (char*)malloc(fsize + 1);
|
||||
fread(buf, 1, fsize, fp);
|
||||
fclose(fp);
|
||||
buf[fsize] = 0;
|
||||
|
||||
strcpy(data, buf);
|
||||
free(buf);
|
||||
replace(data, "\r\n", "\n");
|
||||
split(line, "\n", data);
|
||||
|
||||
fp = fopen(dest, "wb");
|
||||
|
||||
line_num = 0;
|
||||
while(line_num < count(line)) {
|
||||
while(line_num < count(line) && !strcmp(line[line_num], ""))line_num++;
|
||||
if(line_num >= count(line))break;
|
||||
|
||||
gen_header();
|
||||
gen_op();
|
||||
gen_final();
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
#include <nall/string.hpp>
|
||||
using namespace nall;
|
||||
|
||||
FILE *fp;
|
||||
|
||||
string data, output_op;
|
||||
lstring line, part, subpart;
|
||||
|
||||
struct OpList {
|
||||
string name;
|
||||
lstring arg;
|
||||
} op_list[64];
|
||||
|
||||
int32_t op_count, line_num;
|
||||
|
||||
void clear_op_list() {
|
||||
op_count = 0;
|
||||
for(unsigned i = 0; i < 64; i++) {
|
||||
strcpy(op_list[i].name, "");
|
||||
for(unsigned l = 0; l < 8; l++) {
|
||||
strcpy(op_list[i].arg[l], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_begin() {
|
||||
int i = line_num;
|
||||
clear_op_list();
|
||||
|
||||
while(true) {
|
||||
int z = op_count++;
|
||||
string temp = line[i];
|
||||
rtrim(temp, "),");
|
||||
rtrim(temp, ") {");
|
||||
split(subpart, "(", temp);
|
||||
strcpy(op_list[z].name, subpart[0]);
|
||||
split(part, ", ", subpart[1]);
|
||||
for(unsigned l = 0; l < count(part); l++) {
|
||||
strcpy(op_list[z].arg[l], part[l]);
|
||||
}
|
||||
if(strend(line[i], " {") == true) break;
|
||||
i++;
|
||||
}
|
||||
|
||||
strcpy(output_op, "//$$\r\ncase $0: {\r\n");
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void update_line(int i) {
|
||||
replace(line[i], "end;", "break;");
|
||||
}
|
||||
|
||||
void gen_op() {
|
||||
int i = line_num, n, c;
|
||||
char t[4096];
|
||||
while(true) {
|
||||
if(!strcmp(line[i], "}"))break;
|
||||
|
||||
//remove cycle number
|
||||
n = strdec((const char*)line[i]);
|
||||
sprintf(t, "%d:", n);
|
||||
ltrim(line[i], t);
|
||||
//sprintf(t, "//%d:\r\n", n);
|
||||
//strcat(output_op, t);
|
||||
|
||||
update_line(i);
|
||||
if(strcmp(line[i], "")) {
|
||||
strcat(output_op, " ");
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
}
|
||||
|
||||
i++;
|
||||
while(true) {
|
||||
if(line[i][1] == ':' || line[i][2] == ':' || line[i] == "}") break;
|
||||
|
||||
update_line(i);
|
||||
strcat(output_op, line[i]);
|
||||
strcat(output_op, "\r\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
strcat(output_op, "} break;");
|
||||
line_num = i + 1;
|
||||
}
|
||||
|
||||
void gen_end() {
|
||||
string t;
|
||||
for(unsigned i = 0; i < op_count; i++) {
|
||||
t = output_op;
|
||||
replace(t, "$$", op_list[i].name);
|
||||
replace(t, "$0", op_list[i].arg[0]);
|
||||
replace(t, "$1", op_list[i].arg[1]);
|
||||
replace(t, "$2", op_list[i].arg[2]);
|
||||
replace(t, "$3", op_list[i].arg[3]);
|
||||
replace(t, "$4", op_list[i].arg[4]);
|
||||
replace(t, "$5", op_list[i].arg[5]);
|
||||
replace(t, "$6", op_list[i].arg[6]);
|
||||
replace(t, "$7", op_list[i].arg[7]);
|
||||
fprintf(fp, "%s\r\n\r\n", (const char*)t);
|
||||
}
|
||||
}
|
||||
|
||||
void generate(const char *dest, const char *src) {
|
||||
fread(data, src);
|
||||
replace(data, "\r\n", "\n");
|
||||
split(line, "\n", data);
|
||||
|
||||
fp = fopen(dest, "wb");
|
||||
string header = CLASS_NAME;
|
||||
fprintf(fp, "#ifdef %s_CPP\n\n", (const char*)strupper(header)); //inclusion guard
|
||||
|
||||
line_num = 0;
|
||||
while(line_num < count(line)) {
|
||||
while(line_num < count(line) && !strcmp(line[line_num], "")) line_num++;
|
||||
if(line_num >= count(line)) break;
|
||||
|
||||
gen_begin();
|
||||
gen_op();
|
||||
gen_end();
|
||||
}
|
||||
|
||||
fprintf(fp, "#endif\n");
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#include <../base.hpp>
|
||||
#define SMP_CPP
|
||||
|
||||
#include "iplrom.hpp"
|
||||
#include "dsmp.cpp"
|
||||
@@ -1,4 +0,0 @@
|
||||
g++ -c ssmpgen.cpp -I../../../lib
|
||||
g++ -c ../../../lib/nall/string.cpp -I../../../lib
|
||||
g++ -o ssmpgen ssmpgen.o string.o
|
||||
rm *.o
|
||||
@@ -1 +0,0 @@
|
||||
rm ssmpgen
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
#include "opfn.cpp"
|
||||
|
||||
void sSMP::enter() { loop:
|
||||
tracer.trace_smpop(); //traces SMP opcode (only if tracer is enabled)
|
||||
|
||||
status.in_opcode = true;
|
||||
switch(op_readpc()) {
|
||||
#include "op_mov.cpp"
|
||||
#include "op_pc.cpp"
|
||||
#include "op_read.cpp"
|
||||
#include "op_rmw.cpp"
|
||||
#include "op_misc.cpp"
|
||||
}
|
||||
status.in_opcode = false;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
#endif //ifdef SSMP_CPP
|
||||
@@ -1,163 +0,0 @@
|
||||
nop(0x00) {
|
||||
1:op_io();
|
||||
}
|
||||
|
||||
sleep(0xef),
|
||||
stop(0xff) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
regs.pc--;
|
||||
}
|
||||
|
||||
xcn(0x9f) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
daa(0xdf) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
}
|
||||
if(regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a += 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
das(0xbe) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
}
|
||||
if(!regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a -= 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
clrc(0x60, regs.p.c = 0),
|
||||
clrp(0x20, regs.p.p = 0),
|
||||
setc(0x80, regs.p.c = 1),
|
||||
setp(0x40, regs.p.p = 1) {
|
||||
1:op_io();
|
||||
$1;
|
||||
}
|
||||
|
||||
clrv(0xe0) {
|
||||
1:op_io();
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
}
|
||||
|
||||
notc(0xed) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
regs.p.c = !regs.p.c;
|
||||
}
|
||||
|
||||
ei(0xa0, 1),
|
||||
di(0xc0, 0) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
regs.p.i = $1;
|
||||
}
|
||||
|
||||
set0_dp(0x02, rd |= 0x01),
|
||||
clr0_dp(0x12, rd &= ~0x01),
|
||||
set1_dp(0x22, rd |= 0x02),
|
||||
clr1_dp(0x32, rd &= ~0x02),
|
||||
set2_dp(0x42, rd |= 0x04),
|
||||
clr2_dp(0x52, rd &= ~0x04),
|
||||
set3_dp(0x62, rd |= 0x08),
|
||||
clr3_dp(0x72, rd &= ~0x08),
|
||||
set4_dp(0x82, rd |= 0x10),
|
||||
clr4_dp(0x92, rd &= ~0x10),
|
||||
set5_dp(0xa2, rd |= 0x20),
|
||||
clr5_dp(0xb2, rd &= ~0x20),
|
||||
set6_dp(0xc2, rd |= 0x40),
|
||||
clr6_dp(0xd2, rd &= ~0x40),
|
||||
set7_dp(0xe2, rd |= 0x80),
|
||||
clr7_dp(0xf2, rd &= ~0x80) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:$1;
|
||||
op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
push_a(0x2d, a),
|
||||
push_x(0x4d, x),
|
||||
push_y(0x6d, y),
|
||||
push_p(0x0d, p) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_writestack(regs.$1);
|
||||
}
|
||||
|
||||
pop_a(0xae, a),
|
||||
pop_x(0xce, x),
|
||||
pop_y(0xee, y),
|
||||
pop_p(0x8e, p) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:regs.$1 = op_readstack();
|
||||
}
|
||||
|
||||
mul_ya(0xcf) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
7:op_io();
|
||||
8:op_io();
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
//result is set based on y (high-byte) only
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
}
|
||||
|
||||
div_ya_x(0x9e) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
7:op_io();
|
||||
8:op_io();
|
||||
9:op_io();
|
||||
10:op_io();
|
||||
11:op_io();
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
|
||||
if(regs.y < (regs.x << 1)) {
|
||||
//if quotient is <= 511 (will fit into 9-bit result)
|
||||
regs.a = ya / regs.x;
|
||||
regs.y = ya % regs.x;
|
||||
} else {
|
||||
//otherwise, the quotient won't fit into regs.p.v + regs.a
|
||||
//this emulates the odd behavior of the S-SMP in this case
|
||||
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
|
||||
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
|
||||
}
|
||||
//result is set based on a (quotient) only
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
//nop
|
||||
case 0x00: {
|
||||
op_io();
|
||||
} break;
|
||||
|
||||
//sleep
|
||||
case 0xef: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc--;
|
||||
} break;
|
||||
|
||||
//stop
|
||||
case 0xff: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc--;
|
||||
} break;
|
||||
|
||||
//xcn
|
||||
case 0x9f: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
regs.a = (regs.a >> 4) | (regs.a << 4);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//daa
|
||||
case 0xdf: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a += 0x60;
|
||||
regs.p.c = 1;
|
||||
}
|
||||
if(regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a += 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//das
|
||||
case 0xbe: {
|
||||
op_io();
|
||||
op_io();
|
||||
if(!regs.p.c || (regs.a) > 0x99) {
|
||||
regs.a -= 0x60;
|
||||
regs.p.c = 0;
|
||||
}
|
||||
if(!regs.p.h || (regs.a & 15) > 0x09) {
|
||||
regs.a -= 0x06;
|
||||
}
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//clrc
|
||||
case 0x60: {
|
||||
op_io();
|
||||
regs.p.c = 0;
|
||||
} break;
|
||||
|
||||
//clrp
|
||||
case 0x20: {
|
||||
op_io();
|
||||
regs.p.p = 0;
|
||||
} break;
|
||||
|
||||
//setc
|
||||
case 0x80: {
|
||||
op_io();
|
||||
regs.p.c = 1;
|
||||
} break;
|
||||
|
||||
//setp
|
||||
case 0x40: {
|
||||
op_io();
|
||||
regs.p.p = 1;
|
||||
} break;
|
||||
|
||||
//clrv
|
||||
case 0xe0: {
|
||||
op_io();
|
||||
regs.p.v = 0;
|
||||
regs.p.h = 0;
|
||||
} break;
|
||||
|
||||
//notc
|
||||
case 0xed: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p.c = !regs.p.c;
|
||||
} break;
|
||||
|
||||
//ei
|
||||
case 0xa0: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p.i = 1;
|
||||
} break;
|
||||
|
||||
//di
|
||||
case 0xc0: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p.i = 0;
|
||||
} break;
|
||||
|
||||
//set0_dp
|
||||
case 0x02: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x01;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr0_dp
|
||||
case 0x12: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x01;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set1_dp
|
||||
case 0x22: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x02;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr1_dp
|
||||
case 0x32: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x02;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set2_dp
|
||||
case 0x42: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x04;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr2_dp
|
||||
case 0x52: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x04;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set3_dp
|
||||
case 0x62: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x08;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr3_dp
|
||||
case 0x72: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x08;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set4_dp
|
||||
case 0x82: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x10;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr4_dp
|
||||
case 0x92: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x10;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set5_dp
|
||||
case 0xa2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x20;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr5_dp
|
||||
case 0xb2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x20;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set6_dp
|
||||
case 0xc2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x40;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr6_dp
|
||||
case 0xd2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x40;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//set7_dp
|
||||
case 0xe2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= 0x80;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//clr7_dp
|
||||
case 0xf2: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd &= ~0x80;
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//push_a
|
||||
case 0x2d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.a);
|
||||
} break;
|
||||
|
||||
//push_x
|
||||
case 0x4d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.x);
|
||||
} break;
|
||||
|
||||
//push_y
|
||||
case 0x6d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.y);
|
||||
} break;
|
||||
|
||||
//push_p
|
||||
case 0x0d: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.p);
|
||||
} break;
|
||||
|
||||
//pop_a
|
||||
case 0xae: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.a = op_readstack();
|
||||
} break;
|
||||
|
||||
//pop_x
|
||||
case 0xce: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.x = op_readstack();
|
||||
} break;
|
||||
|
||||
//pop_y
|
||||
case 0xee: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.y = op_readstack();
|
||||
} break;
|
||||
|
||||
//pop_p
|
||||
case 0x8e: {
|
||||
op_io();
|
||||
op_io();
|
||||
regs.p = op_readstack();
|
||||
} break;
|
||||
|
||||
//mul_ya
|
||||
case 0xcf: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
ya = regs.y * regs.a;
|
||||
regs.a = ya;
|
||||
regs.y = ya >> 8;
|
||||
//result is set based on y (high-byte) only
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
} break;
|
||||
|
||||
//div_ya_x
|
||||
case 0x9e: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
ya = regs.ya;
|
||||
//overflow set if quotient >= 256
|
||||
regs.p.v = !!(regs.y >= regs.x);
|
||||
regs.p.h = !!((regs.y & 15) >= (regs.x & 15));
|
||||
if(regs.y < (regs.x << 1)) {
|
||||
//if quotient is <= 511 (will fit into 9-bit result)
|
||||
regs.a = ya / regs.x;
|
||||
regs.y = ya % regs.x;
|
||||
} else {
|
||||
//otherwise, the quotient won't fit into regs.p.v + regs.a
|
||||
//this emulates the odd behavior of the S-SMP in this case
|
||||
regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x);
|
||||
regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x);
|
||||
}
|
||||
//result is set based on a (quotient) only
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,217 +0,0 @@
|
||||
mov_a_x(0x7d, a, x),
|
||||
mov_a_y(0xdd, a, y),
|
||||
mov_x_a(0x5d, x, a),
|
||||
mov_y_a(0xfd, y, a),
|
||||
mov_x_sp(0x9d, x, sp) {
|
||||
1:op_io();
|
||||
regs.$1 = regs.$2;
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_sp_x(0xbd, sp, x) {
|
||||
1:op_io();
|
||||
regs.$1 = regs.$2;
|
||||
}
|
||||
|
||||
mov_a_const(0xe8, a),
|
||||
mov_x_const(0xcd, x),
|
||||
mov_y_const(0x8d, y) {
|
||||
1:regs.$1 = op_readpc();
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_ix(0xe6) {
|
||||
1:op_io();
|
||||
2:regs.a = op_readdp(regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_ixinc(0xbf) {
|
||||
1:op_io();
|
||||
2:regs.a = op_readdp(regs.x++);
|
||||
3:op_io();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_dp(0xe4, a),
|
||||
mov_x_dp(0xf8, x),
|
||||
mov_y_dp(0xeb, y) {
|
||||
1:sp = op_readpc();
|
||||
2:regs.$1 = op_readdp(sp);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_dpx(0xf4, a, x),
|
||||
mov_x_dpy(0xf9, x, y),
|
||||
mov_y_dpx(0xfb, y, x) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:regs.$1 = op_readdp(sp + regs.$2);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_addr(0xe5, a),
|
||||
mov_x_addr(0xe9, x),
|
||||
mov_y_addr(0xec, y) {
|
||||
1:sp = op_readpc();
|
||||
2:sp |= op_readpc() << 8;
|
||||
3:regs.$1 = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.$1 & 0x80);
|
||||
regs.p.z = (regs.$1 == 0);
|
||||
}
|
||||
|
||||
mov_a_addrx(0xf5, x),
|
||||
mov_a_addry(0xf6, y) {
|
||||
1:sp = op_readpc();
|
||||
2:sp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:regs.a = op_readaddr(sp + regs.$1);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_idpx(0xe7) {
|
||||
1:dp = op_readpc() + regs.x;
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_a_idpy(0xf7) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
}
|
||||
|
||||
mov_dp_dp(0xfa) {
|
||||
1:sp = op_readpc();
|
||||
2:rd = op_readdp(sp);
|
||||
3:dp = op_readpc();
|
||||
4:op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
mov_dp_const(0x8f) {
|
||||
1:rd = op_readpc();
|
||||
2:dp = op_readpc();
|
||||
3:op_readdp(dp);
|
||||
4:op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
mov_ix_a(0xc6) {
|
||||
1:op_io();
|
||||
2:op_readdp(regs.x);
|
||||
3:op_writedp(regs.x, regs.a);
|
||||
}
|
||||
|
||||
mov_ixinc_a(0xaf) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
3:op_writedp(regs.x++, regs.a);
|
||||
}
|
||||
|
||||
mov_dp_a(0xc4, a),
|
||||
mov_dp_x(0xd8, x),
|
||||
mov_dp_y(0xcb, y) {
|
||||
1:dp = op_readpc();
|
||||
2:op_readdp(dp);
|
||||
3:op_writedp(dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_dpx_a(0xd4, x, a),
|
||||
mov_dpy_x(0xd9, y, x),
|
||||
mov_dpx_y(0xdb, x, y) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
dp += regs.$1;
|
||||
3:op_readdp(dp);
|
||||
4:op_writedp(dp, regs.$2);
|
||||
}
|
||||
|
||||
mov_addr_a(0xc5, a),
|
||||
mov_addr_x(0xc9, x),
|
||||
mov_addr_y(0xcc, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_readaddr(dp);
|
||||
4:op_writeaddr(dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_addrx_a(0xd5, x),
|
||||
mov_addry_a(0xd6, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
dp += regs.$1;
|
||||
4:op_readaddr(dp);
|
||||
5:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpx_a(0xc7) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
sp += regs.x;
|
||||
3:dp = op_readdp(sp);
|
||||
4:dp |= op_readdp(sp + 1) << 8;
|
||||
5:op_readaddr(dp);
|
||||
6:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpy_a(0xd7) {
|
||||
1:sp = op_readpc();
|
||||
2:dp = op_readdp(sp);
|
||||
3:dp |= op_readdp(sp + 1) << 8;
|
||||
4:op_io();
|
||||
dp += regs.y;
|
||||
5:op_readaddr(dp);
|
||||
6:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
movw_ya_dp(0xba) {
|
||||
1:sp = op_readpc();
|
||||
2:regs.a = op_readdp(sp);
|
||||
3:op_io();
|
||||
4:regs.y = op_readdp(sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
}
|
||||
|
||||
movw_dp_ya(0xda) {
|
||||
1:dp = op_readpc();
|
||||
2:op_readdp(dp);
|
||||
3:op_writedp(dp, regs.a);
|
||||
4:op_writedp(dp + 1, regs.y);
|
||||
}
|
||||
|
||||
mov1_c_bit(0xaa) {
|
||||
1:sp = op_readpc();
|
||||
2:sp |= op_readpc() << 8;
|
||||
3:bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_readaddr(sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
}
|
||||
|
||||
mov1_bit_c(0xca) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
4:op_io();
|
||||
5:op_writeaddr(dp, rd);
|
||||
}
|
||||
@@ -1,392 +0,0 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
//mov_a_x
|
||||
case 0x7d: {
|
||||
op_io();
|
||||
regs.a = regs.x;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_y
|
||||
case 0xdd: {
|
||||
op_io();
|
||||
regs.a = regs.y;
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_x_a
|
||||
case 0x5d: {
|
||||
op_io();
|
||||
regs.x = regs.a;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
} break;
|
||||
|
||||
//mov_y_a
|
||||
case 0xfd: {
|
||||
op_io();
|
||||
regs.y = regs.a;
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
} break;
|
||||
|
||||
//mov_x_sp
|
||||
case 0x9d: {
|
||||
op_io();
|
||||
regs.x = regs.sp;
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
} break;
|
||||
|
||||
//mov_sp_x
|
||||
case 0xbd: {
|
||||
op_io();
|
||||
regs.sp = regs.x;
|
||||
} break;
|
||||
|
||||
//mov_a_const
|
||||
case 0xe8: {
|
||||
regs.a = op_readpc();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_x_const
|
||||
case 0xcd: {
|
||||
regs.x = op_readpc();
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
} break;
|
||||
|
||||
//mov_y_const
|
||||
case 0x8d: {
|
||||
regs.y = op_readpc();
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_ix
|
||||
case 0xe6: {
|
||||
op_io();
|
||||
regs.a = op_readdp(regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_ixinc
|
||||
case 0xbf: {
|
||||
op_io();
|
||||
regs.a = op_readdp(regs.x++);
|
||||
op_io();
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_dp
|
||||
case 0xe4: {
|
||||
sp = op_readpc();
|
||||
regs.a = op_readdp(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_x_dp
|
||||
case 0xf8: {
|
||||
sp = op_readpc();
|
||||
regs.x = op_readdp(sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
} break;
|
||||
|
||||
//mov_y_dp
|
||||
case 0xeb: {
|
||||
sp = op_readpc();
|
||||
regs.y = op_readdp(sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_dpx
|
||||
case 0xf4: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
regs.a = op_readdp(sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_x_dpy
|
||||
case 0xf9: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
regs.x = op_readdp(sp + regs.y);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
} break;
|
||||
|
||||
//mov_y_dpx
|
||||
case 0xfb: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
regs.y = op_readdp(sp + regs.x);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_addr
|
||||
case 0xe5: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_x_addr
|
||||
case 0xe9: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
regs.x = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.x & 0x80);
|
||||
regs.p.z = (regs.x == 0);
|
||||
} break;
|
||||
|
||||
//mov_y_addr
|
||||
case 0xec: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
regs.y = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.y & 0x80);
|
||||
regs.p.z = (regs.y == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_addrx
|
||||
case 0xf5: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
op_io();
|
||||
regs.a = op_readaddr(sp + regs.x);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_addry
|
||||
case 0xf6: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
op_io();
|
||||
regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_idpx
|
||||
case 0xe7: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
regs.a = op_readaddr(sp);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_a_idpy
|
||||
case 0xf7: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
regs.a = op_readaddr(sp + regs.y);
|
||||
regs.p.n = !!(regs.a & 0x80);
|
||||
regs.p.z = (regs.a == 0);
|
||||
} break;
|
||||
|
||||
//mov_dp_dp
|
||||
case 0xfa: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//mov_dp_const
|
||||
case 0x8f: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//mov_ix_a
|
||||
case 0xc6: {
|
||||
op_io();
|
||||
op_readdp(regs.x);
|
||||
op_writedp(regs.x, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_ixinc_a
|
||||
case 0xaf: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_writedp(regs.x++, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_dp_a
|
||||
case 0xc4: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_dp_x
|
||||
case 0xd8: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.x);
|
||||
} break;
|
||||
|
||||
//mov_dp_y
|
||||
case 0xcb: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.y);
|
||||
} break;
|
||||
|
||||
//mov_dpx_a
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_dpy_x
|
||||
case 0xd9: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.x);
|
||||
} break;
|
||||
|
||||
//mov_dpx_y
|
||||
case 0xdb: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.y);
|
||||
} break;
|
||||
|
||||
//mov_addr_a
|
||||
case 0xc5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_addr_x
|
||||
case 0xc9: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.x);
|
||||
} break;
|
||||
|
||||
//mov_addr_y
|
||||
case 0xcc: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.y);
|
||||
} break;
|
||||
|
||||
//mov_addrx_a
|
||||
case 0xd5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_addry_a
|
||||
case 0xd6: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_idpx_a
|
||||
case 0xc7: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
sp += regs.x;
|
||||
dp = op_readdp(sp);
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_idpy_a
|
||||
case 0xd7: {
|
||||
sp = op_readpc();
|
||||
dp = op_readdp(sp);
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
op_io();
|
||||
dp += regs.y;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//movw_ya_dp
|
||||
case 0xba: {
|
||||
sp = op_readpc();
|
||||
regs.a = op_readdp(sp);
|
||||
op_io();
|
||||
regs.y = op_readdp(sp + 1);
|
||||
regs.p.n = !!(regs.ya & 0x8000);
|
||||
regs.p.z = (regs.ya == 0);
|
||||
} break;
|
||||
|
||||
//movw_dp_ya
|
||||
case 0xda: {
|
||||
dp = op_readpc();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
op_writedp(dp + 1, regs.y);
|
||||
} break;
|
||||
|
||||
//mov1_c_bit
|
||||
case 0xaa: {
|
||||
sp = op_readpc();
|
||||
sp |= op_readpc() << 8;
|
||||
bit = sp >> 13;
|
||||
sp &= 0x1fff;
|
||||
rd = op_readaddr(sp);
|
||||
regs.p.c = !!(rd & (1 << bit));
|
||||
} break;
|
||||
|
||||
//mov1_bit_c
|
||||
case 0xca: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
if(regs.p.c)rd |= (1 << bit);
|
||||
else rd &= ~(1 << bit);
|
||||
op_io();
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,179 +0,0 @@
|
||||
bra(0x2f, 0),
|
||||
beq(0xf0, !regs.p.z),
|
||||
bne(0xd0, regs.p.z),
|
||||
bcs(0xb0, !regs.p.c),
|
||||
bcc(0x90, regs.p.c),
|
||||
bvs(0x70, !regs.p.v),
|
||||
bvc(0x50, regs.p.v),
|
||||
bmi(0x30, !regs.p.n),
|
||||
bpl(0x10, regs.p.n) {
|
||||
1:rd = op_readpc();
|
||||
if($1)end;
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
bbs0(0x03, 0x01, !=),
|
||||
bbc0(0x13, 0x01, ==),
|
||||
bbs1(0x23, 0x02, !=),
|
||||
bbc1(0x33, 0x02, ==),
|
||||
bbs2(0x43, 0x04, !=),
|
||||
bbc2(0x53, 0x04, ==),
|
||||
bbs3(0x63, 0x08, !=),
|
||||
bbc3(0x73, 0x08, ==),
|
||||
bbs4(0x83, 0x10, !=),
|
||||
bbc4(0x93, 0x10, ==),
|
||||
bbs5(0xa3, 0x20, !=),
|
||||
bbc5(0xb3, 0x20, ==),
|
||||
bbs6(0xc3, 0x40, !=),
|
||||
bbc6(0xd3, 0x40, ==),
|
||||
bbs7(0xe3, 0x80, !=),
|
||||
bbc7(0xf3, 0x80, ==) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readdp(dp);
|
||||
3:rd = op_readpc();
|
||||
4:op_io();
|
||||
if((sp & $1) $2 $1)end;
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
cbne_dp(0x2e) {
|
||||
1:dp = op_readpc();
|
||||
2:sp = op_readdp(dp);
|
||||
3:rd = op_readpc();
|
||||
4:op_io();
|
||||
if(regs.a == sp)end;
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
cbne_dpx(0xde) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp + regs.x);
|
||||
4:rd = op_readpc();
|
||||
5:op_io();
|
||||
if(regs.a == sp)end;
|
||||
6:op_io();
|
||||
7:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
dbnz_dp(0x6e) {
|
||||
1:dp = op_readpc();
|
||||
2:wr = op_readdp(dp);
|
||||
3:op_writedp(dp, --wr);
|
||||
4:rd = op_readpc();
|
||||
if(wr == 0x00)end;
|
||||
5:op_io();
|
||||
6:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
dbnz_y(0xfe) {
|
||||
1:rd = op_readpc();
|
||||
2:op_io();
|
||||
regs.y--;
|
||||
3:op_io();
|
||||
if(regs.y == 0x00)end;
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
regs.pc += (int8)rd;
|
||||
}
|
||||
|
||||
jmp_addr(0x5f) {
|
||||
1:rd = op_readpc();
|
||||
2:rd |= op_readpc() << 8;
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
jmp_iaddrx(0x1f) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
dp += regs.x;
|
||||
4:rd = op_readaddr(dp);
|
||||
5:rd |= op_readaddr(dp + 1) << 8;
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
call(0x3f) {
|
||||
1:rd = op_readpc();
|
||||
2:rd |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_writestack(regs.pc >> 8);
|
||||
7:op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
pcall(0x4f) {
|
||||
1:rd = op_readpc();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_writestack(regs.pc >> 8);
|
||||
5:op_writestack(regs.pc);
|
||||
regs.pc = 0xff00 | rd;
|
||||
}
|
||||
|
||||
tcall_0(0x01, 0),
|
||||
tcall_1(0x11, 1),
|
||||
tcall_2(0x21, 2),
|
||||
tcall_3(0x31, 3),
|
||||
tcall_4(0x41, 4),
|
||||
tcall_5(0x51, 5),
|
||||
tcall_6(0x61, 6),
|
||||
tcall_7(0x71, 7),
|
||||
tcall_8(0x81, 8),
|
||||
tcall_9(0x91, 9),
|
||||
tcall_10(0xa1, 10),
|
||||
tcall_11(0xb1, 11),
|
||||
tcall_12(0xc1, 12),
|
||||
tcall_13(0xd1, 13),
|
||||
tcall_14(0xe1, 14),
|
||||
tcall_15(0xf1, 15) {
|
||||
1:dp = 0xffde - ($1 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
2:rd |= op_readaddr(dp + 1) << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
6:op_writestack(regs.pc >> 8);
|
||||
7:op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
brk(0x0f) {
|
||||
1:rd = op_readaddr(0xffde);
|
||||
2:rd |= op_readaddr(0xffdf) << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_writestack(regs.pc >> 8);
|
||||
6:op_writestack(regs.pc);
|
||||
7:op_writestack(regs.p);
|
||||
regs.pc = rd;
|
||||
regs.p.b = 1;
|
||||
regs.p.i = 0;
|
||||
}
|
||||
|
||||
ret(0x6f) {
|
||||
1:rd = op_readstack();
|
||||
2:rd |= op_readstack() << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
regs.pc = rd;
|
||||
}
|
||||
|
||||
reti(0x7f) {
|
||||
1:regs.p = op_readstack();
|
||||
2:rd = op_readstack();
|
||||
3:rd |= op_readstack() << 8;
|
||||
4:op_io();
|
||||
5:op_io();
|
||||
regs.pc = rd;
|
||||
}
|
||||
@@ -1,606 +0,0 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
//bra
|
||||
case 0x2f: {
|
||||
rd = op_readpc();
|
||||
if(0)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//beq
|
||||
case 0xf0: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.z)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bne
|
||||
case 0xd0: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.z)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bcs
|
||||
case 0xb0: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.c)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bcc
|
||||
case 0x90: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.c)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bvs
|
||||
case 0x70: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.v)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bvc
|
||||
case 0x50: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.v)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bmi
|
||||
case 0x30: {
|
||||
rd = op_readpc();
|
||||
if(!regs.p.n)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bpl
|
||||
case 0x10: {
|
||||
rd = op_readpc();
|
||||
if(regs.p.n)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs0
|
||||
case 0x03: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x01) != 0x01)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc0
|
||||
case 0x13: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x01) == 0x01)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs1
|
||||
case 0x23: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x02) != 0x02)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc1
|
||||
case 0x33: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x02) == 0x02)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs2
|
||||
case 0x43: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x04) != 0x04)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc2
|
||||
case 0x53: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x04) == 0x04)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs3
|
||||
case 0x63: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x08) != 0x08)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc3
|
||||
case 0x73: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x08) == 0x08)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs4
|
||||
case 0x83: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x10) != 0x10)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc4
|
||||
case 0x93: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x10) == 0x10)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs5
|
||||
case 0xa3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x20) != 0x20)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc5
|
||||
case 0xb3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x20) == 0x20)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs6
|
||||
case 0xc3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x40) != 0x40)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc6
|
||||
case 0xd3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x40) == 0x40)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbs7
|
||||
case 0xe3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x80) != 0x80)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//bbc7
|
||||
case 0xf3: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if((sp & 0x80) == 0x80)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//cbne_dp
|
||||
case 0x2e: {
|
||||
dp = op_readpc();
|
||||
sp = op_readdp(dp);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if(regs.a == sp)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//cbne_dpx
|
||||
case 0xde: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp + regs.x);
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
if(regs.a == sp)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//dbnz_dp
|
||||
case 0x6e: {
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
op_writedp(dp, --wr);
|
||||
rd = op_readpc();
|
||||
if(wr == 0x00)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//dbnz_y
|
||||
case 0xfe: {
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
regs.y--;
|
||||
op_io();
|
||||
if(regs.y == 0x00)break;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc += (int8)rd;
|
||||
} break;
|
||||
|
||||
//jmp_addr
|
||||
case 0x5f: {
|
||||
rd = op_readpc();
|
||||
rd |= op_readpc() << 8;
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//jmp_iaddrx
|
||||
case 0x1f: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
dp += regs.x;
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//call
|
||||
case 0x3f: {
|
||||
rd = op_readpc();
|
||||
rd |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//pcall
|
||||
case 0x4f: {
|
||||
rd = op_readpc();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = 0xff00 | rd;
|
||||
} break;
|
||||
|
||||
//tcall_0
|
||||
case 0x01: {
|
||||
dp = 0xffde - (0 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_1
|
||||
case 0x11: {
|
||||
dp = 0xffde - (1 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_2
|
||||
case 0x21: {
|
||||
dp = 0xffde - (2 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_3
|
||||
case 0x31: {
|
||||
dp = 0xffde - (3 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_4
|
||||
case 0x41: {
|
||||
dp = 0xffde - (4 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_5
|
||||
case 0x51: {
|
||||
dp = 0xffde - (5 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_6
|
||||
case 0x61: {
|
||||
dp = 0xffde - (6 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_7
|
||||
case 0x71: {
|
||||
dp = 0xffde - (7 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_8
|
||||
case 0x81: {
|
||||
dp = 0xffde - (8 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_9
|
||||
case 0x91: {
|
||||
dp = 0xffde - (9 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_10
|
||||
case 0xa1: {
|
||||
dp = 0xffde - (10 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_11
|
||||
case 0xb1: {
|
||||
dp = 0xffde - (11 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_12
|
||||
case 0xc1: {
|
||||
dp = 0xffde - (12 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_13
|
||||
case 0xd1: {
|
||||
dp = 0xffde - (13 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_14
|
||||
case 0xe1: {
|
||||
dp = 0xffde - (14 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//tcall_15
|
||||
case 0xf1: {
|
||||
dp = 0xffde - (15 << 1);
|
||||
rd = op_readaddr(dp);
|
||||
rd |= op_readaddr(dp + 1) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//brk
|
||||
case 0x0f: {
|
||||
rd = op_readaddr(0xffde);
|
||||
rd |= op_readaddr(0xffdf) << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_writestack(regs.pc >> 8);
|
||||
op_writestack(regs.pc);
|
||||
op_writestack(regs.p);
|
||||
regs.pc = rd;
|
||||
regs.p.b = 1;
|
||||
regs.p.i = 0;
|
||||
} break;
|
||||
|
||||
//ret
|
||||
case 0x6f: {
|
||||
rd = op_readstack();
|
||||
rd |= op_readstack() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
//reti
|
||||
case 0x7f: {
|
||||
regs.p = op_readstack();
|
||||
rd = op_readstack();
|
||||
rd |= op_readstack() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
regs.pc = rd;
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,205 +0,0 @@
|
||||
adc_a_const(0x88, adc, a),
|
||||
and_a_const(0x28, and, a),
|
||||
cmp_a_const(0x68, cmp, a),
|
||||
cmp_x_const(0xc8, cmp, x),
|
||||
cmp_y_const(0xad, cmp, y),
|
||||
eor_a_const(0x48, eor, a),
|
||||
or_a_const(0x08, or, a),
|
||||
sbc_a_const(0xa8, sbc, a) {
|
||||
1:rd = op_readpc();
|
||||
regs.$2 = op_$1(regs.$2, rd);
|
||||
}
|
||||
|
||||
adc_a_ix(0x86, adc),
|
||||
and_a_ix(0x26, and),
|
||||
cmp_a_ix(0x66, cmp),
|
||||
eor_a_ix(0x46, eor),
|
||||
or_a_ix(0x06, or),
|
||||
sbc_a_ix(0xa6, sbc) {
|
||||
1:op_io();
|
||||
2:rd = op_readdp(regs.x);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_dp(0x84, adc, a),
|
||||
and_a_dp(0x24, and, a),
|
||||
cmp_a_dp(0x64, cmp, a),
|
||||
cmp_x_dp(0x3e, cmp, x),
|
||||
cmp_y_dp(0x7e, cmp, y),
|
||||
eor_a_dp(0x44, eor, a),
|
||||
or_a_dp(0x04, or, a),
|
||||
sbc_a_dp(0xa4, sbc, a) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
regs.$2 = op_$1(regs.$2, rd);
|
||||
}
|
||||
|
||||
adc_a_dpx(0x94, adc),
|
||||
and_a_dpx(0x34, and),
|
||||
cmp_a_dpx(0x74, cmp),
|
||||
eor_a_dpx(0x54, eor),
|
||||
or_a_dpx(0x14, or),
|
||||
sbc_a_dpx(0xb4, sbc) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_addr(0x85, adc, a),
|
||||
and_a_addr(0x25, and, a),
|
||||
cmp_a_addr(0x65, cmp, a),
|
||||
cmp_x_addr(0x1e, cmp, x),
|
||||
cmp_y_addr(0x5e, cmp, y),
|
||||
eor_a_addr(0x45, eor, a),
|
||||
or_a_addr(0x05, or, a),
|
||||
sbc_a_addr(0xa5, sbc, a) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:rd = op_readaddr(dp);
|
||||
regs.$2 = op_$1(regs.$2, rd);
|
||||
}
|
||||
|
||||
adc_a_addrx(0x95, adc, x),
|
||||
adc_a_addry(0x96, adc, y),
|
||||
and_a_addrx(0x35, and, x),
|
||||
and_a_addry(0x36, and, y),
|
||||
cmp_a_addrx(0x75, cmp, x),
|
||||
cmp_a_addry(0x76, cmp, y),
|
||||
eor_a_addrx(0x55, eor, x),
|
||||
eor_a_addry(0x56, eor, y),
|
||||
or_a_addrx(0x15, or, x),
|
||||
or_a_addry(0x16, or, y),
|
||||
sbc_a_addrx(0xb5, sbc, x),
|
||||
sbc_a_addry(0xb6, sbc, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:rd = op_readaddr(dp + regs.$2);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_idpx(0x87, adc),
|
||||
and_a_idpx(0x27, and),
|
||||
cmp_a_idpx(0x67, cmp),
|
||||
eor_a_idpx(0x47, eor),
|
||||
or_a_idpx(0x07, or),
|
||||
sbc_a_idpx(0xa7, sbc) {
|
||||
1:dp = op_readpc() + regs.x;
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:rd = op_readaddr(sp);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_a_idpy(0x97, adc),
|
||||
and_a_idpy(0x37, and),
|
||||
cmp_a_idpy(0x77, cmp),
|
||||
eor_a_idpy(0x57, eor),
|
||||
or_a_idpy(0x17, or),
|
||||
sbc_a_idpy(0xb7, sbc) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:sp = op_readdp(dp);
|
||||
4:sp |= op_readdp(dp + 1) << 8;
|
||||
5:rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_$1(regs.a, rd);
|
||||
}
|
||||
|
||||
adc_ix_iy(0x99, adc, 1),
|
||||
and_ix_iy(0x39, and, 1),
|
||||
cmp_ix_iy(0x79, cmp, 0),
|
||||
eor_ix_iy(0x59, eor, 1),
|
||||
or_ix_iy(0x19, or, 1),
|
||||
sbc_ix_iy(0xb9, sbc, 1) {
|
||||
1:op_io();
|
||||
2:rd = op_readdp(regs.y);
|
||||
3:wr = op_readdp(regs.x);
|
||||
wr = op_$1(wr, rd);
|
||||
4:($2) ? op_writedp(regs.x, wr) : op_io();
|
||||
}
|
||||
|
||||
adc_dp_dp(0x89, adc, 1),
|
||||
and_dp_dp(0x29, and, 1),
|
||||
cmp_dp_dp(0x69, cmp, 0),
|
||||
eor_dp_dp(0x49, eor, 1),
|
||||
or_dp_dp(0x09, or, 1),
|
||||
sbc_dp_dp(0xa9, sbc, 1) {
|
||||
1:sp = op_readpc();
|
||||
2:rd = op_readdp(sp);
|
||||
3:dp = op_readpc();
|
||||
4:wr = op_readdp(dp);
|
||||
5:wr = op_$1(wr, rd);
|
||||
($2) ? op_writedp(dp, wr) : op_io();
|
||||
}
|
||||
|
||||
adc_dp_const(0x98, adc, 1),
|
||||
and_dp_const(0x38, and, 1),
|
||||
cmp_dp_const(0x78, cmp, 0),
|
||||
eor_dp_const(0x58, eor, 1),
|
||||
or_dp_const(0x18, or, 1),
|
||||
sbc_dp_const(0xb8, sbc, 1) {
|
||||
1:rd = op_readpc();
|
||||
2:dp = op_readpc();
|
||||
3:wr = op_readdp(dp);
|
||||
4:wr = op_$1(wr, rd);
|
||||
($2) ? op_writedp(dp, wr) : op_io();
|
||||
}
|
||||
|
||||
addw_ya_dp(0x7a, addw),
|
||||
subw_ya_dp(0x9a, subw) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:op_io();
|
||||
4:rd |= op_readdp(dp + 1) << 8;
|
||||
regs.ya = op_$1(regs.ya, rd);
|
||||
}
|
||||
|
||||
cmpw_ya_dp(0x5a) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:rd |= op_readdp(dp + 1) << 8;
|
||||
op_cmpw(regs.ya, rd);
|
||||
}
|
||||
|
||||
and1_bit(0x4a, !!),
|
||||
and1_notbit(0x6a, !) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.c = regs.p.c & $1(rd & (1 << bit));
|
||||
}
|
||||
|
||||
eor1_bit(0x8a) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
4:op_io();
|
||||
regs.p.c = regs.p.c ^ !!(rd & (1 << bit));
|
||||
}
|
||||
|
||||
not1_bit(0xea) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
rd ^= (1 << bit);
|
||||
4:op_writeaddr(dp, rd);
|
||||
}
|
||||
|
||||
or1_bit(0x0a, !!),
|
||||
or1_notbit(0x2a, !) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
4:op_io();
|
||||
regs.p.c = regs.p.c | $1(rd & (1 << bit));
|
||||
}
|
||||
@@ -1,747 +0,0 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
//adc_a_const
|
||||
case 0x88: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_const
|
||||
case 0x28: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_const
|
||||
case 0x68: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_x_const
|
||||
case 0xc8: {
|
||||
rd = op_readpc();
|
||||
regs.x = op_cmp(regs.x, rd);
|
||||
} break;
|
||||
|
||||
//cmp_y_const
|
||||
case 0xad: {
|
||||
rd = op_readpc();
|
||||
regs.y = op_cmp(regs.y, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_const
|
||||
case 0x48: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_const
|
||||
case 0x08: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_const
|
||||
case 0xa8: {
|
||||
rd = op_readpc();
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_ix
|
||||
case 0x86: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_ix
|
||||
case 0x26: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_ix
|
||||
case 0x66: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_ix
|
||||
case 0x46: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_ix
|
||||
case 0x06: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_ix
|
||||
case 0xa6: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.x);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_dp
|
||||
case 0x84: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_dp
|
||||
case 0x24: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_dp
|
||||
case 0x64: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_x_dp
|
||||
case 0x3e: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.x = op_cmp(regs.x, rd);
|
||||
} break;
|
||||
|
||||
//cmp_y_dp
|
||||
case 0x7e: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.y = op_cmp(regs.y, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_dp
|
||||
case 0x44: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_dp
|
||||
case 0x04: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_dp
|
||||
case 0xa4: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_dpx
|
||||
case 0x94: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_dpx
|
||||
case 0x34: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_dpx
|
||||
case 0x74: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_dpx
|
||||
case 0x54: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_dpx
|
||||
case 0x14: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_dpx
|
||||
case 0xb4: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_addr
|
||||
case 0x85: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_addr
|
||||
case 0x25: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_addr
|
||||
case 0x65: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_x_addr
|
||||
case 0x1e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.x = op_cmp(regs.x, rd);
|
||||
} break;
|
||||
|
||||
//cmp_y_addr
|
||||
case 0x5e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.y = op_cmp(regs.y, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_addr
|
||||
case 0x45: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_addr
|
||||
case 0x05: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_addr
|
||||
case 0xa5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_addrx
|
||||
case 0x95: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_addry
|
||||
case 0x96: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_addrx
|
||||
case 0x35: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_addry
|
||||
case 0x36: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_addrx
|
||||
case 0x75: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_addry
|
||||
case 0x76: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_addrx
|
||||
case 0x55: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_addry
|
||||
case 0x56: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_addrx
|
||||
case 0x15: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_addry
|
||||
case 0x16: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_addrx
|
||||
case 0xb5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.x);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_addry
|
||||
case 0xb6: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
rd = op_readaddr(dp + regs.y);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_idpx
|
||||
case 0x87: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_idpx
|
||||
case 0x27: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_idpx
|
||||
case 0x67: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_idpx
|
||||
case 0x47: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_idpx
|
||||
case 0x07: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_idpx
|
||||
case 0xa7: {
|
||||
dp = op_readpc() + regs.x;
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_a_idpy
|
||||
case 0x97: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_adc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//and_a_idpy
|
||||
case 0x37: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_and(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//cmp_a_idpy
|
||||
case 0x77: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_cmp(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//eor_a_idpy
|
||||
case 0x57: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_eor(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//or_a_idpy
|
||||
case 0x17: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_or(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//sbc_a_idpy
|
||||
case 0xb7: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readdp(dp);
|
||||
sp |= op_readdp(dp + 1) << 8;
|
||||
rd = op_readaddr(sp + regs.y);
|
||||
regs.a = op_sbc(regs.a, rd);
|
||||
} break;
|
||||
|
||||
//adc_ix_iy
|
||||
case 0x99: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_adc(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//and_ix_iy
|
||||
case 0x39: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_and(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//cmp_ix_iy
|
||||
case 0x79: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_cmp(wr, rd);
|
||||
(0) ? op_writedp(regs.x, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//eor_ix_iy
|
||||
case 0x59: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_eor(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//or_ix_iy
|
||||
case 0x19: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_or(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//sbc_ix_iy
|
||||
case 0xb9: {
|
||||
op_io();
|
||||
rd = op_readdp(regs.y);
|
||||
wr = op_readdp(regs.x);
|
||||
wr = op_sbc(wr, rd);
|
||||
(1) ? op_writedp(regs.x, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//adc_dp_dp
|
||||
case 0x89: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_adc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//and_dp_dp
|
||||
case 0x29: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_and(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//cmp_dp_dp
|
||||
case 0x69: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_cmp(wr, rd);
|
||||
(0) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//eor_dp_dp
|
||||
case 0x49: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_eor(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//or_dp_dp
|
||||
case 0x09: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_or(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//sbc_dp_dp
|
||||
case 0xa9: {
|
||||
sp = op_readpc();
|
||||
rd = op_readdp(sp);
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_sbc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//adc_dp_const
|
||||
case 0x98: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_adc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//and_dp_const
|
||||
case 0x38: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_and(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//cmp_dp_const
|
||||
case 0x78: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_cmp(wr, rd);
|
||||
(0) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//eor_dp_const
|
||||
case 0x58: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_eor(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//or_dp_const
|
||||
case 0x18: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_or(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//sbc_dp_const
|
||||
case 0xb8: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
wr = op_readdp(dp);
|
||||
wr = op_sbc(wr, rd);
|
||||
(1) ? op_writedp(dp, wr) : op_io();
|
||||
} break;
|
||||
|
||||
//addw_ya_dp
|
||||
case 0x7a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
op_io();
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
regs.ya = op_addw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//subw_ya_dp
|
||||
case 0x9a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
op_io();
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
regs.ya = op_subw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//cmpw_ya_dp
|
||||
case 0x5a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
op_cmpw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//and1_bit
|
||||
case 0x4a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.c = regs.p.c & !!(rd & (1 << bit));
|
||||
} break;
|
||||
|
||||
//and1_notbit
|
||||
case 0x6a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.c = regs.p.c & !(rd & (1 << bit));
|
||||
} break;
|
||||
|
||||
//eor1_bit
|
||||
case 0x8a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
op_io();
|
||||
regs.p.c = regs.p.c ^ !!(rd & (1 << bit));
|
||||
} break;
|
||||
|
||||
//not1_bit
|
||||
case 0xea: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
rd ^= (1 << bit);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//or1_bit
|
||||
case 0x0a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
op_io();
|
||||
regs.p.c = regs.p.c | !!(rd & (1 << bit));
|
||||
} break;
|
||||
|
||||
//or1_notbit
|
||||
case 0x2a: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
bit = dp >> 13;
|
||||
dp &= 0x1fff;
|
||||
rd = op_readaddr(dp);
|
||||
op_io();
|
||||
regs.p.c = regs.p.c | !(rd & (1 << bit));
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
inc_a(0xbc, inc, a),
|
||||
inc_x(0x3d, inc, x),
|
||||
inc_y(0xfc, inc, y),
|
||||
dec_a(0x9c, dec, a),
|
||||
dec_x(0x1d, dec, x),
|
||||
dec_y(0xdc, dec, y),
|
||||
asl_a(0x1c, asl, a),
|
||||
lsr_a(0x5c, lsr, a),
|
||||
rol_a(0x3c, rol, a),
|
||||
ror_a(0x7c, ror, a) {
|
||||
1:op_io();
|
||||
regs.$2 = op_$1(regs.$2);
|
||||
}
|
||||
|
||||
inc_dp(0xab, inc),
|
||||
dec_dp(0x8b, dec),
|
||||
asl_dp(0x0b, asl),
|
||||
lsr_dp(0x4b, lsr),
|
||||
rol_dp(0x2b, rol),
|
||||
ror_dp(0x6b, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:rd = op_$1(rd);
|
||||
op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
inc_dpx(0xbb, inc),
|
||||
dec_dpx(0x9b, dec),
|
||||
asl_dpx(0x1b, asl),
|
||||
lsr_dpx(0x5b, lsr),
|
||||
rol_dpx(0x3b, rol),
|
||||
ror_dpx(0x7b, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:rd = op_readdp(dp + regs.x);
|
||||
4:rd = op_$1(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
}
|
||||
|
||||
inc_addr(0xac, inc),
|
||||
dec_addr(0x8c, dec),
|
||||
asl_addr(0x0c, asl),
|
||||
lsr_addr(0x4c, lsr),
|
||||
rol_addr(0x2c, rol),
|
||||
ror_addr(0x6c, ror) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:rd = op_readaddr(dp);
|
||||
4:rd = op_$1(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
}
|
||||
|
||||
tset_addr_a(0x0e, |),
|
||||
tclr_addr_a(0x4e, &~) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
4:op_readaddr(dp);
|
||||
5:op_writeaddr(dp, rd $1 regs.a);
|
||||
}
|
||||
|
||||
incw_dp(0x3a, ++),
|
||||
decw_dp(0x1a, --) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
rd$1;
|
||||
3:op_writedp(dp++, rd);
|
||||
4:rd += op_readdp(dp) << 8;
|
||||
5:op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
#ifdef SSMP_CPP
|
||||
|
||||
//inc_a
|
||||
case 0xbc: {
|
||||
op_io();
|
||||
regs.a = op_inc(regs.a);
|
||||
} break;
|
||||
|
||||
//inc_x
|
||||
case 0x3d: {
|
||||
op_io();
|
||||
regs.x = op_inc(regs.x);
|
||||
} break;
|
||||
|
||||
//inc_y
|
||||
case 0xfc: {
|
||||
op_io();
|
||||
regs.y = op_inc(regs.y);
|
||||
} break;
|
||||
|
||||
//dec_a
|
||||
case 0x9c: {
|
||||
op_io();
|
||||
regs.a = op_dec(regs.a);
|
||||
} break;
|
||||
|
||||
//dec_x
|
||||
case 0x1d: {
|
||||
op_io();
|
||||
regs.x = op_dec(regs.x);
|
||||
} break;
|
||||
|
||||
//dec_y
|
||||
case 0xdc: {
|
||||
op_io();
|
||||
regs.y = op_dec(regs.y);
|
||||
} break;
|
||||
|
||||
//asl_a
|
||||
case 0x1c: {
|
||||
op_io();
|
||||
regs.a = op_asl(regs.a);
|
||||
} break;
|
||||
|
||||
//lsr_a
|
||||
case 0x5c: {
|
||||
op_io();
|
||||
regs.a = op_lsr(regs.a);
|
||||
} break;
|
||||
|
||||
//rol_a
|
||||
case 0x3c: {
|
||||
op_io();
|
||||
regs.a = op_rol(regs.a);
|
||||
} break;
|
||||
|
||||
//ror_a
|
||||
case 0x7c: {
|
||||
op_io();
|
||||
regs.a = op_ror(regs.a);
|
||||
} break;
|
||||
|
||||
//inc_dp
|
||||
case 0xab: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_inc(rd);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//dec_dp
|
||||
case 0x8b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_dec(rd);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//asl_dp
|
||||
case 0x0b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_asl(rd);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//lsr_dp
|
||||
case 0x4b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_lsr(rd);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//rol_dp
|
||||
case 0x2b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_rol(rd);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//ror_dp
|
||||
case 0x6b: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd = op_ror(rd);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//inc_dpx
|
||||
case 0xbb: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_inc(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
} break;
|
||||
|
||||
//dec_dpx
|
||||
case 0x9b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_dec(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
} break;
|
||||
|
||||
//asl_dpx
|
||||
case 0x1b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_asl(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
} break;
|
||||
|
||||
//lsr_dpx
|
||||
case 0x5b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_lsr(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
} break;
|
||||
|
||||
//rol_dpx
|
||||
case 0x3b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_rol(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
} break;
|
||||
|
||||
//ror_dpx
|
||||
case 0x7b: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
rd = op_readdp(dp + regs.x);
|
||||
rd = op_ror(rd);
|
||||
op_writedp(dp + regs.x, rd);
|
||||
} break;
|
||||
|
||||
//inc_addr
|
||||
case 0xac: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_inc(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//dec_addr
|
||||
case 0x8c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_dec(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//asl_addr
|
||||
case 0x0c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_asl(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//lsr_addr
|
||||
case 0x4c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_lsr(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//rol_addr
|
||||
case 0x2c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_rol(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//ror_addr
|
||||
case 0x6c: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
rd = op_ror(rd);
|
||||
op_writeaddr(dp, rd);
|
||||
} break;
|
||||
|
||||
//tset_addr_a
|
||||
case 0x0e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, rd | regs.a);
|
||||
} break;
|
||||
|
||||
//tclr_addr_a
|
||||
case 0x4e: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
rd = op_readaddr(dp);
|
||||
regs.p.n = !!((regs.a - rd) & 0x80);
|
||||
regs.p.z = ((regs.a - rd) == 0);
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, rd &~ regs.a);
|
||||
} break;
|
||||
|
||||
//incw_dp
|
||||
case 0x3a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd++;
|
||||
op_writedp(dp++, rd);
|
||||
rd += op_readdp(dp) << 8;
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
} break;
|
||||
|
||||
//decw_dp
|
||||
case 0x1a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd--;
|
||||
op_writedp(dp++, rd);
|
||||
rd += op_readdp(dp) << 8;
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
} break;
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
uint8 ram_read(uint16 addr);
|
||||
void ram_write(uint16 addr, uint8 data);
|
||||
|
||||
uint8 port_read(uint8 port);
|
||||
void port_write(uint8 port, uint8 data);
|
||||
|
||||
//======================
|
||||
//core SMP bus functions
|
||||
//======================
|
||||
uint8 op_busread(uint16 addr);
|
||||
void op_buswrite(uint16 addr, uint8 data);
|
||||
|
||||
void op_io();
|
||||
uint8 op_read(uint16 addr);
|
||||
void op_write(uint16 addr, uint8 data);
|
||||
|
||||
//===================================================
|
||||
//helper memory addressing functions used by SMP core
|
||||
//===================================================
|
||||
uint8 op_readpc();
|
||||
|
||||
uint8 op_readstack();
|
||||
void op_writestack(uint8 data);
|
||||
|
||||
uint8 op_readaddr(uint16 addr);
|
||||
void op_writeaddr(uint16 addr, uint8 data);
|
||||
|
||||
uint8 op_readdp(uint8 addr);
|
||||
void op_writedp(uint8 addr, uint8 data);
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifdef SNES_CPP
|
||||
|
||||
void SNES::Audio::update(uint16 l_sample, uint16 r_sample) {
|
||||
snesinterface.audio_sample(l_sample, r_sample);
|
||||
}
|
||||
|
||||
void SNES::Audio::init() {
|
||||
}
|
||||
|
||||
#endif //ifdef SNES_CPP
|
||||
@@ -1,7 +0,0 @@
|
||||
class Audio {
|
||||
public:
|
||||
void update(uint16 l_sample, uint16 r_sample);
|
||||
void init();
|
||||
|
||||
friend class SNES;
|
||||
} audio;
|
||||
@@ -1,17 +0,0 @@
|
||||
//====================
|
||||
//SNES interface class
|
||||
//====================
|
||||
//Interfaces SNES core with platform-specific functionality (video, audio, input, ...)
|
||||
|
||||
class SNESInterface {
|
||||
public:
|
||||
void video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height);
|
||||
void audio_sample(uint16_t l_sample, uint16_t r_sample);
|
||||
void input_poll();
|
||||
int16_t input_poll(unsigned deviceid, unsigned id);
|
||||
|
||||
void init();
|
||||
void term();
|
||||
};
|
||||
|
||||
extern SNESInterface snesinterface;
|
||||
@@ -1,84 +0,0 @@
|
||||
#include "interface/interface.hpp"
|
||||
#include "scheduler/scheduler.hpp"
|
||||
#include "tracer/tracer.hpp"
|
||||
|
||||
class VideoFilter;
|
||||
|
||||
class SNES {
|
||||
public:
|
||||
enum Region { NTSC = 0, PAL = 1 };
|
||||
enum RegionAutodetect { Autodetect = 2 };
|
||||
enum ExpansionPortDevice { ExpansionNone = 0, ExpansionBSX = 1 };
|
||||
|
||||
struct Config {
|
||||
unsigned controller_port1;
|
||||
unsigned controller_port2;
|
||||
unsigned expansion_port;
|
||||
unsigned region;
|
||||
|
||||
struct File {
|
||||
bool autodetect_type;
|
||||
bool bypass_patch_crc32;
|
||||
} file;
|
||||
|
||||
struct Path {
|
||||
string base; //binary path
|
||||
string user; //user profile path (bsnes.cfg, ...)
|
||||
string current; //current working directory (path to currently loaded cartridge)
|
||||
string rom, save, patch, cheat, data;
|
||||
string bsx, st;
|
||||
} path;
|
||||
|
||||
struct CPU {
|
||||
unsigned version;
|
||||
unsigned ntsc_clock_rate;
|
||||
unsigned pal_clock_rate;
|
||||
unsigned alu_mul_delay;
|
||||
unsigned alu_div_delay;
|
||||
unsigned wram_init_value;
|
||||
} cpu;
|
||||
|
||||
struct SMP {
|
||||
unsigned ntsc_clock_rate;
|
||||
unsigned pal_clock_rate;
|
||||
} smp;
|
||||
|
||||
struct PPU1 {
|
||||
unsigned version;
|
||||
} ppu1;
|
||||
|
||||
struct PPU2 {
|
||||
unsigned version;
|
||||
} ppu2;
|
||||
} config;
|
||||
|
||||
//system functions
|
||||
virtual void run();
|
||||
virtual void runtoframe();
|
||||
|
||||
virtual void init();
|
||||
virtual void term();
|
||||
virtual void power();
|
||||
virtual void reset();
|
||||
|
||||
virtual void frame();
|
||||
virtual void scanline();
|
||||
|
||||
//return *active* region / expansion port device information
|
||||
//settings cached upon power-on
|
||||
Region region() const;
|
||||
ExpansionPortDevice expansion() const;
|
||||
|
||||
#include "video/video.hpp"
|
||||
#include "audio/audio.hpp"
|
||||
#include "input/input.hpp"
|
||||
|
||||
SNES();
|
||||
virtual ~SNES() {}
|
||||
|
||||
private:
|
||||
unsigned snes_region;
|
||||
unsigned snes_expansion;
|
||||
};
|
||||
|
||||
extern SNES snes;
|
||||
@@ -1,85 +0,0 @@
|
||||
##############################
|
||||
### platform configuration ###
|
||||
##############################
|
||||
|
||||
objects := main $(if $(call streq,$(platform),win),resource) $(objects)
|
||||
|
||||
moc = moc
|
||||
rcc = rcc
|
||||
|
||||
ifeq ($(platform),x) # X11
|
||||
link += $(call mklib,Xtst)
|
||||
link += `pkg-config --libs QtCore QtGui`
|
||||
qtflags = `pkg-config --cflags QtCore QtGui`
|
||||
else ifeq ($(platform),win) # Windows
|
||||
qtdir = c:/qt450
|
||||
|
||||
link += $(call mklibpath,$(qtdir)/lib)
|
||||
link += $(call mklibpath,$(qtdir)/plugins/imageformats)
|
||||
|
||||
link += $(call mklib,mingw32)
|
||||
link += $(call mklib,qtmain)
|
||||
link += $(call mklib,QtGui)
|
||||
link += $(call mklib,comdlg32)
|
||||
link += $(call mklib,oleaut32)
|
||||
link += $(call mklib,imm32)
|
||||
link += $(call mklib,winmm)
|
||||
link += $(call mklib,winspool)
|
||||
link += $(call mklib,msimg32)
|
||||
link += $(call mklib,QtCore)
|
||||
link += $(call mklib,ole32)
|
||||
link += $(call mklib,advapi32)
|
||||
link += $(call mklib,ws2_32)
|
||||
link += $(call mklib,uuid)
|
||||
link += $(call mklib,gdi32)
|
||||
|
||||
# optional image-file support:
|
||||
# link += $(call mklib,qjpeg)
|
||||
# link += $(call mklib,qmng)
|
||||
|
||||
qtflags = $(call mkincpath,$(qtdir)/include)
|
||||
qtflags += $(call mkincpath,$(qtdir)/include/QtCore)
|
||||
qtflags += $(call mkincpath,$(qtdir)/include/QtGui)
|
||||
endif
|
||||
|
||||
moc_objects = \
|
||||
$(ui)/base/main.moc \
|
||||
$(ui)/base/loader.moc \
|
||||
$(ui)/base/htmlviewer.moc \
|
||||
$(ui)/base/about.moc \
|
||||
$(ui)/settings/settings.moc \
|
||||
$(ui)/settings/video.moc \
|
||||
$(ui)/settings/audio.moc \
|
||||
$(ui)/settings/input.moc \
|
||||
$(ui)/settings/paths.moc \
|
||||
$(ui)/settings/cheateditor.moc \
|
||||
$(ui)/settings/advanced.moc \
|
||||
$(ui)/settings/utility/inputcapture.moc \
|
||||
$(ui)/settings/utility/codeeditor.moc \
|
||||
|
||||
#############
|
||||
### rules ###
|
||||
#############
|
||||
|
||||
%.moc: $<; $(moc) $(patsubst %.moc,%.hpp,$@) -o $@
|
||||
$(foreach object,$(moc_objects),$(eval $(object): $(patsubst %.moc,%.hpp,$(object))))
|
||||
|
||||
obj/main.$(obj): $(ui)/main.cpp \
|
||||
$(ui)/* $(ui)/input/* $(ui)/utility/* $(ui)/base/* $(ui)/settings/* $(ui)/settings/utility/* \
|
||||
data/*
|
||||
$(call compile,$(qtflags))
|
||||
|
||||
$(ui)/resource/resource.rcc: $(ui)/resource/resource.qrc data/*
|
||||
$(rcc) $(ui)/resource/resource.qrc -o $(ui)/resource/resource.rcc
|
||||
|
||||
obj/resource.$(obj): $(ui)/resource/resource.rc
|
||||
windres $(ui)/resource/resource.rc obj/resource.$(obj)
|
||||
|
||||
###############
|
||||
### targets ###
|
||||
###############
|
||||
|
||||
ui_build: $(ui)/resource/resource.rcc $(moc_objects);
|
||||
ui_clean:
|
||||
-$(foreach object,$(moc_objects),@$(call delete,$(object)))
|
||||
-@$(call delete,$(ui)/resource/resource.rcc)
|
||||
@@ -1,31 +0,0 @@
|
||||
SNESInterface snesinterface;
|
||||
|
||||
void SNESInterface::video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height) {
|
||||
uint32_t *output;
|
||||
unsigned outpitch;
|
||||
if(video.lock(output, outpitch) == true) {
|
||||
unsigned outwidth, outheight;
|
||||
libfilter::filter.render(output, outpitch, outwidth, outheight, data, pitch, line, width, height);
|
||||
video.unlock();
|
||||
video.refresh(outwidth, outheight);
|
||||
}
|
||||
}
|
||||
|
||||
void SNESInterface::audio_sample(uint16_t left, uint16_t right) {
|
||||
if(config.audio.mute) left = right = 0;
|
||||
audio.sample(left, right);
|
||||
}
|
||||
|
||||
void SNESInterface::input_poll() {
|
||||
inputManager.poll();
|
||||
}
|
||||
|
||||
int16_t SNESInterface::input_poll(unsigned deviceid, unsigned id) {
|
||||
return inputManager.getStatus(deviceid, id);
|
||||
}
|
||||
|
||||
void SNESInterface::init() {
|
||||
}
|
||||
|
||||
void SNESInterface::term() {
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
string Utility::selectCartridge() {
|
||||
audio.clear();
|
||||
QString filename = QFileDialog::getOpenFileName(0,
|
||||
"Load Cartridge",
|
||||
utf8() << (snes.config.path.rom != "" ? snes.config.path.rom : snes.config.path.current),
|
||||
"SNES images (*.smc *.sfc *.swc *.fig *.bs *.st"
|
||||
#if defined(GZIP_SUPPORT)
|
||||
" *.zip *.gz"
|
||||
#endif
|
||||
#if defined(JMA_SUPPORT)
|
||||
" *.jma"
|
||||
#endif
|
||||
");;"
|
||||
"All files (*)"
|
||||
);
|
||||
return string() << filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
string Utility::selectFolder(const char *title) {
|
||||
audio.clear();
|
||||
QString pathname = QFileDialog::getExistingDirectory(0,
|
||||
title, utf8() << snes.config.path.current,
|
||||
QFileDialog::ShowDirsOnly);
|
||||
return string() << pathname.toUtf8().constData();
|
||||
}
|
||||
|
||||
void Utility::loadCartridge(const char *filename) {
|
||||
switch(cartridge.detect_image_type(filename)) {
|
||||
case Cartridge::TypeNormal: loadCartridgeNormal(filename); break;
|
||||
case Cartridge::TypeBsxSlotted: winLoader->loadBsxSlottedCartridge(filename, ""); break;
|
||||
case Cartridge::TypeBsxBios: winLoader->loadBsxCartridge(filename, ""); break;
|
||||
case Cartridge::TypeBsx: winLoader->loadBsxCartridge(snes.config.path.bsx, filename); break;
|
||||
case Cartridge::TypeSufamiTurboBios: winLoader->loadSufamiTurboCartridge(filename, "", ""); break;
|
||||
case Cartridge::TypeSufamiTurbo: winLoader->loadSufamiTurboCartridge(snes.config.path.st, filename, ""); break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Utility::loadCartridgeNormal(const char *base) {
|
||||
if(!*base) return false;
|
||||
unloadCartridge();
|
||||
cartridge.load_normal(base);
|
||||
modifySystemState(LoadCartridge);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utility::loadCartridgeBsxSlotted(const char *base, const char *slot) {
|
||||
if(!*base) return false;
|
||||
unloadCartridge();
|
||||
cartridge.load_bsx_slotted(base, slot);
|
||||
modifySystemState(LoadCartridge);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utility::loadCartridgeBsx(const char *base, const char *slot) {
|
||||
if(!*base) return false;
|
||||
unloadCartridge();
|
||||
cartridge.load_bsx(base, slot);
|
||||
modifySystemState(LoadCartridge);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utility::loadCartridgeSufamiTurbo(const char *base, const char *slotA, const char *slotB) {
|
||||
if(!*base) return false;
|
||||
unloadCartridge();
|
||||
cartridge.load_sufami_turbo(base, slotA, slotB);
|
||||
modifySystemState(LoadCartridge);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Utility::unloadCartridge() {
|
||||
if(cartridge.loaded()) {
|
||||
cartridge.unload();
|
||||
modifySystemState(UnloadCartridge);
|
||||
}
|
||||
}
|
||||
|
||||
void Utility::modifySystemState(system_state_t state) {
|
||||
video.clear();
|
||||
audio.clear();
|
||||
|
||||
switch(state) {
|
||||
case LoadCartridge: {
|
||||
//must call cartridge.load_cart_...() before calling modifySystemState(LoadCartridge)
|
||||
if(cartridge.loaded() == false) break;
|
||||
|
||||
application.power = true;
|
||||
application.pause = false;
|
||||
snes.power();
|
||||
|
||||
//warn if unsupported hardware detected
|
||||
string chip;
|
||||
if(cartridge.has_superfx()) chip = "SuperFX";
|
||||
else if(cartridge.has_sa1()) chip = "SA-1";
|
||||
else if(cartridge.has_st011()) chip = "ST011";
|
||||
else if(cartridge.has_st018()) chip = "ST018";
|
||||
else if(cartridge.has_dsp3()) chip = "DSP-3";
|
||||
if(chip != "") {
|
||||
QMessageBox::warning(winMain->window, "Warning", utf8()
|
||||
<< "<p><b>Warning:</b><br>Unsupported " << chip << " chip detected. "
|
||||
<< "It is unlikely that this title will work properly.</p>");
|
||||
}
|
||||
|
||||
showMessage(utf8()
|
||||
<< "Loaded " << cartridge.name()
|
||||
<< (cartridge.patched() ? ", and applied UPS patch." : "."));
|
||||
winMain->window->setWindowTitle(utf8() << BSNES_TITLE << " - " << cartridge.name());
|
||||
} break;
|
||||
|
||||
case UnloadCartridge: {
|
||||
if(cartridge.loaded() == false) break; //no cart to unload?
|
||||
cartridge.unload();
|
||||
|
||||
application.power = false;
|
||||
application.pause = true;
|
||||
|
||||
showMessage(utf8() << "Unloaded " << cartridge.name() << ".");
|
||||
winMain->window->setWindowTitle(utf8() << BSNES_TITLE);
|
||||
} break;
|
||||
|
||||
case PowerOn: {
|
||||
if(cartridge.loaded() == false || application.power == true) break;
|
||||
|
||||
application.power = true;
|
||||
application.pause = false;
|
||||
snes.power();
|
||||
|
||||
showMessage("Power on.");
|
||||
} break;
|
||||
|
||||
case PowerOff: {
|
||||
if(cartridge.loaded() == false || application.power == false) break;
|
||||
|
||||
application.power = false;
|
||||
application.pause = true;
|
||||
|
||||
showMessage("Power off.");
|
||||
} break;
|
||||
|
||||
case PowerCycle: {
|
||||
if(cartridge.loaded() == false) break;
|
||||
|
||||
application.power = true;
|
||||
application.pause = false;
|
||||
snes.power();
|
||||
|
||||
showMessage("System power was cycled.");
|
||||
} break;
|
||||
|
||||
case Reset: {
|
||||
if(cartridge.loaded() == false || application.power == false) break;
|
||||
|
||||
application.pause = false;
|
||||
snes.reset();
|
||||
|
||||
showMessage("System was reset.");
|
||||
} break;
|
||||
}
|
||||
|
||||
winMain->syncUi();
|
||||
winCodeEditor->dismiss();
|
||||
winCheatEditor->reloadList();
|
||||
winCheatEditor->syncUi();
|
||||
}
|
||||
8
bugs/project.yaml
Normal file
8
bugs/project.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
--- !ditz.rubyforge.org,2008-03-06/project
|
||||
name: snesram
|
||||
version: "0.5"
|
||||
components:
|
||||
- !ditz.rubyforge.org,2008-03-06/component
|
||||
name: snesram
|
||||
releases: []
|
||||
|
||||
@@ -182,7 +182,7 @@ AVRDUDE_PROGRAMMER = stk500v2
|
||||
|
||||
# com1 = serial port. Use lpt1 to connect to parallel port.
|
||||
|
||||
AVRDUDE_PORT = /dev/tty.PL2303-00002006
|
||||
AVRDUDE_PORT =/dev/tty.PL2303-00001124
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
# Revision: $Id: checksize 83 2006-01-05 22:20:53Z cs $
|
||||
|
||||
error=0
|
||||
codelimit=8192 # default value
|
||||
datalimit=992 # default value; leave 32 bytes for stack
|
||||
codelimit=2048 # default value
|
||||
datalimit=96 # default value; leave 32 bytes for stack
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
codelimit="$2"
|
||||
|
||||
@@ -29,7 +29,7 @@ extern FILE uart_stdout;
|
||||
#define RAM_REG PINA
|
||||
|
||||
#define CTRL_PORT PORTB
|
||||
#define CTR_DIR DDRB
|
||||
#define CTRL_DIR DDRB
|
||||
#define LATCH_PORT PORTB
|
||||
#define LATCH_DIR DDRB
|
||||
|
||||
@@ -39,14 +39,77 @@ extern FILE uart_stdout;
|
||||
#define LED_PORT PORTD
|
||||
#define LED_DIR DDRD
|
||||
|
||||
#define FILENAME "sprite.raw"
|
||||
//#define FILENAME "sprite.raw" //ok
|
||||
//#define FILENAME "ascii.smc" //ok
|
||||
//#define FILENAME "rom.smc" //ok
|
||||
//#define FILENAME "supert.smc" //ok
|
||||
//#define FILENAME "vortex.smc" //failed
|
||||
//#define FILENAME "mrdo.smc" //failed
|
||||
//#define FILENAME "spacei.smc" //ok ntsc
|
||||
//#define FILENAME "bank01.smc" //ok
|
||||
//#define FILENAME "bank02.smc" //ok
|
||||
//#define FILENAME "bank03.smc" //ok
|
||||
//#define FILENAME "bank04.smc" //ok
|
||||
//#define FILENAME "bank05.smc" //ok
|
||||
//#define FILENAME "bank06.smc" //ok
|
||||
//#define FILENAME "bank07.smc" //ok
|
||||
//#define FILENAME "banklo.smc" //ok
|
||||
//#define FILENAME "bankhi.smc" //ok
|
||||
//#define FILENAME "vram2.smc" //ok
|
||||
//#define FILENAME "super02.smc" //ok
|
||||
//#define FILENAME "super01.smc"//ok
|
||||
//#define FILENAME "crc.smc" //ok
|
||||
//#define FILENAME "banks.smc" //ok
|
||||
//#define FILENAME "hungry.smc" //ok
|
||||
//#define FILENAME "arkanoid.smc"//ok
|
||||
//#define FILENAME "eric.smc"
|
||||
#define FILENAME "turrican.smc"
|
||||
|
||||
#define ROMSIZE 4
|
||||
#define DUMPNAME "dump256.smc"
|
||||
#define BUFFER_SIZE 512
|
||||
#define BLOCKS 512
|
||||
#define BLOCKS (ROMSIZE << 8)
|
||||
#define MEMSIZE 0x80000
|
||||
|
||||
uint8_t read_buffer[BUFFER_SIZE];
|
||||
|
||||
|
||||
uint16_t crc_xmodem_update (uint16_t crc, uint8_t data)
|
||||
{
|
||||
int i;
|
||||
crc = crc ^ ((uint16_t)data << 8);
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
if (crc & 0x8000)
|
||||
crc = (crc << 1) ^ 0x1021;
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t do_crc(uint8_t * data,uint16_t size)
|
||||
{
|
||||
uint16_t crc =0;
|
||||
uint16_t i;
|
||||
for (i=0; i<size; i++){
|
||||
crc = crc_xmodem_update(crc,data[i]);
|
||||
//printf("%x : %x\n",crc,data[i]);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size)
|
||||
{
|
||||
uint16_t i;
|
||||
for (i=0; i<size; i++)
|
||||
crc = crc_xmodem_update(crc,data[i]);
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
void dump_packet(uint32_t addr,uint32_t len,uint8_t *packet){
|
||||
uint16_t i,j;
|
||||
uint16_t sum = 0;
|
||||
@@ -101,6 +164,17 @@ void spi_master_transmit(unsigned char cData)
|
||||
while(!(SPSR & (1<<SPIF)));
|
||||
}
|
||||
|
||||
|
||||
void sram_set_addr(uint32_t addr)
|
||||
{
|
||||
spi_master_transmit((uint8_t)(addr>>16));
|
||||
spi_master_transmit((uint8_t)(addr>>8));
|
||||
spi_master_transmit((uint8_t)(addr>>0));
|
||||
|
||||
LATCH_PORT |= (1<<S_LATCH);
|
||||
LATCH_PORT &= ~(1<<S_LATCH);
|
||||
}
|
||||
|
||||
uint8_t sram_read(uint32_t addr)
|
||||
{
|
||||
uint8_t byte;
|
||||
@@ -164,18 +238,28 @@ void sram_init(void){
|
||||
RAM_DIR = 0x00;
|
||||
RAM_PORT = 0x00;
|
||||
|
||||
CTR_DIR |= ((1<<R_WR) | (1<<R_RD));
|
||||
CTRL_DIR |= ((1<<R_WR) | (1<<R_RD));
|
||||
CTRL_PORT |= (1<<R_RD);
|
||||
CTRL_PORT |= (1<<R_WR);
|
||||
|
||||
LED_PORT |= (1<<D_LED0);
|
||||
}
|
||||
|
||||
void sram_snes_mode(void){
|
||||
void sram_snes_mode01(void){
|
||||
CTRL_PORT |= (1<<R_WR);
|
||||
CTRL_PORT &= ~(1<<R_RD);
|
||||
}
|
||||
|
||||
void sram_snes_mode02(void){
|
||||
CTRL_DIR |= (1<<R_WR);
|
||||
CTRL_PORT |= (1<<R_WR);
|
||||
//CTRL_PORT &= ~(1<<R_RD);
|
||||
CTRL_DIR &= ~(1<<R_RD);
|
||||
CTRL_PORT &= ~(1<<R_RD);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void sram_clear(uint32_t addr, uint32_t len){
|
||||
|
||||
uint32_t i;
|
||||
@@ -217,8 +301,9 @@ int main(void)
|
||||
uint8_t fat_attrib = 0;
|
||||
uint32_t fat_size = 0;
|
||||
uint32_t rom_addr = 0;
|
||||
uint32_t skip_block = 0;
|
||||
|
||||
uint8_t bank_cnt = 0;
|
||||
uint16_t crc = 0;
|
||||
uint16_t block_cnt;
|
||||
uart_init();
|
||||
stdout = &uart_stdout;
|
||||
|
||||
@@ -228,19 +313,37 @@ int main(void)
|
||||
spi_init();
|
||||
printf("SPI Init\n");
|
||||
|
||||
|
||||
//sram_clear(0x000000, 0x400000);
|
||||
//printf("sram_clear\n");
|
||||
#if 0
|
||||
uint8_t t[] = "david";
|
||||
printf("Test CRC %x\n",do_crc(t,5));
|
||||
while(1);
|
||||
#endif
|
||||
|
||||
//printf("read 0x0f0f\n");
|
||||
//sram_read(0x0f0f);
|
||||
//printf("write 0x0f0f\n");
|
||||
//sram_write(0x0f0f,0xaa);
|
||||
//while(1);
|
||||
|
||||
#if 0
|
||||
sram_clear(0x000000, 0x80000);
|
||||
printf("sram_clear\n");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printf("read 0x0f0f\n");
|
||||
sram_read(0x0f0f);
|
||||
printf("write 0x0f0f\n");
|
||||
sram_write(0x0f0f,0xaa);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
rom_addr = 0x4aaaa;
|
||||
printf("write %lx\n",rom_addr);
|
||||
sram_set_addr(rom_addr);
|
||||
while(1);
|
||||
#endif
|
||||
|
||||
|
||||
while ( mmc_init() !=0) {
|
||||
printf("No sdcard...\n");
|
||||
}
|
||||
printf("MMC Init sone\n");
|
||||
printf("MMC Init done\n");
|
||||
fat_init(read_buffer);
|
||||
printf("FAT Init done.\n");
|
||||
rom_addr = 0x000000;
|
||||
@@ -253,29 +356,102 @@ int main(void)
|
||||
read_buffer) == 1) {
|
||||
|
||||
|
||||
for (uint16_t block_cnt=0; block_cnt<BLOCKS; block_cnt++) {
|
||||
for (block_cnt=0; block_cnt<BLOCKS; block_cnt++) {
|
||||
fat_read_file (fat_cluster,read_buffer,block_cnt);
|
||||
if (block_cnt % 16 == 0)
|
||||
printf("Write Ram 0x%lx Skipped %li\n",rom_addr,skip_block);
|
||||
|
||||
if (sram_check(read_buffer,512))
|
||||
sram_copy(rom_addr,read_buffer,512);
|
||||
else
|
||||
skip_block +=1;
|
||||
if (block_cnt && block_cnt % 64 == 0){
|
||||
printf("Write Ram Bank: 0x%x Addr: 0x%lx Block: %x CRC: %x\n",bank_cnt,rom_addr,block_cnt,crc);
|
||||
bank_cnt++;
|
||||
crc = 0;
|
||||
}
|
||||
crc = do_crc_update(crc,read_buffer,512);
|
||||
sram_copy(rom_addr,read_buffer,512);
|
||||
rom_addr += 512;
|
||||
}
|
||||
printf("Done 0x%lx Skipped %li\n",rom_addr,skip_block);
|
||||
printf("Write Ram Bank: 0x%x Addr: 0x%lx Block: %x CRC: %x\n",bank_cnt,rom_addr,block_cnt,crc);
|
||||
printf("Done\n");
|
||||
}
|
||||
|
||||
|
||||
printf("Dump Headern\r");
|
||||
rom_addr = 0x8000-512;
|
||||
sram_read_buffer(rom_addr,read_buffer,512);
|
||||
dump_packet(rom_addr,512,read_buffer);
|
||||
|
||||
#if 0
|
||||
printf("Dump Memory\n\r");
|
||||
rom_addr = 0x000000;
|
||||
for (uint16_t block_cnt=0; block_cnt<BLOCKS; block_cnt++) {
|
||||
for (uint16_t block_cnt=0; block_cnt < 64; block_cnt++) {
|
||||
sram_read_buffer(rom_addr,read_buffer,512);
|
||||
dump_packet(rom_addr,512,read_buffer);
|
||||
rom_addr += 512;
|
||||
}
|
||||
printf("\nDone 0x%lx\n",rom_addr);
|
||||
sram_snes_mode();
|
||||
printf("\nEnter Snes mode\n");
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
block_cnt = 0;
|
||||
crc = 0;
|
||||
bank_cnt=0x00;
|
||||
rom_addr = 0x000000;
|
||||
for (block_cnt=0; block_cnt<BLOCKS; block_cnt++) {
|
||||
sram_read_buffer(rom_addr,read_buffer,512);
|
||||
if (block_cnt && block_cnt % 64 == 0){
|
||||
printf("Read Ram Bank: 0x%x Addr: 0x%lx Block: %x CRC: %x\n",bank_cnt,rom_addr,block_cnt,crc);
|
||||
bank_cnt++;
|
||||
crc = 0;
|
||||
}
|
||||
crc = do_crc_update(crc,read_buffer,512);
|
||||
rom_addr += 512;
|
||||
}
|
||||
printf("Read Ram Bank: 0x%x Addr: 0x%lx Block: %x CRC: %x\n",bank_cnt,rom_addr,block_cnt,crc);
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
printf("Look for %s\n",DUMPNAME);
|
||||
|
||||
fat_cluster = 0;
|
||||
fat_attrib = 0;
|
||||
fat_size = 0;
|
||||
|
||||
if (fat_search_file((uint8_t*)DUMPNAME,
|
||||
&fat_cluster,
|
||||
&fat_size,
|
||||
&fat_attrib,
|
||||
read_buffer) == 1) {
|
||||
|
||||
|
||||
printf("Found %s\n",DUMPNAME);
|
||||
rom_addr = 0x000000;
|
||||
bank_cnt =0;
|
||||
for (uint16_t block_cnt=0; block_cnt<BLOCKS; block_cnt++) {
|
||||
printf("Write 1");
|
||||
sram_read_buffer(rom_addr,read_buffer,512);
|
||||
printf("Write 2");
|
||||
fat_write_file (fat_cluster,read_buffer,block_cnt);
|
||||
if (block_cnt % 64 == 0){
|
||||
bank_cnt++;
|
||||
}
|
||||
printf("Write File Bank: 0x%x Addr: 0x%lx Skipped: %li\n",bank_cnt,rom_addr,skip_block);
|
||||
rom_addr += 512;
|
||||
}
|
||||
printf("Done 0x%lx Skipped %li\n",rom_addr,skip_block);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
sram_snes_mode01();
|
||||
printf("\nEnter Snes mode 02\n");
|
||||
#endif
|
||||
#if 0
|
||||
sram_snes_mode02();
|
||||
printf("\nEnter Snes mode 02\n");
|
||||
#endif
|
||||
|
||||
printf("\nUpload done.\n");
|
||||
|
||||
while(1);
|
||||
return 0 ;
|
||||
|
||||
|
||||
168
poc/avr_usbload/Makefile
Normal file
168
poc/avr_usbload/Makefile
Normal file
@@ -0,0 +1,168 @@
|
||||
# Name: Makefile
|
||||
# Project: custom-class example
|
||||
# Author: Christian Starkjohann
|
||||
# Creation Date: 2008-04-07
|
||||
# Tabsize: 4
|
||||
# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
# This Revision: $Id: Makefile 692 2008-11-07 15:07:40Z cs $
|
||||
|
||||
DEVICE = atmega16
|
||||
F_CPU = 16000000 # in Hz
|
||||
FUSE_L = # see below for fuse values for particular devices
|
||||
FUSE_H =
|
||||
AVRDUDE = avrdude -c stk500v2 -p $(DEVICE) -P /dev/tty.PL2303-00002006
|
||||
#AVRDUDE = avrdude -c stk500v2 -p $(DEVICE) -P /dev/tty.PL2303-00001424
|
||||
|
||||
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
|
||||
#-std=gnu99
|
||||
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o uart.o fifo.o sram.o crc.o debug.o
|
||||
|
||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
|
||||
|
||||
##############################################################################
|
||||
# Fuse values for particular devices
|
||||
##############################################################################
|
||||
# If your device is not listed here, go to
|
||||
# http://palmavr.sourceforge.net/cgi-bin/fc.cgi
|
||||
# and choose options for external crystal clock and no clock divider
|
||||
#
|
||||
################################## ATMega8 ##################################
|
||||
# ATMega8 FUSE_L (Fuse low byte):
|
||||
# 0x9f = 1 0 0 1 1 1 1 1
|
||||
# ^ ^ \ / \--+--/
|
||||
# | | | +------- CKSEL 3..0 (external >8M crystal)
|
||||
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
|
||||
# | +------------------ BODEN (BrownOut Detector enabled)
|
||||
# +-------------------- BODLEVEL (2.7V)
|
||||
# ATMega8 FUSE_H (Fuse high byte):
|
||||
# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
|
||||
# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0
|
||||
# | | | | | +-------- BOOTSZ1
|
||||
# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase)
|
||||
# | | | +-------------- CKOPT (full output swing)
|
||||
# | | +---------------- SPIEN (allow serial programming)
|
||||
# | +------------------ WDTON (WDT not always on)
|
||||
# +-------------------- RSTDISBL (reset pin is enabled)
|
||||
#
|
||||
############################## ATMega48/88/168 ##############################
|
||||
# ATMega*8 FUSE_L (Fuse low byte):
|
||||
# 0xdf = 1 1 0 1 1 1 1 1
|
||||
# ^ ^ \ / \--+--/
|
||||
# | | | +------- CKSEL 3..0 (external >8M crystal)
|
||||
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
|
||||
# | +------------------ CKOUT (if 0: Clock output enabled)
|
||||
# +-------------------- CKDIV8 (if 0: divide by 8)
|
||||
# ATMega*8 FUSE_H (Fuse high byte):
|
||||
# 0xde = 1 1 0 1 1 1 1 0
|
||||
# ^ ^ ^ ^ ^ \-+-/
|
||||
# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V)
|
||||
# | | | | + --------- EESAVE (preserve EEPROM over chip erase)
|
||||
# | | | +-------------- WDTON (if 0: watchdog always on)
|
||||
# | | +---------------- SPIEN (allow serial programming)
|
||||
# | +------------------ DWEN (debug wire enable)
|
||||
# +-------------------- RSTDISBL (reset pin is enabled)
|
||||
#
|
||||
############################## ATTiny25/45/85 ###############################
|
||||
# ATMega*5 FUSE_L (Fuse low byte):
|
||||
# 0xef = 1 1 1 0 1 1 1 1
|
||||
# ^ ^ \+/ \--+--/
|
||||
# | | | +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz)
|
||||
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power)
|
||||
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
|
||||
# +-------------------- CKDIV8 (divide clock by 8 -> don't divide)
|
||||
# ATMega*5 FUSE_H (Fuse high byte):
|
||||
# 0xdd = 1 1 0 1 1 1 0 1
|
||||
# ^ ^ ^ ^ ^ \-+-/
|
||||
# | | | | | +------ BODLEVEL 2..0 (brownout trigger level -> 2.7V)
|
||||
# | | | | +---------- EESAVE (preserve EEPROM on Chip Erase -> not preserved)
|
||||
# | | | +-------------- WDTON (watchdog timer always on -> disable)
|
||||
# | | +---------------- SPIEN (enable serial programming -> enabled)
|
||||
# | +------------------ DWEN (debug wire enable)
|
||||
# +-------------------- RSTDISBL (disable external reset -> enabled)
|
||||
#
|
||||
################################ ATTiny2313 #################################
|
||||
# ATTiny2313 FUSE_L (Fuse low byte):
|
||||
# 0xef = 1 1 1 0 1 1 1 1
|
||||
# ^ ^ \+/ \--+--/
|
||||
# | | | +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz)
|
||||
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power)
|
||||
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
|
||||
# +-------------------- CKDIV8 (divide clock by 8 -> don't divide)
|
||||
# ATTiny2313 FUSE_H (Fuse high byte):
|
||||
# 0xdb = 1 1 0 1 1 0 1 1
|
||||
# ^ ^ ^ ^ \-+-/ ^
|
||||
# | | | | | +---- RSTDISBL (disable external reset -> enabled)
|
||||
# | | | | +-------- BODLEVEL 2..0 (brownout trigger level -> 2.7V)
|
||||
# | | | +-------------- WDTON (watchdog timer always on -> disable)
|
||||
# | | +---------------- SPIEN (enable serial programming -> enabled)
|
||||
# | +------------------ EESAVE (preserve EEPROM on Chip Erase -> not preserved)
|
||||
# +-------------------- DWEN (debug wire enable)
|
||||
|
||||
|
||||
# symbolic targets:
|
||||
help:
|
||||
@echo "This Makefile has no default rule. Use one of the following:"
|
||||
@echo "make hex ....... to build main.hex"
|
||||
@echo "make program ... to flash fuses and firmware"
|
||||
@echo "make fuse ...... to flash the fuses"
|
||||
@echo "make flash ..... to flash the firmware (use this on metaboard)"
|
||||
@echo "make clean ..... to delete objects and hex file"
|
||||
|
||||
all: hex
|
||||
|
||||
hex: main.hex
|
||||
|
||||
program: flash fuse
|
||||
|
||||
# rule for programming fuse bits:
|
||||
fuse:
|
||||
@[ "$(FUSE_H)" != "" -a "$(FUSE_L)" != "" ] || \
|
||||
{ echo "*** Edit Makefile and choose values for FUSE_L and FUSE_H!"; exit 1; }
|
||||
$(AVRDUDE) -U hfuse:w:$(FUSE_H):m -U lfuse:w:$(FUSE_L):m
|
||||
|
||||
# rule for uploading firmware:
|
||||
flash: main.hex
|
||||
$(AVRDUDE) -U flash:w:main.hex:i
|
||||
|
||||
# rule for deleting dependent files (those which can be built by Make):
|
||||
clean:
|
||||
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s
|
||||
|
||||
# Generic rule for compiling C files:
|
||||
.c.o:
|
||||
$(COMPILE) -c $< -o $@
|
||||
|
||||
# Generic rule for assembling Assembler source files:
|
||||
.S.o:
|
||||
$(COMPILE) -x assembler-with-cpp -c $< -o $@
|
||||
# "-x assembler-with-cpp" should not be necessary since this is the default
|
||||
# file type for the .S (with capital S) extension. However, upper case
|
||||
# characters are not always preserved on Windows. To ensure WinAVR
|
||||
# compatibility define the file type manually.
|
||||
|
||||
# Generic rule for compiling C to assembler, used for debugging only.
|
||||
.c.s:
|
||||
$(COMPILE) -S $< -o $@
|
||||
|
||||
# file targets:
|
||||
|
||||
# Since we don't want to ship the driver multipe times, we copy it into this project:
|
||||
usbdrv:
|
||||
cp -r ../../../usbdrv .
|
||||
|
||||
main.elf: usbdrv $(OBJECTS) # usbdrv dependency only needed because we copy it
|
||||
$(COMPILE) -o main.elf $(OBJECTS)
|
||||
|
||||
main.hex: main.elf
|
||||
rm -f main.hex main.eep.hex
|
||||
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
|
||||
avr-size main.hex
|
||||
|
||||
# debugging targets:
|
||||
|
||||
disasm: main.elf
|
||||
avr-objdump -d main.elf
|
||||
|
||||
cpp:
|
||||
$(COMPILE) -E main.c
|
||||
35
poc/avr_usbload/checksize
Normal file
35
poc/avr_usbload/checksize
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
# Name: checksize
|
||||
# Project: PowerSwitch/AVR-USB
|
||||
# Author: Christian Starkjohann
|
||||
# Creation Date: 2004-12-29
|
||||
# Tabsize: 4
|
||||
# Copyright: (c) 2005 OBJECTIVE DEVELOPMENT Software GmbH.
|
||||
# Revision: $Id: checksize 83 2006-01-05 22:20:53Z cs $
|
||||
|
||||
error=0
|
||||
codelimit=16384 # default value
|
||||
datalimit=992 # default value; leave 32 bytes for stack
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
codelimit="$2"
|
||||
fi
|
||||
if [ $# -gt 2 ]; then
|
||||
datalimit="$3"
|
||||
fi
|
||||
|
||||
set -- `avr-size -d "$1" | awk '/[0-9]/ {print $1 + $2, $2 + $3, $2}'`
|
||||
if [ $1 -gt $codelimit ]; then
|
||||
echo "*** code size $1 exceeds limit of $codelimit"
|
||||
error=1
|
||||
else
|
||||
echo "ROM: $1 bytes (data=$3)"
|
||||
fi
|
||||
if [ $2 -gt $datalimit ]; then
|
||||
echo "*** data size $2 exceeds limit of $datalimit"
|
||||
error=1
|
||||
else
|
||||
echo "RAM: $2 bytes"
|
||||
fi
|
||||
|
||||
exit $error
|
||||
48
poc/avr_usbload/commandline/Makefile
Normal file
48
poc/avr_usbload/commandline/Makefile
Normal file
@@ -0,0 +1,48 @@
|
||||
# Name: Makefile
|
||||
# Project: custom-class example
|
||||
# Author: Christian Starkjohann
|
||||
# Creation Date: 2008-04-06
|
||||
# Tabsize: 4
|
||||
# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
# This Revision: $Id: Makefile 692 2008-11-07 15:07:40Z cs $
|
||||
|
||||
|
||||
# Concigure the following definitions according to your system.
|
||||
# This Makefile has been tested on Mac OS X, Linux and Windows.
|
||||
|
||||
# Use the following 3 lines on Unix (uncomment the framework on Mac OS X):
|
||||
USBFLAGS = `libusb-config --cflags`
|
||||
USBLIBS = `libusb-config --libs`
|
||||
EXE_SUFFIX =
|
||||
|
||||
# Use the following 3 lines on Windows and comment out the 3 above. You may
|
||||
# have to change the include paths to where you installed libusb-win32
|
||||
#USBFLAGS = -I/usr/local/include
|
||||
#USBLIBS = -L/usr/local/lib -lusb
|
||||
#EXE_SUFFIX = .exe
|
||||
|
||||
NAME = snesuploader
|
||||
|
||||
OBJECTS = opendevice.o $(NAME).o
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = $(CPPFLAGS) $(USBFLAGS) -O -g -Wall
|
||||
LIBS = $(USBLIBS)
|
||||
|
||||
PROGRAM = $(NAME)$(EXE_SUFFIX)
|
||||
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
$(PROGRAM): $(OBJECTS)
|
||||
$(CC) -o $(PROGRAM) $(OBJECTS) $(LIBS)
|
||||
|
||||
strip: $(PROGRAM)
|
||||
strip $(PROGRAM)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROGRAM)
|
||||
285
poc/avr_usbload/commandline/opendevice.c
Normal file
285
poc/avr_usbload/commandline/opendevice.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Name: opendevice.c Project: V-USB host-side library Author: Christian
|
||||
* Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c) 2008 by
|
||||
* OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see License.txt),
|
||||
* GNU GPL v3 or proprietary (CommercialLicense.txt) This Revision: $Id:
|
||||
* opendevice.c 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
* General Description: The functions in this module can be used to find and
|
||||
* open a device based on libusb or libusb-win32.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "opendevice.h"
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define MATCH_SUCCESS 1
|
||||
#define MATCH_FAILED 0
|
||||
#define MATCH_ABORT -1
|
||||
|
||||
/*
|
||||
* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or
|
||||
* MATCH_ABORT.
|
||||
*/
|
||||
static int _shellStyleMatch(char *text, char *p)
|
||||
{
|
||||
int last,
|
||||
matched,
|
||||
reverse;
|
||||
|
||||
for (; *p; text++, p++) {
|
||||
if (*text == 0 && *p != '*')
|
||||
return MATCH_ABORT;
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
/*
|
||||
* Literal match with following character.
|
||||
*/
|
||||
p++;
|
||||
/*
|
||||
* FALLTHROUGH
|
||||
*/
|
||||
default:
|
||||
if (*text != *p)
|
||||
return MATCH_FAILED;
|
||||
continue;
|
||||
case '?':
|
||||
/*
|
||||
* Match anything.
|
||||
*/
|
||||
continue;
|
||||
case '*':
|
||||
while (*++p == '*')
|
||||
/*
|
||||
* Consecutive stars act just like one.
|
||||
*/
|
||||
continue;
|
||||
if (*p == 0)
|
||||
/*
|
||||
* Trailing star matches everything.
|
||||
*/
|
||||
return MATCH_SUCCESS;
|
||||
while (*text)
|
||||
if ((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
|
||||
return matched;
|
||||
return MATCH_ABORT;
|
||||
case '[':
|
||||
reverse = p[1] == '^';
|
||||
if (reverse) /* Inverted character class. */
|
||||
p++;
|
||||
matched = MATCH_FAILED;
|
||||
if (p[1] == ']' || p[1] == '-')
|
||||
if (*++p == *text)
|
||||
matched = MATCH_SUCCESS;
|
||||
for (last = *p; *++p && *p != ']'; last = *p)
|
||||
if (*p == '-' && p[1] != ']' ? *text <= *++p
|
||||
&& *text >= last : *text == *p)
|
||||
matched = MATCH_SUCCESS;
|
||||
if (matched == reverse)
|
||||
return MATCH_FAILED;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return *text == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* public interface for shell style matching: returns 0 if fails, 1 if matches
|
||||
*/
|
||||
static int shellStyleMatch(char *text, char *pattern)
|
||||
{
|
||||
if (pattern == NULL) /* NULL pattern is synonymous to "*" */
|
||||
return 1;
|
||||
return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int usbGetStringAscii(usb_dev_handle * dev, int index, char *buf, int buflen)
|
||||
{
|
||||
char buffer[256];
|
||||
int rval,
|
||||
i;
|
||||
|
||||
if ((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use
|
||||
* libusb
|
||||
* version
|
||||
* if
|
||||
* it
|
||||
* works
|
||||
*/
|
||||
return rval;
|
||||
if ((rval =
|
||||
usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||
(USB_DT_STRING << 8) + index, 0x0409, buffer,
|
||||
sizeof(buffer), 5000)) < 0)
|
||||
return rval;
|
||||
if (buffer[1] != USB_DT_STRING) {
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
if ((unsigned char) buffer[0] < rval)
|
||||
rval = (unsigned char) buffer[0];
|
||||
rval /= 2;
|
||||
/*
|
||||
* lossy conversion to ISO Latin1:
|
||||
*/
|
||||
for (i = 1; i < rval; i++) {
|
||||
if (i > buflen) /* destination buffer overflow */
|
||||
break;
|
||||
buf[i - 1] = buffer[2 * i];
|
||||
if (buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||
buf[i - 1] = '?';
|
||||
}
|
||||
buf[i - 1] = 0;
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int usbOpenDevice(usb_dev_handle ** device, int vendorID,
|
||||
char *vendorNamePattern, int productID,
|
||||
char *productNamePattern, char *serialNamePattern,
|
||||
FILE * printMatchingDevicesFp, FILE * warningsFp)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for (bus = usb_get_busses(); bus; bus = bus->next) {
|
||||
for (dev = bus->devices; dev; dev = dev->next) { /* iterate over
|
||||
* all devices
|
||||
* on all
|
||||
* busses */
|
||||
if ((vendorID == 0 || dev->descriptor.idVendor == vendorID)
|
||||
&& (productID == 0 || dev->descriptor.idProduct == productID)) {
|
||||
char vendor[256],
|
||||
product[256],
|
||||
serial[256];
|
||||
int len;
|
||||
handle = usb_open(dev); /* we need to open the device in order
|
||||
* to query strings */
|
||||
if (!handle) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot open VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct, usb_strerror());
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* now check whether the names match:
|
||||
*/
|
||||
len = vendor[0] = 0;
|
||||
if (dev->descriptor.iManufacturer > 0) {
|
||||
len =
|
||||
usbGetStringAscii(handle, dev->descriptor.iManufacturer,
|
||||
vendor, sizeof(vendor));
|
||||
}
|
||||
if (len < 0) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct, usb_strerror());
|
||||
} else {
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/*
|
||||
* printf("seen device from vendor ->%s<-\n", vendor);
|
||||
*/
|
||||
if (shellStyleMatch(vendor, vendorNamePattern)) {
|
||||
len = product[0] = 0;
|
||||
if (dev->descriptor.iProduct > 0) {
|
||||
len =
|
||||
usbGetStringAscii(handle,
|
||||
dev->descriptor.iProduct,
|
||||
product, sizeof(product));
|
||||
}
|
||||
if (len < 0) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
usb_strerror());
|
||||
} else {
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/*
|
||||
* printf("seen product ->%s<-\n", product);
|
||||
*/
|
||||
if (shellStyleMatch(product, productNamePattern)) {
|
||||
len = serial[0] = 0;
|
||||
if (dev->descriptor.iSerialNumber > 0) {
|
||||
len =
|
||||
usbGetStringAscii(handle,
|
||||
dev->descriptor.
|
||||
iSerialNumber, serial,
|
||||
sizeof(serial));
|
||||
}
|
||||
if (len < 0) {
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if (warningsFp != NULL)
|
||||
fprintf(warningsFp,
|
||||
"Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
usb_strerror());
|
||||
}
|
||||
if (shellStyleMatch(serial, serialNamePattern)) {
|
||||
if (printMatchingDevicesFp != NULL) {
|
||||
if (serial[0] == 0) {
|
||||
fprintf(printMatchingDevicesFp,
|
||||
"VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
vendor, product);
|
||||
} else {
|
||||
fprintf(printMatchingDevicesFp,
|
||||
"VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n",
|
||||
dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct,
|
||||
vendor, product, serial);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if (handle) /* we have found a deice */
|
||||
break;
|
||||
}
|
||||
if (handle != NULL) {
|
||||
errorCode = 0;
|
||||
*device = handle;
|
||||
}
|
||||
if (printMatchingDevicesFp != NULL) /* never return an error for listing
|
||||
* only */
|
||||
errorCode = 0;
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: opendevice.h
|
||||
* Project: AVR-USB host-side library
|
||||
* Project: V-USB host-side library
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-10
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: opendevice.h 692 2008-11-07 15:07:40Z cs $
|
||||
* This Revision: $Id: opendevice.h 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
244
poc/avr_usbload/commandline/snesuploader.c
Normal file
244
poc/avr_usbload/commandline/snesuploader.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Name: set-led.c Project: custom-class, a basic USB example Author:
|
||||
* Christian Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c)
|
||||
* 2008 by OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see
|
||||
* License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) This
|
||||
* Revision: $Id: set-led.c 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
* General Description: This is the host-side driver for the custom-class
|
||||
* example device. It searches the USB for the LEDControl device and sends the
|
||||
* requests understood by this device. This program must be linked with libusb
|
||||
* on Unix and libusb-win32 on Windows. See http://libusb.sourceforge.net/ or
|
||||
* http://libusb-win32.sourceforge.net/ respectively.
|
||||
*/
|
||||
|
||||
|
||||
#define READ_BUFFER_SIZE 1024
|
||||
#define SEND_BUFFER_SIZE 128
|
||||
#define BUFFER_CRC (1024 * 32)
|
||||
#define BANK_SIZE (1<<15)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <usb.h> /* this is libusb */
|
||||
#include "opendevice.h" /* common code moved to separate module */
|
||||
|
||||
#include "../requests.h" /* custom request numbers */
|
||||
#include "../usbconfig.h" /* device's VID/PID and names */
|
||||
|
||||
|
||||
void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
|
||||
{
|
||||
uint16_t i,
|
||||
j;
|
||||
uint16_t sum = 0;
|
||||
uint8_t clear = 0;
|
||||
|
||||
for (i = 0; i < len; i += 16) {
|
||||
|
||||
sum = 0;
|
||||
for (j = 0; j < 16; j++) {
|
||||
sum += packet[i + j];
|
||||
}
|
||||
if (!sum) {
|
||||
clear = 1;
|
||||
continue;
|
||||
}
|
||||
if (clear) {
|
||||
printf("*\n");
|
||||
clear = 0;
|
||||
}
|
||||
printf("%08x:", addr + i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
printf(" %02x", packet[i + j]);
|
||||
}
|
||||
printf(" |");
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (packet[i + j] >= 33 && packet[i + j] <= 126)
|
||||
printf("%c", packet[i + j]);
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
|
||||
{
|
||||
int i;
|
||||
crc = crc ^ ((uint16_t) data << 8);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (crc & 0x8000)
|
||||
crc = (crc << 1) ^ 0x1021;
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t do_crc(uint8_t * data, uint16_t size)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint16_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc_xmodem_update(crc, data[i]);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
|
||||
{
|
||||
uint16_t i;
|
||||
for (i = 0; i < size; i++)
|
||||
crc = crc_xmodem_update(crc, data[i]);
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "usage:\n");
|
||||
fprintf(stderr, " %s upload filename.. upload\n", name);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
usb_dev_handle *handle = NULL;
|
||||
const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = {
|
||||
USB_CFG_DEVICE_ID};
|
||||
char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = {
|
||||
USB_CFG_DEVICE_NAME, 0};
|
||||
int cnt,
|
||||
vid,
|
||||
pid;
|
||||
int cnt_crc = 0;
|
||||
uint8_t *read_buffer;
|
||||
uint8_t *crc_buffer;
|
||||
uint32_t addr = 0;
|
||||
uint16_t addr_lo = 0;
|
||||
uint16_t addr_hi = 0;
|
||||
uint16_t step = 0;
|
||||
uint16_t crc = 0;
|
||||
uint8_t bank = 0;
|
||||
FILE *fp;
|
||||
|
||||
usb_init();
|
||||
if (argc < 2) { /* we need at least one argument */
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* compute VID/PID from usbconfig.h so that there is a central source
|
||||
* of information
|
||||
*/
|
||||
vid = rawVid[1] * 256 + rawVid[0];
|
||||
pid = rawPid[1] * 256 + rawPid[0];
|
||||
/*
|
||||
* The following function is in opendevice.c:
|
||||
*/
|
||||
if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) !=
|
||||
0) {
|
||||
fprintf(stderr,
|
||||
"Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n",
|
||||
product, vid, pid);
|
||||
exit(1);
|
||||
}
|
||||
printf("Open USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid,
|
||||
pid);
|
||||
if (strcasecmp(argv[1], "upload") == 0) {
|
||||
if (argc < 3) { /* we need at least one argument */
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
fp = fopen(argv[2], "r");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Cannot open file %s ", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
read_buffer = (unsigned char *) malloc(READ_BUFFER_SIZE);
|
||||
crc_buffer = (unsigned char *) malloc(BUFFER_CRC);
|
||||
memset(crc_buffer, 0, BUFFER_CRC);
|
||||
addr = 0x000000;
|
||||
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
|
||||
USB_UPLOAD_INIT, 0, 0, NULL, 0, 5000);
|
||||
|
||||
|
||||
while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
|
||||
for (step = 0; step < READ_BUFFER_SIZE; step += SEND_BUFFER_SIZE) {
|
||||
addr_lo = addr & 0xffff;
|
||||
addr_hi = (addr >> 16) & 0xff;
|
||||
usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_UPLOAD_ADDR, addr_hi,
|
||||
addr_lo, (char *) read_buffer + step,
|
||||
SEND_BUFFER_SIZE, 5000);
|
||||
#if 0
|
||||
dump_packet(addr, SEND_BUFFER_SIZE, read_buffer + step);
|
||||
#endif
|
||||
addr += SEND_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
memcpy(crc_buffer + cnt_crc, read_buffer, READ_BUFFER_SIZE);
|
||||
cnt_crc += READ_BUFFER_SIZE;
|
||||
if (cnt_crc >= BANK_SIZE) {
|
||||
crc = do_crc(crc_buffer, BANK_SIZE);
|
||||
printf
|
||||
("Addr: 0x%06x Bank: 0x%02x HiAddr: 0x%02x LoAddr: 0x%04x Crc: 0x%04x\n",
|
||||
addr, bank, addr_hi, addr_lo, crc);
|
||||
memset(crc_buffer, 0, BUFFER_CRC);
|
||||
bank++;
|
||||
cnt_crc = 0;
|
||||
}
|
||||
}
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_CRC, addr_hi, addr_lo, NULL,
|
||||
0, 5000);
|
||||
|
||||
|
||||
if (cnt < 1) {
|
||||
if (cnt < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
} else {
|
||||
fprintf(stderr, "only %d bytes received.\n", cnt);
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(argv[1], "crc") == 0) {
|
||||
/*
|
||||
* if(argc < 2){ usage(argv[0]); exit(1); }
|
||||
*/
|
||||
addr = 0x000000;
|
||||
addr_lo = addr & 0xffff;
|
||||
addr_hi = (addr >> 16) & 0xff;
|
||||
printf("Request CRC for Addr: 0x%06x\n", addr);
|
||||
|
||||
cnt = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, USB_CRC_ADDR, addr_hi, addr_lo,
|
||||
NULL, (1 << 15) / 4, 5000);
|
||||
|
||||
if (cnt < 1) {
|
||||
if (cnt < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
} else {
|
||||
fprintf(stderr, "only %d bytes received.\n", cnt);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
usb_close(handle);
|
||||
return 0;
|
||||
}
|
||||
41
poc/avr_usbload/crc.c
Normal file
41
poc/avr_usbload/crc.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crc.h"
|
||||
#include "uart.h"
|
||||
|
||||
extern FILE uart_stdout;
|
||||
|
||||
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
|
||||
{
|
||||
int i;
|
||||
crc = crc ^ ((uint16_t) data << 8);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (crc & 0x8000)
|
||||
crc = (crc << 1) ^ 0x1021;
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t do_crc(uint8_t * data, uint16_t size)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint16_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc_xmodem_update(crc, data[i]);
|
||||
// printf("%x : %x\n",crc,data[i]);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
|
||||
{
|
||||
uint16_t i;
|
||||
for (i = 0; i < size; i++)
|
||||
crc = crc_xmodem_update(crc, data[i]);
|
||||
return crc;
|
||||
}
|
||||
7
poc/avr_usbload/crc.h
Normal file
7
poc/avr_usbload/crc.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
uint16_t crc_xmodem_update (uint16_t crc, uint8_t data);
|
||||
uint16_t do_crc(uint8_t * data,uint16_t size);
|
||||
uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size);
|
||||
44
poc/avr_usbload/debug.c
Normal file
44
poc/avr_usbload/debug.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
extern FILE uart_stdout;
|
||||
|
||||
void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
|
||||
{
|
||||
uint16_t i,
|
||||
j;
|
||||
uint16_t sum = 0;
|
||||
uint8_t clear = 0;
|
||||
|
||||
for (i = 0; i < len; i += 16) {
|
||||
|
||||
sum = 0;
|
||||
for (j = 0; j < 16; j++) {
|
||||
sum += packet[i + j];
|
||||
}
|
||||
if (!sum) {
|
||||
clear = 1;
|
||||
continue;
|
||||
}
|
||||
if (clear) {
|
||||
printf("*\n");
|
||||
clear = 0;
|
||||
}
|
||||
printf("%08lx:", addr + i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
printf(" %02x", packet[i + j]);
|
||||
}
|
||||
printf(" |");
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (packet[i + j] >= 33 && packet[i + j] <= 126)
|
||||
printf("%c", packet[i + j]);
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
}
|
||||
5
poc/avr_usbload/debug.h
Normal file
5
poc/avr_usbload/debug.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void dump_packet(uint32_t addr,uint32_t len,uint8_t *packet);
|
||||
|
||||
28
poc/avr_usbload/fifo.c
Normal file
28
poc/avr_usbload/fifo.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "fifo.h"
|
||||
|
||||
void fifo_init(fifo_t * f, uint8_t * buffer, const uint8_t size)
|
||||
{
|
||||
f->count = 0;
|
||||
f->pread = f->pwrite = buffer;
|
||||
f->read2end = f->write2end = f->size = size;
|
||||
}
|
||||
|
||||
uint8_t fifo_put(fifo_t * f, const uint8_t data)
|
||||
{
|
||||
return _inline_fifo_put(f, data);
|
||||
}
|
||||
|
||||
uint8_t fifo_get_wait(fifo_t * f)
|
||||
{
|
||||
while (!f->count);
|
||||
|
||||
return _inline_fifo_get(f);
|
||||
}
|
||||
|
||||
int fifo_get_nowait(fifo_t * f)
|
||||
{
|
||||
if (!f->count)
|
||||
return -1;
|
||||
|
||||
return (int) _inline_fifo_get(f);
|
||||
}
|
||||
69
poc/avr_usbload/fifo.h
Normal file
69
poc/avr_usbload/fifo.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef _FIFO_H_
|
||||
#define _FIFO_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t volatile count; // # Zeichen im Puffer
|
||||
uint8_t size; // Puffer-Größe
|
||||
uint8_t *pread; // Lesezeiger
|
||||
uint8_t *pwrite; // Schreibzeiger
|
||||
uint8_t read2end, write2end; // # Zeichen bis zum Überlauf Lese-/Schreibzeiger
|
||||
} fifo_t;
|
||||
|
||||
extern void fifo_init(fifo_t *, uint8_t * buf, const uint8_t size);
|
||||
extern uint8_t fifo_put(fifo_t *, const uint8_t data);
|
||||
extern uint8_t fifo_get_wait(fifo_t *);
|
||||
extern int fifo_get_nowait(fifo_t *);
|
||||
|
||||
static inline uint8_t _inline_fifo_put(fifo_t * f, const uint8_t data)
|
||||
{
|
||||
if (f->count >= f->size)
|
||||
return 0;
|
||||
|
||||
uint8_t *pwrite = f->pwrite;
|
||||
|
||||
*(pwrite++) = data;
|
||||
|
||||
uint8_t write2end = f->write2end;
|
||||
|
||||
if (--write2end == 0) {
|
||||
write2end = f->size;
|
||||
pwrite -= write2end;
|
||||
}
|
||||
|
||||
f->write2end = write2end;
|
||||
f->pwrite = pwrite;
|
||||
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
f->count++;
|
||||
SREG = sreg;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline uint8_t _inline_fifo_get(fifo_t * f)
|
||||
{
|
||||
uint8_t *pread = f->pread;
|
||||
uint8_t data = *(pread++);
|
||||
uint8_t read2end = f->read2end;
|
||||
|
||||
if (--read2end == 0) {
|
||||
read2end = f->size;
|
||||
pread -= read2end;
|
||||
}
|
||||
|
||||
f->pread = pread;
|
||||
f->read2end = read2end;
|
||||
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
f->count--;
|
||||
SREG = sreg;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif /* _FIFO_H_ */
|
||||
213
poc/avr_usbload/main.c
Normal file
213
poc/avr_usbload/main.c
Normal file
@@ -0,0 +1,213 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h> /* for sei() */
|
||||
#include <util/delay.h> /* for _delay_ms() */
|
||||
#include <stdlib.h>
|
||||
#include <avr/pgmspace.h> /* required by usbdrv.h */
|
||||
|
||||
#include "usbdrv.h"
|
||||
#include "oddebug.h" /* This is also an example for using debug
|
||||
* macros */
|
||||
#include "requests.h" /* The custom request numbers we use */
|
||||
#include "uart.h"
|
||||
#include "sram.h"
|
||||
#include "debug.h"
|
||||
#include "crc.h"
|
||||
|
||||
|
||||
#define REQ_IDLE 0
|
||||
#define REQ_UPLOAD 1
|
||||
#define RES_CRC 2
|
||||
#define BUFFER_SIZE 256
|
||||
|
||||
extern FILE uart_stdout;
|
||||
|
||||
uint8_t read_buffer[BUFFER_SIZE];
|
||||
uint32_t req_addr = 0;
|
||||
uint32_t req_size;
|
||||
uint8_t req_bank;
|
||||
uint32_t req_bank_size;
|
||||
uint8_t req_state = REQ_IDLE;
|
||||
uint8_t rx_remaining = 0;
|
||||
uint8_t tx_remaining = 0;
|
||||
uint16_t sync_errors = 0;
|
||||
uint8_t tx_buffer[32];
|
||||
uint8_t data_buffer[4];
|
||||
uint32_t addr;
|
||||
|
||||
void crc_check_memory(uint32_t top_addr)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint32_t addr;
|
||||
req_bank = 0;
|
||||
for (addr = 0x000000; addr < top_addr; addr += BUFFER_SIZE) {
|
||||
sram_read_buffer(addr, read_buffer, BUFFER_SIZE);
|
||||
crc = do_crc_update(crc, read_buffer, BUFFER_SIZE);
|
||||
if (addr && addr % 32768 == 0) {
|
||||
printf("crc_check_memory: req_bank: 0x%x Addr: 0x%lx CRC: %x\n",
|
||||
req_bank, addr, crc);
|
||||
req_bank++;
|
||||
crc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void crc_check_memory_
|
||||
range(uint32_t start_addr, uint32_t size)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint32_t addr;
|
||||
req_bank = 0;
|
||||
for (addr = start_addr; addr < start_addr + size; addr += BUFFER_SIZE) {
|
||||
sram_read_buffer(addr, read_buffer, BUFFER_SIZE);
|
||||
crc = do_crc_update(crc, read_buffer, BUFFER_SIZE);
|
||||
}
|
||||
tx_buffer[0] = crc & 0xff;
|
||||
tx_buffer[1] = (crc >> 8) & 0xff;
|
||||
printf("crc_check_memory_range: Addr: 0x%lx CRC: %x\n", addr, crc);
|
||||
}
|
||||
|
||||
|
||||
usbMsgLen_t usbFunctionSetup(uchar data[8])
|
||||
{
|
||||
|
||||
usbRequest_t *rq = (void *) data;
|
||||
uint8_t ret_len = 0;
|
||||
if (rq->bRequest == USB_UPLOAD_INIT) {
|
||||
req_bank = 0;
|
||||
rx_remaining = 0;
|
||||
req_bank_size = 1 << rq->wValue.word;
|
||||
sync_errors = 0;
|
||||
printf("USB_UPLOAD_INIT: bank size %li\n", req_bank_size);
|
||||
} else if (rq->bRequest == USB_UPLOAD_ADDR) { /* echo -- used for
|
||||
* reliability tests */
|
||||
req_state = REQ_UPLOAD;
|
||||
req_addr = rq->wValue.word;
|
||||
req_addr = req_addr << 16;
|
||||
req_addr = req_addr | rq->wIndex.word;
|
||||
if (rx_remaining) {
|
||||
sync_errors++;
|
||||
printf
|
||||
("USB_UPLOAD_ADDR: Out of sync Addr=0x%lx remain=%i packet=%i sync_error=%i\n",
|
||||
req_addr, rx_remaining, rq->wLength.word, sync_errors);
|
||||
ret_len = 0;
|
||||
}
|
||||
rx_remaining = rq->wLength.word;
|
||||
ret_len = 0xff;
|
||||
if (req_addr && req_addr % req_bank_size == 0) {
|
||||
printf("USB_UPLOAD_ADDR: req_bank: 0x%x Addr: 0x%08lx \n",
|
||||
req_bank, req_addr);
|
||||
req_bank++;
|
||||
}
|
||||
ret_len = 0xff;
|
||||
} else if (rq->bRequest == USB_DOWNLOAD_INIT) {
|
||||
printf("USB_DOWNLOAD_INIT\n");
|
||||
} else if (rq->bRequest == USB_DOWNLOAD_ADDR) {
|
||||
printf("USB_DOWNLOAD_ADDR\n");
|
||||
} else if (rq->bRequest == USB_CRC) {
|
||||
req_addr = rq->wValue.word;
|
||||
req_addr = req_addr << 16;
|
||||
req_addr = req_addr | rq->wIndex.word;
|
||||
printf("USB_CRC: Addr 0x%lx \n", req_addr);
|
||||
cli();
|
||||
crc_check_memory(req_addr);
|
||||
sei();
|
||||
} else if (rq->bRequest == USB_CRC_ADDR) {
|
||||
req_addr = rq->wValue.word;
|
||||
req_addr = req_addr << 16;
|
||||
req_addr = req_addr | rq->wIndex.word;
|
||||
printf("USB_CRC_ADDR: Addr: 0x%lx Size: %i\n", req_addr,
|
||||
rq->wLength.word);
|
||||
req_size = rq->wLength.word;
|
||||
req_size = req_size << 2;
|
||||
tx_remaining = 2;
|
||||
printf("USB_CRC_ADDR: Addr: 0x%lx Size: %li\n", req_addr, req_size);
|
||||
cli();
|
||||
// crc_check_memory_range(req_addr,req_size);
|
||||
sei();
|
||||
ret_len = 2;
|
||||
}
|
||||
|
||||
usbMsgPtr = data_buffer;
|
||||
return ret_len; /* default for not implemented requests: return
|
||||
* no data back to host */
|
||||
}
|
||||
|
||||
|
||||
uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
|
||||
{
|
||||
if (len > rx_remaining) {
|
||||
printf("usbFunctionWrite more data than expected remain: %i len: %i\n",
|
||||
rx_remaining, len);
|
||||
len = rx_remaining;
|
||||
}
|
||||
if (req_state == REQ_UPLOAD) {
|
||||
|
||||
rx_remaining -= len;
|
||||
#if 1
|
||||
printf("usbFunctionWrite addr: 0x%08lx len: %i rx_remaining=%i\n",
|
||||
req_addr, len, rx_remaining);
|
||||
#endif
|
||||
cli();
|
||||
sram_copy(req_addr, data, len);
|
||||
sei();
|
||||
req_addr += len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
uint8_t usbFunctionRead(uint8_t * data, uint8_t len)
|
||||
{
|
||||
uint8_t i;
|
||||
if (len > tx_remaining)
|
||||
len = tx_remaining;
|
||||
tx_remaining -= len;
|
||||
#if 1
|
||||
printf("usbFunctionRead len=%i tx_remaining=%i \n", len, tx_remaining);
|
||||
#endif
|
||||
for (i = 0; i < len; i++) {
|
||||
*data = tx_buffer[len];
|
||||
data++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t i;
|
||||
wdt_enable(WDTO_1S);
|
||||
uart_init();
|
||||
stdout = &uart_stdout;
|
||||
sram_init();
|
||||
printf("SRAM Init\n");
|
||||
spi_init();
|
||||
printf("SPI Init\n");
|
||||
usbInit();
|
||||
printf("USB Init\n");
|
||||
usbDeviceDisconnect(); /* enforce re-enumeration, do this while
|
||||
* interrupts are disabled! */
|
||||
printf("USB disconnect\n");
|
||||
i = 10;
|
||||
while (--i) { /* fake USB disconnect for > 250 ms */
|
||||
wdt_reset();
|
||||
_delay_ms(1);
|
||||
}
|
||||
usbDeviceConnect();
|
||||
printf("USB connect\n");
|
||||
sei();
|
||||
printf("USB poll\n");
|
||||
for (;;) { /* main event loop */
|
||||
wdt_reset();
|
||||
usbPoll();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
26
poc/avr_usbload/requests.h
Normal file
26
poc/avr_usbload/requests.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Name: requests.h
|
||||
* Project: custom-class, a basic USB example
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-09
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: requests.h 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
/* This header is shared between the firmware and the host software. It
|
||||
* defines the USB request numbers (and optionally data types) used to
|
||||
* communicate between the host and the device.
|
||||
*/
|
||||
|
||||
#ifndef __REQUESTS_H_INCLUDED__
|
||||
#define __REQUESTS_H_INCLUDED__
|
||||
|
||||
#define USB_UPLOAD_INIT 0
|
||||
#define USB_UPLOAD_ADDR 1
|
||||
#define USB_DOWNLOAD_INIT 2
|
||||
#define USB_DOWNLOAD_ADDR 3
|
||||
#define USB_CRC 4
|
||||
#define USB_CRC_ADDR 5
|
||||
|
||||
#endif /* __REQUESTS_H_INCLUDED__ */
|
||||
172
poc/avr_usbload/sram.c
Normal file
172
poc/avr_usbload/sram.c
Normal file
@@ -0,0 +1,172 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "sram.h"
|
||||
#include "uart.h"
|
||||
#include "debug.h"
|
||||
|
||||
void spi_init(void)
|
||||
{
|
||||
/*
|
||||
* Set MOSI and SCK output, all others input
|
||||
*/
|
||||
SPI_DIR |= ((1 << S_MOSI) | (1 << S_SCK) | (1 << S_LATCH));
|
||||
SPI_DIR &= ~(1 << S_MISO);
|
||||
SPI_PORT |= (1 << S_MISO);
|
||||
/*
|
||||
* Enable SPI, Master
|
||||
*/
|
||||
SPCR = ((1 << SPE) | (1 << MSTR));
|
||||
}
|
||||
|
||||
void spi_master_transmit(unsigned char cData)
|
||||
{
|
||||
/*
|
||||
* Start transmission
|
||||
*/
|
||||
SPDR = cData;
|
||||
|
||||
/*
|
||||
* Wait for transmission complete
|
||||
*/
|
||||
while (!(SPSR & (1 << SPIF)));
|
||||
}
|
||||
|
||||
|
||||
void sram_set_addr(uint32_t addr)
|
||||
{
|
||||
spi_master_transmit((uint8_t) (addr >> 16));
|
||||
spi_master_transmit((uint8_t) (addr >> 8));
|
||||
spi_master_transmit((uint8_t) (addr >> 0));
|
||||
|
||||
LATCH_PORT |= (1 << S_LATCH);
|
||||
LATCH_PORT &= ~(1 << S_LATCH);
|
||||
}
|
||||
|
||||
uint8_t sram_read(uint32_t addr)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
RAM_DIR = 0x00;
|
||||
RAM_PORT = 0xff;
|
||||
|
||||
CTRL_PORT |= (1 << R_RD);
|
||||
CTRL_PORT |= (1 << R_WR);
|
||||
|
||||
spi_master_transmit((uint8_t) (addr >> 16));
|
||||
spi_master_transmit((uint8_t) (addr >> 8));
|
||||
spi_master_transmit((uint8_t) (addr >> 0));
|
||||
|
||||
LATCH_PORT |= (1 << S_LATCH);
|
||||
LATCH_PORT &= ~(1 << S_LATCH);
|
||||
CTRL_PORT &= ~(1 << R_RD);
|
||||
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
asm volatile ("nop");
|
||||
|
||||
byte = RAM_REG;
|
||||
CTRL_PORT |= (1 << R_RD);
|
||||
RAM_DIR = 0x00;
|
||||
RAM_PORT = 0x00;
|
||||
return byte;
|
||||
}
|
||||
|
||||
void sram_write(uint32_t addr, uint8_t data)
|
||||
{
|
||||
RAM_DIR = 0xff;
|
||||
|
||||
CTRL_PORT |= (1 << R_RD);
|
||||
CTRL_PORT |= (1 << R_WR);
|
||||
|
||||
spi_master_transmit((uint8_t) (addr >> 16));
|
||||
spi_master_transmit((uint8_t) (addr >> 8));
|
||||
spi_master_transmit((uint8_t) (addr >> 0));
|
||||
|
||||
LATCH_PORT |= (1 << S_LATCH);
|
||||
LATCH_PORT &= ~(1 << S_LATCH);
|
||||
|
||||
|
||||
CTRL_PORT &= ~(1 << R_WR);
|
||||
|
||||
RAM_PORT = data;
|
||||
CTRL_PORT |= (1 << R_WR);
|
||||
|
||||
RAM_DIR = 0x00;
|
||||
RAM_PORT = 0x00;
|
||||
}
|
||||
|
||||
void sram_init(void)
|
||||
{
|
||||
|
||||
RAM_DIR = 0x00;
|
||||
RAM_PORT = 0x00;
|
||||
|
||||
CTRL_DIR |= ((1 << R_WR) | (1 << R_RD));
|
||||
CTRL_PORT |= (1 << R_RD);
|
||||
CTRL_PORT |= (1 << R_WR);
|
||||
|
||||
LED_PORT |= (1 << D_LED0);
|
||||
}
|
||||
|
||||
void sram_snes_mode01(void)
|
||||
{
|
||||
CTRL_PORT |= (1 << R_WR);
|
||||
CTRL_PORT &= ~(1 << R_RD);
|
||||
}
|
||||
|
||||
void sram_snes_mode02(void)
|
||||
{
|
||||
CTRL_DIR |= (1 << R_WR);
|
||||
CTRL_PORT |= (1 << R_WR);
|
||||
// CTRL_PORT &= ~(1<<R_RD);
|
||||
CTRL_DIR &= ~(1 << R_RD);
|
||||
CTRL_PORT &= ~(1 << R_RD);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void sram_clear(uint32_t addr, uint32_t len)
|
||||
{
|
||||
|
||||
uint32_t i;
|
||||
for (i = addr; i < (addr + len); i++) {
|
||||
if (0 == i % 0xfff)
|
||||
printf("sram_clear %lx\n\r", i);
|
||||
sram_write(i, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
void sram_copy(uint32_t addr, uint8_t * src, uint32_t len)
|
||||
{
|
||||
|
||||
uint32_t i;
|
||||
uint8_t *ptr = src;
|
||||
for (i = addr; i < (addr + len); i++)
|
||||
sram_write(i, *ptr++);
|
||||
}
|
||||
|
||||
void sram_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
|
||||
{
|
||||
|
||||
uint32_t i;
|
||||
uint8_t *ptr = dst;
|
||||
for (i = addr; i < (addr + len); i++) {
|
||||
*ptr = sram_read(i);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
uint8_t sram_check(uint8_t * buffer, uint32_t len)
|
||||
{
|
||||
uint16_t cnt;
|
||||
for (cnt = 0; cnt < len; cnt++)
|
||||
if (buffer[cnt])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
51
poc/avr_usbload/sram.h
Normal file
51
poc/avr_usbload/sram.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
|
||||
//SREG defines
|
||||
#define S_MOSI PB5
|
||||
#define S_MISO PB6
|
||||
#define S_SCK PB7
|
||||
#define S_LATCH PB4
|
||||
|
||||
//DEBUG defines
|
||||
#define D_LED0 PD6
|
||||
|
||||
//SRAM defines
|
||||
#define R_WR PB1
|
||||
#define R_RD PB0
|
||||
|
||||
#define RAM_PORT PORTA
|
||||
#define RAM_DIR DDRA
|
||||
#define RAM_REG PINA
|
||||
|
||||
#define CTRL_PORT PORTB
|
||||
#define CTRL_DIR DDRB
|
||||
#define LATCH_PORT PORTB
|
||||
#define LATCH_DIR DDRB
|
||||
|
||||
#define SPI_PORT PORTB
|
||||
#define SPI_DIR DDRB
|
||||
|
||||
#define LED_PORT PORTD
|
||||
#define LED_DIR DDRD
|
||||
|
||||
#define ROMSIZE 4
|
||||
#define BLOCKS (ROMSIZE << 8)
|
||||
#define MEMSIZE 0x80000
|
||||
|
||||
|
||||
|
||||
void spi_init(void);
|
||||
void spi_master_transmit(unsigned char cData);
|
||||
void sram_set_addr(uint32_t addr);
|
||||
uint8_t sram_read(uint32_t addr);
|
||||
void sram_write(uint32_t addr, uint8_t data);
|
||||
void sram_init(void);
|
||||
void sram_snes_mode01(void);
|
||||
void sram_snes_mode02(void);
|
||||
void sram_clear(uint32_t addr, uint32_t len);
|
||||
void sram_copy(uint32_t addr,uint8_t *src, uint32_t len);
|
||||
void sram_read_buffer(uint32_t addr,uint8_t *dst, uint32_t len);
|
||||
uint8_t sram_check(uint8_t *buffer, uint32_t len);
|
||||
77
poc/avr_usbload/uart.c
Normal file
77
poc/avr_usbload/uart.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <stdio.h>
|
||||
#include "uart.h"
|
||||
#include "fifo.h"
|
||||
|
||||
volatile struct {
|
||||
uint8_t tmr_int:1;
|
||||
uint8_t adc_int:1;
|
||||
uint8_t rx_int:1;
|
||||
} intflags;
|
||||
|
||||
/*
|
||||
* * Last character read from the UART.
|
||||
*
|
||||
*/
|
||||
volatile char rxbuff;
|
||||
|
||||
|
||||
FILE uart_stdout = FDEV_SETUP_STREAM(uart_stream, NULL, _FDEV_SETUP_WRITE);
|
||||
|
||||
void uart_init(void)
|
||||
{
|
||||
UCSRA = _BV(U2X); /* improves baud rate error @ F_CPU = 1 MHz */
|
||||
UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE); /* tx/rx enable, rx complete
|
||||
* intr */
|
||||
UBRRL = (F_CPU / (8 * 115200UL)) - 1; /* 9600 Bd */
|
||||
|
||||
}
|
||||
|
||||
|
||||
ISR(USART_RXC_vect)
|
||||
{
|
||||
uint8_t c;
|
||||
c = UDR;
|
||||
if (bit_is_clear(UCSRA, FE)) {
|
||||
rxbuff = c;
|
||||
intflags.rx_int = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uart_putc(uint8_t c)
|
||||
{
|
||||
loop_until_bit_is_set(UCSRA, UDRE);
|
||||
UDR = c;
|
||||
}
|
||||
|
||||
|
||||
void uart_puts(const char *s)
|
||||
{
|
||||
do {
|
||||
uart_putc(*s);
|
||||
}
|
||||
while (*s++);
|
||||
}
|
||||
|
||||
void uart_puts_P(PGM_P s)
|
||||
{
|
||||
while (1) {
|
||||
unsigned char c = pgm_read_byte(s);
|
||||
s++;
|
||||
if ('\0' == c)
|
||||
break;
|
||||
uart_putc(c);
|
||||
}
|
||||
}
|
||||
|
||||
static int uart_stream(char c, FILE * stream)
|
||||
{
|
||||
if (c == '\n')
|
||||
uart_putc('\r');
|
||||
loop_until_bit_is_set(UCSRA, UDRE);
|
||||
UDR = c;
|
||||
return 0;
|
||||
}
|
||||
18
poc/avr_usbload/uart.h
Normal file
18
poc/avr_usbload/uart.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#define CR "\r\n"
|
||||
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void uart_init(void);
|
||||
void uart_putc(const uint8_t);
|
||||
void uart_puts(const char *s);
|
||||
void uart_puts_P(PGM_P s);
|
||||
static int uart_stream(char c, FILE *stream);
|
||||
|
||||
|
||||
#endif /* _UART_H_ */
|
||||
351
poc/avr_usbload/usbconfig.h
Normal file
351
poc/avr_usbload/usbconfig.h
Normal file
@@ -0,0 +1,351 @@
|
||||
/* Name: usbconfig.h
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2005-04-01
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __usbconfig_h_included__
|
||||
#define __usbconfig_h_included__
|
||||
|
||||
/*
|
||||
General Description:
|
||||
This file is an example configuration (with inline documentation) for the USB
|
||||
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
|
||||
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
|
||||
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
|
||||
other hardware interrupt, as long as it is the highest level interrupt, see
|
||||
section at the end of this file).
|
||||
*/
|
||||
|
||||
/* ---------------------------- Hardware Config ---------------------------- */
|
||||
|
||||
#define USB_CFG_IOPORTNAME D
|
||||
/* This is the port where the USB bus is connected. When you configure it to
|
||||
* "B", the registers PORTB, PINB and DDRB will be used.
|
||||
*/
|
||||
#define USB_CFG_DMINUS_BIT 4
|
||||
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
|
||||
* This may be any bit in the port.
|
||||
*/
|
||||
#define USB_CFG_DPLUS_BIT 2
|
||||
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
|
||||
* This may be any bit in the port. Please note that D+ must also be connected
|
||||
* to interrupt pin INT0! [You can also use other interrupts, see section
|
||||
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
|
||||
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
|
||||
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
|
||||
* markers every millisecond.]
|
||||
*/
|
||||
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
|
||||
* 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no
|
||||
* crystal, they tolerate +/- 1% deviation from the nominal frequency. All
|
||||
* other rates require a precision of 2000 ppm and thus a crystal!
|
||||
* Default if not specified: 12 MHz
|
||||
*/
|
||||
#define USB_CFG_CHECK_CRC 0
|
||||
/* Define this to 1 if you want that the driver checks integrity of incoming
|
||||
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
|
||||
* currently only available for 18 MHz crystal clock. You must choose
|
||||
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
|
||||
*/
|
||||
|
||||
/* ----------------------- Optional Hardware Config ------------------------ */
|
||||
|
||||
#define USB_CFG_PULLUP_IOPORTNAME D
|
||||
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
|
||||
* V+, you can connect and disconnect the device from firmware by calling
|
||||
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
|
||||
* This constant defines the port on which the pullup resistor is connected.
|
||||
*/
|
||||
#define USB_CFG_PULLUP_BIT 6
|
||||
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
|
||||
* above) where the 1.5k pullup resistor is connected. See description
|
||||
* above for details.
|
||||
*/
|
||||
|
||||
/* --------------------------- Functional Range ---------------------------- */
|
||||
|
||||
#define USB_CFG_HAVE_INTRIN_ENDPOINT 0
|
||||
/* Define this to 1 if you want to compile a version with two endpoints: The
|
||||
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
|
||||
* number).
|
||||
*/
|
||||
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
|
||||
/* Define this to 1 if you want to compile a version with three endpoints: The
|
||||
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
|
||||
* configured below) and a catch-all default interrupt-in endpoint as above.
|
||||
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
|
||||
*/
|
||||
#define USB_CFG_EP3_NUMBER 3
|
||||
/* If the so-called endpoint 3 is used, it can now be configured to any other
|
||||
* endpoint number (except 0) with this macro. Default if undefined is 3.
|
||||
*/
|
||||
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
|
||||
/* The above macro defines the startup condition for data toggling on the
|
||||
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
|
||||
* Since the token is toggled BEFORE sending any data, the first packet is
|
||||
* sent with the oposite value of this configuration!
|
||||
*/
|
||||
#define USB_CFG_IMPLEMENT_HALT 0
|
||||
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
|
||||
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
|
||||
* it is required by the standard. We have made it a config option because it
|
||||
* bloats the code considerably.
|
||||
*/
|
||||
#define USB_CFG_SUPPRESS_INTR_CODE 1
|
||||
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
|
||||
* want to send any data over them. If this macro is defined to 1, functions
|
||||
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
|
||||
* you need the interrupt-in endpoints in order to comply to an interface
|
||||
* (e.g. HID), but never want to send any data. This option saves a couple
|
||||
* of bytes in flash memory and the transmit buffers in RAM.
|
||||
*/
|
||||
#define USB_CFG_INTR_POLL_INTERVAL 10
|
||||
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
|
||||
* interval. The value is in milliseconds and must not be less than 10 ms for
|
||||
* low speed devices.
|
||||
*/
|
||||
#define USB_CFG_IS_SELF_POWERED 0
|
||||
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
|
||||
* device is powered from the USB bus.
|
||||
*/
|
||||
#define USB_CFG_MAX_BUS_POWER 40
|
||||
/* Set this variable to the maximum USB bus power consumption of your device.
|
||||
* The value is in milliamperes. [It will be divided by two since USB
|
||||
* communicates power requirements in units of 2 mA.]
|
||||
*/
|
||||
#define USB_CFG_IMPLEMENT_FN_WRITE 1
|
||||
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
|
||||
* transfers. Set it to 0 if you don't need it and want to save a couple of
|
||||
* bytes.
|
||||
*/
|
||||
#define USB_CFG_IMPLEMENT_FN_READ 0
|
||||
/* Set this to 1 if you need to send control replies which are generated
|
||||
* "on the fly" when usbFunctionRead() is called. If you only want to send
|
||||
* data from a static buffer, set it to 0 and return the data from
|
||||
* usbFunctionSetup(). This saves a couple of bytes.
|
||||
*/
|
||||
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
|
||||
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
|
||||
* You must implement the function usbFunctionWriteOut() which receives all
|
||||
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
|
||||
* can be found in 'usbRxToken'.
|
||||
*/
|
||||
#define USB_CFG_HAVE_FLOWCONTROL 0
|
||||
/* Define this to 1 if you want flowcontrol over USB data. See the definition
|
||||
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
|
||||
* usbdrv.h.
|
||||
*/
|
||||
#define USB_CFG_LONG_TRANSFERS 0
|
||||
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
|
||||
* in a single control-in or control-out transfer. Note that the capability
|
||||
* for long transfers increases the driver size.
|
||||
*/
|
||||
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
|
||||
/* This macro is a hook if you want to do unconventional things. If it is
|
||||
* defined, it's inserted at the beginning of received message processing.
|
||||
* If you eat the received message and don't want default processing to
|
||||
* proceed, do a return after doing your things. One possible application
|
||||
* (besides debugging) is to flash a status LED on each packet.
|
||||
*/
|
||||
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
|
||||
/* This macro is a hook if you need to know when an USB RESET occurs. It has
|
||||
* one parameter which distinguishes between the start of RESET state and its
|
||||
* end.
|
||||
*/
|
||||
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
|
||||
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
|
||||
* received.
|
||||
*/
|
||||
#define USB_COUNT_SOF 0
|
||||
/* define this macro to 1 if you need the global variable "usbSofCount" which
|
||||
* counts SOF packets. This feature requires that the hardware interrupt is
|
||||
* connected to D- instead of D+.
|
||||
*/
|
||||
/* #ifdef __ASSEMBLER__
|
||||
* macro myAssemblerMacro
|
||||
* in YL, TCNT0
|
||||
* sts timer0Snapshot, YL
|
||||
* endm
|
||||
* #endif
|
||||
* #define USB_SOF_HOOK myAssemblerMacro
|
||||
* This macro (if defined) is executed in the assembler module when a
|
||||
* Start Of Frame condition is detected. It is recommended to define it to
|
||||
* the name of an assembler macro which is defined here as well so that more
|
||||
* than one assembler instruction can be used. The macro may use the register
|
||||
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
|
||||
* immediately after an SOF pulse may be lost and must be retried by the host.
|
||||
* What can you do with this hook? Since the SOF signal occurs exactly every
|
||||
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
|
||||
* designs running on the internal RC oscillator.
|
||||
* Please note that Start Of Frame detection works only if D- is wired to the
|
||||
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
|
||||
*/
|
||||
#define USB_CFG_CHECK_DATA_TOGGLING 0
|
||||
/* define this macro to 1 if you want to filter out duplicate data packets
|
||||
* sent by the host. Duplicates occur only as a consequence of communication
|
||||
* errors, when the host does not receive an ACK. Please note that you need to
|
||||
* implement the filtering yourself in usbFunctionWriteOut() and
|
||||
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
|
||||
* for each control- and out-endpoint to check for duplicate packets.
|
||||
*/
|
||||
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
|
||||
/* define this macro to 1 if you want the function usbMeasureFrameLength()
|
||||
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
|
||||
*/
|
||||
|
||||
/* -------------------------- Device Description --------------------------- */
|
||||
|
||||
#define USB_CFG_VENDOR_ID 0xc0, 0x16
|
||||
/* USB vendor ID for the device, low byte first. If you have registered your
|
||||
* own Vendor ID, define it here. Otherwise you use one of obdev's free shared
|
||||
* VID/PID pairs. Be sure to read USBID-License.txt for rules!
|
||||
*/
|
||||
#define USB_CFG_DEVICE_ID 0xdc, 0x05
|
||||
/* This is the ID of the product, low byte first. It is interpreted in the
|
||||
* scope of the vendor ID. If you have registered your own VID with usb.org
|
||||
* or if you have licensed a PID from somebody else, define it here. Otherwise
|
||||
* you use obdev's free shared VID/PID pair. Be sure to read the rules in
|
||||
* USBID-License.txt!
|
||||
*/
|
||||
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
|
||||
/* Version number of the device: Minor number first, then major number.
|
||||
*/
|
||||
#define USB_CFG_VENDOR_NAME 'o', 'p', 't', 'i', 'x', 'x', '.', 'o', 'r', 'g'
|
||||
#define USB_CFG_VENDOR_NAME_LEN 10
|
||||
/* These two values define the vendor name returned by the USB device. The name
|
||||
* must be given as a list of characters under single quotes. The characters
|
||||
* are interpreted as Unicode (UTF-16) entities.
|
||||
* If you don't want a vendor name string, undefine these macros.
|
||||
* ALWAYS define a vendor name containing your Internet domain name if you use
|
||||
* obdev's free shared VID/PID pair. See the file USBID-License.txt for
|
||||
* details.
|
||||
*/
|
||||
#define USB_CFG_DEVICE_NAME 'S', 'N', 'E', 'S', 'R', 'A', 'M'
|
||||
#define USB_CFG_DEVICE_NAME_LEN 7
|
||||
/* Same as above for the device name. If you don't want a device name, undefine
|
||||
* the macros. See the file USBID-License.txt before you assign a name if you
|
||||
* use a shared VID/PID.
|
||||
*/
|
||||
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
|
||||
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
|
||||
/* Same as above for the serial number. If you don't want a serial number,
|
||||
* undefine the macros.
|
||||
* It may be useful to provide the serial number through other means than at
|
||||
* compile time. See the section about descriptor properties below for how
|
||||
* to fine tune control over USB descriptors such as the string descriptor
|
||||
* for the serial number.
|
||||
*/
|
||||
#define USB_CFG_DEVICE_CLASS 0xff /* set to 0 if deferred to interface */
|
||||
#define USB_CFG_DEVICE_SUBCLASS 0
|
||||
/* See USB specification if you want to conform to an existing device class.
|
||||
* Class 0xff is "vendor specific".
|
||||
*/
|
||||
#define USB_CFG_INTERFACE_CLASS 0 /* define class here if not at device level */
|
||||
#define USB_CFG_INTERFACE_SUBCLASS 0
|
||||
#define USB_CFG_INTERFACE_PROTOCOL 0
|
||||
/* See USB specification if you want to conform to an existing device class or
|
||||
* protocol. The following classes must be set at interface level:
|
||||
* HID class is 3, no subclass and protocol required (but may be useful!)
|
||||
* CDC class is 2, use subclass 2 and protocol 1 for ACM
|
||||
*/
|
||||
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0
|
||||
|
||||
/* Define this to the length of the HID report descriptor, if you implement
|
||||
* an HID device. Otherwise don't define it or define it to 0.
|
||||
* If you use this define, you must add a PROGMEM character array named
|
||||
* "usbHidReportDescriptor" to your code which contains the report descriptor.
|
||||
* Don't forget to keep the array and this define in sync!
|
||||
*/
|
||||
|
||||
/* #define USB_PUBLIC static */
|
||||
/* Use the define above if you #include usbdrv.c instead of linking against it.
|
||||
* This technique saves a couple of bytes in flash memory.
|
||||
*/
|
||||
|
||||
/* ------------------- Fine Control over USB Descriptors ------------------- */
|
||||
/* If you don't want to use the driver's default USB descriptors, you can
|
||||
* provide our own. These can be provided as (1) fixed length static data in
|
||||
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
|
||||
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
|
||||
* information about this function.
|
||||
* Descriptor handling is configured through the descriptor's properties. If
|
||||
* no properties are defined or if they are 0, the default descriptor is used.
|
||||
* Possible properties are:
|
||||
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
|
||||
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
|
||||
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
|
||||
* you want RAM pointers.
|
||||
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
|
||||
* in static memory is in RAM, not in flash memory.
|
||||
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
|
||||
* the driver must know the descriptor's length. The descriptor itself is
|
||||
* found at the address of a well known identifier (see below).
|
||||
* List of static descriptor names (must be declared PROGMEM if in flash):
|
||||
* char usbDescriptorDevice[];
|
||||
* char usbDescriptorConfiguration[];
|
||||
* char usbDescriptorHidReport[];
|
||||
* char usbDescriptorString0[];
|
||||
* int usbDescriptorStringVendor[];
|
||||
* int usbDescriptorStringDevice[];
|
||||
* int usbDescriptorStringSerialNumber[];
|
||||
* Other descriptors can't be provided statically, they must be provided
|
||||
* dynamically at runtime.
|
||||
*
|
||||
* Descriptor properties are or-ed or added together, e.g.:
|
||||
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
|
||||
*
|
||||
* The following descriptors are defined:
|
||||
* USB_CFG_DESCR_PROPS_DEVICE
|
||||
* USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||
* USB_CFG_DESCR_PROPS_STRINGS
|
||||
* USB_CFG_DESCR_PROPS_STRING_0
|
||||
* USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||
* USB_CFG_DESCR_PROPS_HID
|
||||
* USB_CFG_DESCR_PROPS_HID_REPORT
|
||||
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
|
||||
*
|
||||
* Note about string descriptors: String descriptors are not just strings, they
|
||||
* are Unicode strings prefixed with a 2 byte header. Example:
|
||||
* int serialNumberDescriptor[] = {
|
||||
* USB_STRING_DESCRIPTOR_HEADER(6),
|
||||
* 'S', 'e', 'r', 'i', 'a', 'l'
|
||||
* };
|
||||
*/
|
||||
|
||||
#define USB_CFG_DESCR_PROPS_DEVICE 0
|
||||
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
|
||||
#define USB_CFG_DESCR_PROPS_STRINGS 0
|
||||
#define USB_CFG_DESCR_PROPS_STRING_0 0
|
||||
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
|
||||
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
|
||||
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
|
||||
#define USB_CFG_DESCR_PROPS_HID 0
|
||||
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
|
||||
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
|
||||
|
||||
/* ----------------------- Optional MCU Description ------------------------ */
|
||||
|
||||
/* The following configurations have working defaults in usbdrv.h. You
|
||||
* usually don't need to set them explicitly. Only if you want to run
|
||||
* the driver on a device which is not yet supported or with a compiler
|
||||
* which is not fully supported (such as IAR C) or if you use a differnt
|
||||
* interrupt than INT0, you may have to define some of these.
|
||||
*/
|
||||
/* #define USB_INTR_CFG MCUCR */
|
||||
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
|
||||
/* #define USB_INTR_CFG_CLR 0 */
|
||||
/* #define USB_INTR_ENABLE GIMSK */
|
||||
/* #define USB_INTR_ENABLE_BIT INT0 */
|
||||
/* #define USB_INTR_PENDING GIFR */
|
||||
/* #define USB_INTR_PENDING_BIT INTF0 */
|
||||
/* #define USB_INTR_VECTOR SIG_INTERRUPT0 */
|
||||
|
||||
#endif /* __usbconfig_h_included__ */
|
||||
@@ -268,3 +268,10 @@ Scroll down to the bottom to see the most recent changes.
|
||||
- Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser.
|
||||
|
||||
* Release 2009-03-23
|
||||
|
||||
- Hid-mouse example used settings from hid-data example, fixed that.
|
||||
- Renamed project to V-USB due to a trademark issue with Atmel(r).
|
||||
- Changed CommercialLicense.txt and USBID-License.txt to make the
|
||||
background of USB ID registration clearer.
|
||||
|
||||
* Release 2009-04-15
|
||||
@@ -1,5 +1,5 @@
|
||||
AVR-USB Driver Software License Agreement
|
||||
Version 2008-10-07
|
||||
V-USB Driver Software License Agreement
|
||||
Version 2009-04-14
|
||||
|
||||
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
|
||||
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
|
||||
@@ -13,8 +13,8 @@ Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA.
|
||||
|
||||
1.2 "You" shall mean the Licensee.
|
||||
|
||||
1.3 "AVR-USB" shall mean all files included in the package distributed under
|
||||
the name "avrusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/avrusb/)
|
||||
1.3 "V-USB" shall mean all files included in the package distributed under
|
||||
the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/)
|
||||
unless otherwise noted. This includes the firmware-only USB device
|
||||
implementation for Atmel AVR microcontrollers, some simple device examples
|
||||
and host side software examples and libraries.
|
||||
@@ -23,21 +23,22 @@ and host side software examples and libraries.
|
||||
2 LICENSE GRANTS
|
||||
|
||||
2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source
|
||||
code of AVR-USB.
|
||||
code of V-USB.
|
||||
|
||||
2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the
|
||||
non-exclusive right to use, copy and distribute AVR-USB with your hardware
|
||||
non-exclusive right to use, copy and distribute V-USB with your hardware
|
||||
product(s), restricted by the limitations in section 3 below.
|
||||
|
||||
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
|
||||
the source code and your copy of AVR-USB according to your needs.
|
||||
the source code and your copy of V-USB according to your needs.
|
||||
|
||||
2.4 USB IDs. OBJECTIVE DEVELOPMENT grants you the exclusive rights to use
|
||||
USB Product ID(s) sent to you in e-mail after receiving your payment in
|
||||
conjunction with USB Vendor ID 5824. OBJECTIVE DEVELOPMENT has acquired an
|
||||
exclusive license for this pair of USB identifiers from Wouter van Ooijen
|
||||
(www.voti.nl), who has licensed the VID from the USB Implementers Forum,
|
||||
Inc. (www.usb.org).
|
||||
2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB Product
|
||||
ID(s), sent to you in e-mail. These Product IDs are reserved exclusively for
|
||||
you. They have been obtained from Wouter van Ooijen (www.voti.nl), who has
|
||||
reserved the Vendor ID 5824 (decimal) at the USB Implementers Forum, Inc.
|
||||
(www.usb.org). This mechanism ensures that there are no Product ID conflicts,
|
||||
but you cannot become USB certified (enter into the USB-IF Trademark License
|
||||
Agreement) as you would need your own Vendor ID for that.
|
||||
|
||||
|
||||
3 LICENSE RESTRICTIONS
|
||||
@@ -46,21 +47,21 @@ Inc. (www.usb.org).
|
||||
applicable. Which one is determined by the amount you pay to OBJECTIVE
|
||||
DEVELOPMENT, see section 4 ("Payment") below.
|
||||
|
||||
Hobby License: You may use AVR-USB according to section 2 above in no more
|
||||
Hobby License: You may use V-USB according to section 2 above in no more
|
||||
than 5 hardware units. These units must not be sold for profit.
|
||||
|
||||
Entry Level License: You may use AVR-USB according to section 2 above in no
|
||||
Entry Level License: You may use V-USB according to section 2 above in no
|
||||
more than 150 hardware units.
|
||||
|
||||
Professional License: You may use AVR-USB according to section 2 above in
|
||||
Professional License: You may use V-USB according to section 2 above in
|
||||
any number of hardware units, except for large scale production ("unlimited
|
||||
fair use"). Quantities below 10,000 units are not considered large scale
|
||||
production. If your reach quantities which are obviously large scale
|
||||
production, you must pay a license fee of 0.10 EUR per unit for all units
|
||||
above 10,000.
|
||||
|
||||
3.2 Rental. You may not rent, lease, or lend AVR-USB or otherwise encumber
|
||||
any copy of AVR-USB, or any of the rights granted herein.
|
||||
3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber
|
||||
any copy of V-USB, or any of the rights granted herein.
|
||||
|
||||
3.3 Transfer. You may not transfer your rights under this Agreement to
|
||||
another party without OBJECTIVE DEVELOPMENT's prior written consent. If
|
||||
@@ -78,7 +79,7 @@ non-exclusive.
|
||||
by third parties. In particular, you are not allowed to use the USB logo or
|
||||
other trademarks owned by the USB Implementers Forum, Inc. without their
|
||||
consent. Since such consent depends on USB certification, it should be
|
||||
noted that AVR-USB will not pass certification because it does not
|
||||
noted that V-USB will not pass certification because it does not
|
||||
implement checksum verification and the microcontroller ports do not meet
|
||||
the electrical specifications.
|
||||
|
||||
@@ -88,15 +89,15 @@ the electrical specifications.
|
||||
The payment amount depends on the variation of this agreement (according to
|
||||
section 3.1) into which you want to enter. Concrete prices are listed on
|
||||
OBJECTIVE DEVELOPMENT's web site, usually at
|
||||
http://www.obdev.at/avrusb/license.html. You agree to pay the amount listed
|
||||
http://www.obdev.at/vusb/license.html. You agree to pay the amount listed
|
||||
there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor
|
||||
or reseller.
|
||||
|
||||
|
||||
5 COPYRIGHT AND OWNERSHIP
|
||||
|
||||
AVR-USB is protected by copyright laws and international copyright
|
||||
treaties, as well as other intellectual property laws and treaties. AVR-USB
|
||||
V-USB is protected by copyright laws and international copyright
|
||||
treaties, as well as other intellectual property laws and treaties. V-USB
|
||||
is licensed, not sold.
|
||||
|
||||
|
||||
@@ -112,12 +113,12 @@ and limitation of liability shall survive termination of this agreement.
|
||||
|
||||
7 DISCLAIMER OF WARRANTY AND LIABILITY
|
||||
|
||||
LIMITED WARRANTY. AVR-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE
|
||||
DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
|
||||
NON-INFRINGEMENT, WITH REGARD TO AVR-USB, AND THE PROVISION OF OR FAILURE
|
||||
NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE
|
||||
TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
|
||||
RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO
|
||||
STATE/JURISDICTION.
|
||||
@@ -127,11 +128,11 @@ IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY
|
||||
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
|
||||
(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
|
||||
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY
|
||||
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE AVR-USB OR THE
|
||||
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE
|
||||
PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE
|
||||
DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY
|
||||
CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS
|
||||
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR AVR-USB.
|
||||
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB.
|
||||
|
||||
|
||||
8 MISCELLANEOUS TERMS
|
||||
@@ -1,18 +1,18 @@
|
||||
OBJECTIVE DEVELOPMENT GmbH's AVR-USB driver software is distributed under the
|
||||
OBJECTIVE DEVELOPMENT GmbH's V-USB driver software is distributed under the
|
||||
terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is
|
||||
your choice whether you apply the terms of version 2 or version 3. The full
|
||||
text of GPLv2 is included below. In addition to the requirements in the GPL,
|
||||
we STRONGLY ENCOURAGE you to do the following:
|
||||
|
||||
(1) Publish your entire project on a web site and drop us a note with the URL.
|
||||
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
|
||||
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
|
||||
|
||||
(2) Adhere to minimum publication standards. Please include AT LEAST:
|
||||
- a circuit diagram in PDF, PNG or GIF format
|
||||
- full source code for the host software
|
||||
- a Readme.txt file in ASCII format which describes the purpose of the
|
||||
project and what can be found in which directories and which files
|
||||
- a reference to http://www.obdev.at/avrusb/
|
||||
- a reference to http://www.obdev.at/vusb/
|
||||
|
||||
(3) If you improve the driver firmware itself, please give us a free license
|
||||
to your modifications for our commercial license offerings.
|
||||
@@ -1,6 +1,6 @@
|
||||
This is the Readme file to Objective Development's firmware-only USB driver
|
||||
for Atmel AVR microcontrollers. For more information please visit
|
||||
http://www.obdev.at/avrusb/
|
||||
http://www.obdev.at/vusb/
|
||||
|
||||
This directory contains the USB firmware only. Copy it as-is to your own
|
||||
project and add all .c and .S files to your project (these files are marked
|
||||
@@ -53,7 +53,7 @@ actual clock rate must be configured in usbdrv.h unless you use the default
|
||||
12 MHz.
|
||||
|
||||
12 MHz Clock
|
||||
This is the traditional clock rate of AVR-USB because it's the lowest clock
|
||||
This is the traditional clock rate of V-USB because it's the lowest clock
|
||||
rate where the timing constraints of the USB spec can be met.
|
||||
|
||||
15 MHz Clock
|
||||
@@ -78,7 +78,7 @@ oscillator can reach 16.5 MHz with the RC oscillator. This includes the very
|
||||
popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost
|
||||
all AVRs can reach 12.8 MHz, although this is outside the specified range.
|
||||
|
||||
See the EasyLogger example at http://www.obdev.at/avrusb/easylogger.html for
|
||||
See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for
|
||||
code which calibrates the RC oscillator based on the USB frame clock.
|
||||
|
||||
18 MHz Clock
|
||||
@@ -108,14 +108,14 @@ and hobbyists, we provide some VID/PID pairs for free. See the file
|
||||
USBID-License.txt for details.
|
||||
|
||||
Objective Development also has some license offerings which include product
|
||||
IDs. See http://www.obdev.at/avrusb/ for details.
|
||||
IDs. See http://www.obdev.at/vusb/ for details.
|
||||
|
||||
|
||||
DEVELOPMENT SYSTEM
|
||||
==================
|
||||
This driver has been developed and optimized for the GNU compiler version 3
|
||||
(gcc 3). It does work well with gcc 4, but with bigger code size. We recommend
|
||||
that you use the GNU compiler suite because it is freely available. AVR-USB
|
||||
that you use the GNU compiler suite because it is freely available. V-USB
|
||||
has also been ported to the IAR compiler and assembler. It has been tested
|
||||
with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the "small" and "tiny"
|
||||
memory model. Not every release is tested with IAR CC and the driver may
|
||||
@@ -123,8 +123,8 @@ therefore fail to compile with IAR. Please note that gcc is more efficient for
|
||||
usbdrv.c because this module has been deliberately optimized for gcc.
|
||||
|
||||
|
||||
USING AVR-USB FOR FREE
|
||||
======================
|
||||
USING V-USB FOR FREE
|
||||
====================
|
||||
The AVR firmware driver is published under the GNU General Public License
|
||||
Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is
|
||||
your choice whether you apply the terms of version 2 or version 3.
|
||||
@@ -133,26 +133,26 @@ If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the
|
||||
following things IN ADDITION to the obligations from the GPL:
|
||||
|
||||
(1) Publish your entire project on a web site and drop us a note with the URL.
|
||||
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
|
||||
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
|
||||
If you don't have a web site, you can publish the project in obdev's
|
||||
documentation wiki at
|
||||
http://www.obdev.at/goto.php?t=avrusb-wiki&p=hosted-projects.
|
||||
http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects.
|
||||
|
||||
(2) Adhere to minimum publication standards. Please include AT LEAST:
|
||||
- a circuit diagram in PDF, PNG or GIF format
|
||||
- full source code for the host software
|
||||
- a Readme.txt file in ASCII format which describes the purpose of the
|
||||
project and what can be found in which directories and which files
|
||||
- a reference to http://www.obdev.at/avrusb/
|
||||
- a reference to http://www.obdev.at/vusb/
|
||||
|
||||
(3) If you improve the driver firmware itself, please give us a free license
|
||||
to your modifications for our commercial license offerings.
|
||||
|
||||
|
||||
COMMERCIAL LICENSES FOR AVR-USB
|
||||
===============================
|
||||
COMMERCIAL LICENSES FOR V-USB
|
||||
=============================
|
||||
If you don't want to publish your source code under the terms of the GPL,
|
||||
you can simply pay money for AVR-USB. As an additional benefit you get
|
||||
USB PIDs for free, licensed exclusively to you. See the file
|
||||
you can simply pay money for V-USB. As an additional benefit you get
|
||||
USB PIDs for free, reserved exclusively to you. See the file
|
||||
"CommercialLicense.txt" for details.
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
Royalty-Free Non-Exclusive License USB Product-ID
|
||||
Royalty-Free Non-Exclusive Use of USB Product-IDs
|
||||
=================================================
|
||||
|
||||
Version 2008-04-07
|
||||
Version 2009-04-13
|
||||
|
||||
Strictly speaking, this is not a license. You can't give a license to use
|
||||
a simple number (such as e.g. 1500) for any purpose. This is a set of rules
|
||||
which should make it possible to build USB devices without the requirement
|
||||
for individual USB IDs. If you break one of the rules, you will run into
|
||||
technical problems sooner or later, but you don't risk legal trouble.
|
||||
|
||||
|
||||
OBJECTIVE DEVELOPMENT Software GmbH hereby grants you the non-exclusive
|
||||
right to use three USB.org vendor-ID (VID) / product-ID (PID) pairs with
|
||||
right to use four USB.org vendor-ID (VID) / product-ID (PID) pairs with
|
||||
products based on Objective Development's firmware-only USB driver for
|
||||
Atmel AVR microcontrollers:
|
||||
|
||||
@@ -27,10 +34,11 @@ used by many companies and individuals for different products. To avoid
|
||||
conflicts, your device and host driver software MUST adhere to the rules
|
||||
outlined below.
|
||||
|
||||
OBJECTIVE DEVELOPMENT Software GmbH has licensed these VID/PID pairs from
|
||||
Wouter van Ooijen (see www.voti.nl), who has licensed the VID from the USB
|
||||
Implementers Forum, Inc. (see www.usb.org). The VID is registered for the
|
||||
company name "Van Ooijen Technische Informatica".
|
||||
OBJECTIVE DEVELOPMENT Software GmbH has obtained these VID/PID pairs from
|
||||
Wouter van Ooijen (see www.voti.nl) for exclusive disposition. Wouter van
|
||||
Ooijen has obtained the VID from the USB Implementers Forum, Inc.
|
||||
(see www.usb.org). The VID is registered for the company name
|
||||
"Van Ooijen Technische Informatica".
|
||||
|
||||
|
||||
RULES AND RESTRICTIONS
|
||||
@@ -44,7 +52,7 @@ MUST be available at least in USB language 0x0409 (English/US).
|
||||
domain name (e.g. "mycompany.com") registered and owned by you, or an
|
||||
e-mail address under your control (e.g. "myname@gmx.net"). You can embed
|
||||
the domain name or e-mail address in any string you like, e.g. "Objective
|
||||
Development http://www.obdev.at/avrusb/".
|
||||
Development http://www.obdev.at/vusb/".
|
||||
|
||||
(3) You are responsible for retaining ownership of the domain or e-mail
|
||||
address for as long as any of your products are in use.
|
||||
@@ -142,5 +150,5 @@ violates the USB specification. If you do it, you do it at your own risk.
|
||||
|
||||
To avoid possible incompatibilities, we highly recommend that you get your
|
||||
own VID/PID pair if you intend to sell your product. Objective
|
||||
Development's commercial licenses for AVR-USB include a PID for
|
||||
Development's commercial licenses for V-USB include a PID for
|
||||
unrestricted exclusive use.
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Name: asmcommon.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2007-11-05
|
||||
* Tabsize: 4
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbconfig.h
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2005-04-01
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbconfig-prototype.h 734 2009-03-23 11:10:07Z cs $
|
||||
* This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __usbconfig_h_included__
|
||||
@@ -14,7 +14,7 @@
|
||||
/*
|
||||
General Description:
|
||||
This file is an example configuration (with inline documentation) for the USB
|
||||
driver. It configures AVR-USB for USB D+ connected to Port D bit 2 (which is
|
||||
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
|
||||
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
|
||||
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
|
||||
other hardware interrupt, as long as it is the highest level interrupt, see
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrv.c
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2004-12-29
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrv.c 721 2009-03-16 19:03:19Z cs $
|
||||
* This Revision: $Id: usbdrv.c 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
#include "usbportability.h"
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrv.h
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2004-12-29
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrv.h 738 2009-03-23 11:13:24Z cs $
|
||||
* This Revision: $Id: usbdrv.h 748 2009-04-15 15:05:07Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __usbdrv_h_included__
|
||||
@@ -122,7 +122,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
|
||||
/* --------------------------- Module Interface ---------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define USBDRV_VERSION 20090323
|
||||
#define USBDRV_VERSION 20090415
|
||||
/* This define uniquely identifies a driver version. It is a decimal number
|
||||
* constructed from the driver's release date in the form YYYYMMDD. If the
|
||||
* driver's behavior or interface changes, you can use this constant to
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm.S
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2007-06-13
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm.S 722 2009-03-16 19:03:57Z cs $
|
||||
* Revision: $Id: usbdrvasm.S 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Name: usbdrvasm.asm
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2006-03-01
|
||||
* Tabsize: 4
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm12.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2004-12-29
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrvasm12.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* This Revision: $Id: usbdrvasm12.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm128.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-10-11
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbdrvasm128.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* This Revision: $Id: usbdrvasm128.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm15.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: contributed by V. Bosch
|
||||
* Creation Date: 2007-08-06
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm15.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* Revision: $Id: usbdrvasm15.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm16.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2007-06-15
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm16.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* Revision: $Id: usbdrvasm16.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm165.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2007-04-22
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm165.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* Revision: $Id: usbdrvasm165.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbdrvasm18.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop)
|
||||
* Creation Date: 2009-01-20
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm18-crc.inc 734 2009-03-23 11:10:07Z cs $
|
||||
* Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,12 +1,12 @@
|
||||
/* Name: usbdrvasm20.inc
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Jeroen Benschop
|
||||
* Based on usbdrvasm16.inc from Christian Starkjohann
|
||||
* Creation Date: 2008-03-05
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* Revision: $Id: usbdrvasm20.inc 692 2008-11-07 15:07:40Z cs $
|
||||
* Revision: $Id: usbdrvasm20.inc 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/* Do not link this file! Link usbdrvasm.S instead, which includes the
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Name: usbportability.h
|
||||
* Project: AVR USB driver
|
||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-06-17
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: usbportability.h 692 2008-11-07 15:07:40Z cs $
|
||||
* This Revision: $Id: usbportability.h 740 2009-04-13 18:23:31Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user