dgen-sdl-1.23/Makefile.in 644 1750 1750 37754 7320414775 10373 # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # DGen/SDL v1.20+ # Tell how to make assembler files SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_alias = @build_alias@ build_triplet = @build@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ AWK = @AWK@ CC = @CC@ CHOP_ = @CHOP_@ CPP = @CPP@ CPUDIRS = @CPUDIRS@ CXX = @CXX@ CXXCPP = @CXXCPP@ EXTRAOBJS = @EXTRAOBJS@ INTERFACE = @INTERFACE@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ MUSA = @MUSA@ MZ80 = @MZ80@ NASM = @NASM@ NASM_FMT = @NASM_FMT@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STAR = @STAR@ VERSION = @VERSION@ SUFFIXES = .asmu .asm DIST_SUBDIRS = star musa mz80 sdl SUBDIRS = @CPUDIRS@ @INTERFACE@ INCLUDES = -I$(top_srcdir)/@INTERFACE@ bin_PROGRAMS = dgen tobin man_MANS = dgen.1 dgenrc.5 tobin.1 EXTRA_DIST = sample.dgenrc $(man_MANS) Makefile.asm.am # dgen dgen_SOURCES = rc.cpp romload.c md.cpp mdfr.cpp md-joe.cpp decode.c vdp.cpp save.cpp graph.cpp myfm.cpp fm.c sn76496.c ras.cpp main.cpp rc.h md-phil.h rc-vars.h md.h mz80.h fm.h decode.h mem.cpp ras-drawplane.h pd.h driver.h sn76496.h mz80.h starcpu.h m68k.h m68kconf.h dgen_LDADD = -L@INTERFACE@ -lpd @STAR@ @MUSA@ @MZ80@ @SDL_LIBS@ @EXTRAOBJS@ dgen_DEPENDENCIES = @EXTRAOBJS@ EXTRA_dgen_SOURCES = asm_tiles.asmu ctv.asmu asm_memcpy.asmu mmx_memcpy.asmu sn76496u.c zz80.c md-phil.cpp # tobin tobin_SOURCES = tobin.c romload.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = PROGRAMS = $(bin_PROGRAMS) DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ dgen_OBJECTS = rc.o romload.o md.o mdfr.o md-joe.o decode.o vdp.o \ save.o graph.o myfm.o fm.o sn76496.o ras.o main.o mem.o dgen_LDFLAGS = tobin_OBJECTS = tobin.o romload.o tobin_LDADD = $(LDADD) tobin_DEPENDENCIES = tobin_LDFLAGS = CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 MANS = $(man_MANS) NROFF = nroff DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ Makefile.in acinclude.m4 aclocal.m4 config.guess config.sub configure \ configure.in install-sh missing mkinstalldirs DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(dgen_SOURCES) $(EXTRA_dgen_SOURCES) $(tobin_SOURCES) OBJECTS = $(dgen_OBJECTS) $(tobin_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .asm .asmu .c .cpp .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.asm.am cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status $(ACLOCAL_M4): configure.in acinclude.m4 cd $(srcdir) && $(ACLOCAL) config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) cd $(srcdir) && $(AUTOCONF) mostlyclean-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) distclean-binPROGRAMS: maintainer-clean-binPROGRAMS: install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(bindir) @list='$(bin_PROGRAMS)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) list='$(bin_PROGRAMS)'; for p in $$list; do \ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ done .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: dgen: $(dgen_OBJECTS) $(dgen_DEPENDENCIES) @rm -f dgen $(CXXLINK) $(dgen_LDFLAGS) $(dgen_OBJECTS) $(dgen_LDADD) $(LIBS) tobin: $(tobin_OBJECTS) $(tobin_DEPENDENCIES) @rm -f tobin $(LINK) $(tobin_LDFLAGS) $(tobin_OBJECTS) $(tobin_LDADD) $(LIBS) .cpp.o: $(CXXCOMPILE) -c $< install-man1: $(mkinstalldirs) $(DESTDIR)$(man1dir) @list='$(man1_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ done uninstall-man1: @list='$(man1_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.1*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ rm -f $(DESTDIR)$(man1dir)/$$inst; \ done install-man5: $(mkinstalldirs) $(DESTDIR)$(man5dir) @list='$(man5_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.5*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \ $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \ done uninstall-man5: @list='$(man5_MANS)'; \ l2='$(man_MANS)'; for i in $$l2; do \ case "$$i" in \ *.5*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \ rm -f $(DESTDIR)$(man5dir)/$$inst; \ done install-man: $(MANS) @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-man1 install-man5 uninstall-man: @$(NORMAL_UNINSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 uninstall-man5 # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. @SET_MAKE@ all-recursive install-data-recursive install-exec-recursive \ installdirs-recursive install-recursive uninstall-recursive \ check-recursive installcheck-recursive info-recursive dvi-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ test "$$subdir" = "." && dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist -rm -rf $(distdir) GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz mkdir $(distdir)/=build mkdir $(distdir)/=inst dc_install_base=`cd $(distdir)/=inst && pwd`; \ cd $(distdir)/=build \ && ../configure --srcdir=.. --prefix=$$dc_install_base \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) dist -rm -rf $(distdir) @banner="$(distdir).tar.gz is ready for distribution"; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes" dist: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) dist-all: distdir -chmod -R a+r $(distdir) GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) -rm -rf $(distdir) distdir: $(DISTFILES) -rm -rf $(distdir) mkdir $(distdir) -chmod 777 $(distdir) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done for subdir in $(DIST_SUBDIRS); do \ if test "$$subdir" = .; then :; else \ test -d $(distdir)/$$subdir \ || mkdir $(distdir)/$$subdir \ || exit 1; \ chmod 777 $(distdir)/$$subdir; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ || exit 1; \ fi; \ done info-am: info: info-recursive dvi-am: dvi: dvi-recursive check-am: all-am check: check-recursive installcheck-am: installcheck: installcheck-recursive install-exec-am: install-binPROGRAMS install-exec: install-exec-recursive install-data-am: install-man install-data: install-data-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-recursive uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall: uninstall-recursive all-am: Makefile $(PROGRAMS) $(MANS) all-redirect: all-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: installdirs-recursive installdirs-am: $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1 \ $(DESTDIR)$(mandir)/man5 mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ mostlyclean-tags mostlyclean-generic mostlyclean: mostlyclean-recursive clean-am: clean-binPROGRAMS clean-compile clean-tags clean-generic \ mostlyclean-am clean: clean-recursive distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \ distclean-generic clean-am distclean: distclean-recursive -rm -f config.status maintainer-clean-am: maintainer-clean-binPROGRAMS \ maintainer-clean-compile maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-recursive -rm -f config.status .PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile install-man1 uninstall-man1 install-man5 \ uninstall-man5 install-man uninstall-man install-data-recursive \ uninstall-data-recursive install-exec-recursive \ uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ all-recursive check-recursive installcheck-recursive info-recursive \ dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ install-exec install-data-am install-data install-am install \ uninstall-am uninstall all-redirect all-am all installdirs-am \ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean .asm.o: @NASM@ -f @NASM_FMT@ $< .asmu.o: @@CHOP_@ $< > .$< @NASM@ -f @NASM_FMT@ -o $@ .$< @rm -f .$< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: dgen-sdl-1.23/README 644 1750 1750 15421 7320150124 7152 -------------------------------------------------------------------------------- WHAT IS THIS? -------------------------------------------------------------------------------- This is DGen/SDL, a semi-fantastic emulator for Unix-esque operating systems supported by the Simple DirectMedia Layer (SDL) library. It produces a virtual environment in which Sega Genesis (MegaDrive outside the US) games may run with fairly accurate audio and video. -------------------------------------------------------------------------------- HOW DO I INSTALL IT? -------------------------------------------------------------------------------- You'll need SDL version 1.0 or greater. Fetch it from http://www.libsdl.org/, and install it. Make sure, if you're using prepackaged rpm's or deb's, to get both the SDL and SDL-devel packages. For Intel/AMD/Cyrix CPUs, you'll also need NASM, which can be found at http://www.web-sites.co.uk/nasm/, in order to utilize the assembler optimizations. *WARNING*: The NASM that comes prepackaged with RedHat 7.x is broken! Install the rpm from RedHat 6.x, and it should work. One such rpm can be found at http://pknet.com/~joe/nasm-0.98-2.i386.rpm. Now you should be able to build and install DGen like any other autoconf-using package: sh ./configure && make && make install If you have egcs or GCC >= 2.95, you can give configure the '--with-extra-opt' switch, which will add some insane optimization to the CFLAGS used to compile the program, giving the binary a very decent speed boost. The control configuration and other options available in DGen/SDL are set through a file dgenrc, which should be in the location $HOME/.dgen/dgenrc. The sample.dgenrc file in this archive documents all the fields, and so does the dgenrc(5) manpage. If it doesn't exist, an empty one will be created when dgen is run. Now that it's been installed, running 'dgen ROMFILE' should run the Genesis program contained in ROMFILE. For a list of all the fancy options supported, run either 'dgen' with no options, or see the dgen(1) manpage for more detail. -------------------------------------------------------------------------------- IT'S TOO SLOW! -------------------------------------------------------------------------------- Well, sorry. Here are some ideas to help accelerate it: - Lower the value of "int_nice" in your dgenrc. 0 is good for short tempers :-) - Turn off sound. - Run fullscreen, if possible. - Increase int_soundsegs to 16 or (if you're desperate) 32. - Buy a faster computer. (sorry, had to say it ;) -------------------------------------------------------------------------------- IT'S TOO FAST! -------------------------------------------------------------------------------- I couldn't believe it either, but someone asked me this. If you happen to find yourself in this unfortunate predicament, here's how to slow it down: - Raise the sound rate to 44100Hz. It sounds a LOT better, and is a LOT slower. - Increase the value of int_nice in your dgenrc. This is the best way to slow things down, since it makes dgen much more CPU friendly. - In the game, press the key set to 'dgen_cpu_toggle' (which defaults to F11), to use the Musashi CPU core, which is slower and more accurate than StarScream. -------------------------------------------------------------------------------- FREQUENTLY ASKED QUESTIONS -------------------------------------------------------------------------------- Q: DGen segfaults on startup! A: The two most common causes of this are a broken NASM, or an absent NASM. RedHat 7.x distributions ship with a prepackaged NASM which doesn't work. You'll need to use an RPM from a different distribution, or RedHat 6.x. Q: How do I set up OpenGL mode? A: OpenGL mode can be activated either from the commandline, or from the dgenrc file. Using the '-G XxY' switch will activate OpenGL mode. The switch takes the desired resolution as an argument. For example: $ dgen -G 640x480 sonic.bin will run with a 640x480 screen resolution. So that you do not have to type this switch every time you use dgen, you can add the following lines to ~/.dgen/dgenrc so that dgen will start in OpenGL mode every time: bool_opengl = yes int_opengl_width = 640 int_opengl_height = 480 int_opengl_width and int_opengl_height can be changed to suit your own preferences. Q: I make dgen setuid-root, and try to run it fullscreen, and all I get is a black screen with the game running in the middle of it. A: You need to have your X server set up with a 320x240 video mode. For XFree86, if you have XF86Setup installed (which is more than likely): - Close all X sessions you have running. - From a console, as root, run "XF86Setup". When asked "Would you like to use the existing XF86Config file for defaults?" say Yes. - After 30 seconds or so the X server should start in VGA mode, and put you in the setup program. Everything else is set up, just click on the "Modeselection" button in the top right-hand corner. - From the list of possible modes, choose 1024x768 (or whatever mode you use regularly), and 320x240 (which is the mode DGen wants). Choose a bits-per- pixel from the list on the bottom (DGen works best in 15- or 16-bpp). - Press "Done", then "Okay". - It should restart the X server. When you see the message "Congratulations!...", try pressing CTRL-ALT-KEYPAD+ to switch to your new 320x240 mode, just to make sure it works. Press CTRL-ALT-KEYPAD- to switch back, and press "Save the configuration and exit". - Restart your X session. If you use xdm, press CTRL-ALT-BACKSPACE to kill the X server and restart it. Fullscreen should work now. Q: DGen's colors are messed up! A: Some video cards, such as most Riva cards, use different pixel formats for true-color modes. If you use 16-bpp bit depth, try 15- or 32-bpp bit depth. Q: I try compiling, but when I run ./configure, it tells me it can't find sdl-config. I installed SDL from the rpm's. A: You need to install the SDL-devel rpm as well: http://www.devolution.com/~slouken/SDL/release/SDL-devel--1.i386.rpm Q: Sonic 2 freezes right before the title screen! A: There is a bug in the StarScream CPU core which causes Sonic 2 to freeze at this point. Press F11 to switch to the Musashi core, until you get to the title sequence, then press it again to switch back to StarScream. Save a snapshot here, so you don't have to go through it again. :) -------------------------------------------------------------------------------- BUGS -------------------------------------------------------------------------------- Of course the chances of finding a bug are unlikely, but if you do, tell me about it. Send me a patch too, if possible :-) Also, check the FAQ above before reporting bugs, to see if your question's already been answered. Enjoy DGen! dgen-sdl-1.23/AUTHORS 644 1750 1750 2546 7242143532 7336 DGen was originally written by Dave . It was ported to SDL by Joe Groff and Phil K. Hornung . The following people have also made contributions to DGen: Andrew Bazan - Got DGen/SDL to run under BeOS. Steve Snake - The author of the best DOS emulator KGen, was also very patient with my stupid questions about the Genesis, thus allowing me to fix little emulation quirks. ;) Amy Lear - Helped add 8-bit sound support. :) Daniel Wislocki - Improved the sound engine to be nicer to higher-end systems. John Stiles - He works on the Mac port of DGen, and what a job he does! He wrote the original raster engine, and also has sped things up enormously. Dylan Griffiths - Rewrote a lot of the string-handling code to make it much less evil-looking. Allen Noe - Added screenshot functionality. Jeff Grady - Fixed compilation problems with gcc snapshots. Cameron Moore - Fixed SDL joystick initialization problems. Daniel Robbins - Helped fix timing problems on very fast machines. Andre Souza - Added OpenGL rendering mode. dgen-sdl-1.23/COPYING 644 1750 1750 3731 7034763436 7330 With the exceptions listed below, all files in this archive fall under this license: # Copyright (c) 1998, 1999 Dave. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the authors nor the names of their contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. The following files do not allow for commercial redistribution: musa/* zz80.c z80stb.h z80stbd.h The contents of the star/ directory are copyright Neil Corlett, under a license described in star/stardoc.txt. The contents of the mz80/ directory are copyright Neil Bradly, under a license described in mz80/mz80.txt. Open-source replacements for the above modules would be appreciated, if you have the time and ability. dgen-sdl-1.23/ChangeLog 644 1750 1750 13070 7320166124 10051 -------------------------------------------------------------------------------- WHAT'S NEW? -------------------------------------------------------------------------------- v1.23 <- v1.22 * Added fullscreen toggle, using Alt-Enter by default. * Added the ability to set modifiers on key bindings, using the prefixes "shift-", "ctrl-", "alt-", and "meta-". * When 'z' is pressed to stop emulation while running fullscreen, the screen is toggled into windowed mode until emulation resumes. (assuming SDL supports this on your platform) * Fixed some buffer overflows in the rc parser. - Fixed a minor bug in creating the .dgen directory framework upon first run. * NASM is now required on x86 platforms. - Fixed a possible problem in the configure script detecting NASM object format on non-ELF platforms. v1.22 <- v1.21 * Fixed save RAM problems with some games that did not properly switch save RAM on/off, such as Shadowrun and Shining Force. * Fixed SDL joystick code, thanks to Cameron Moore . * Fixed timing problems on FreeBSD and on very fast machines when playing with sound. If you use FreeBSD, I suggest updating to the latest 4-STABLE snapshot and rebuilding your kernel to get the best sound sync. * Added OpenGL rendering mode, thanks to Andre Souza . See the '-G' option in the dgen(1) manpage or 'bool_opengl' in dgenrc(5) in order to activate it. * Added 'bool_fullscreen', 'int_scale', 'bool_opengl', 'int_opengl_width', and 'int_opengl_height' dgenrc fields, in order to allow fullscreen, scaling, and OpenGL preferences to be set permanently in dgenrc. v1.21 <- v1.20a * Screenshot code added, courtesy of Allen Noe . The key_screenshot field in dgenrc sets the key that will make screenshots happen. Its default is F12. * MZ80 core updated to version 3.4. Sound in Aladdin and the Sonic games should run at the correct speed now. * Fixed a bug in the handling of handling saved state and RAM filenames, which would result in saved state files being saved with a null filename. - Added a '-s' switch, which will load the given saved state at startup. * Added support for joystick through SDL for SDL 1.1.x. - Fixed compilation problems with the gcc "2.96" on Redhat 7.x systems. Thanks to Jeff Grady . v1.20a <- 1.20 - Fixed a tiny problem that caused MMX to be improperly detected on some Linux boxes. v1.20 <- 1.18 * DGen now uses autoconf/automake, so compiling DGen is now as easy as './configure && make && make install'. Because of this, though, you'll need to upgrade SDL to v1.0.1. The new Autoconf scripts are still a bit experimental; if it seems broken on your platform, try to fix it and send a patch. - I rewrote and reorganized documentation to better fit the way Automake likes to do things. * Manpages are now available, for dgen(1) and dgenrc(5). * If the normal window size is too small for you, you can now scale the window with the new -X and -Y options. v1.19 <- v1.18 - $%&($! Nothing was working! v1.18 <- v1.17 * Enormous speed increase, thanks to the hard work of John Stiles, who also has put all interrupt bugs to rest, finally. * DGen works in FreeBSD! The included Makefile.config.FreeBSD should work without modifications. You need the GNU make and EGCS ports, though. * Demo record/play! You can record a demo of yourself playing a game with the '-d DEMONAME' switch, i.e. "dgen -d foo.demo my_rom.smd". Then play it back later with "dgen -D foo.demo my_rom.smd". Also, no verifaction checks are done on the demos, so you can feed it arbitrary files and see what happens, if you like. :) v1.17 <- v1.16 * Save RAM implementation has been overhauled, so now games with overlapping ROM and save RAM (like Phantasy Star IV and Sonic 3 + Knuckles) can save games correctly. Many thanks to Steve Snake for helping me make this work right. * Crude PAL mode support, give the '-P' option to use it. Doesn't work very well yet. - I made some changes that should (hopefully) make DGen run properly on big-endian platforms, but I don't have any way of testing it. If you have a PowerPC, SPARC, or other big-endian system, give it a try and help me iron out the wrinkles. :) * Window is now emulated properly, so Herzog Zwei split-screen and other little bugs should be fixed. Thanks again to Steve. - A little bug that caused SDL to complain about not being able to initialize sound, even if bool_sound was false in dgenrc, was fixed. This should help all you folks without sound cards. * Assembler tile rendering is now in place for the new raster effect engine. A small but noticeable speed increase. :) [PKH] * All the SDL-dependent stuff has been separated into the sdl/ directory, and I wrote a little platform-dependent (pd) API so you can attach an interface for your favorite Unix-like operating system and toolkit. :) If you want to do a port to BeOS, MacOS X, QNX, etc. this should make your life easier. I also hope to have raw Xlib and SVGAlib interfaces to replace SDL, and thus require one less thing to download. :) - Improved sound writing method, by Daniel Wislocki . He says this improves flaky sound in 44kHz, and also fixes the problem of the emulator being too fast. I have a very slow computer, so I have to take his word for it. ;) - I also removed most of the messages dgen makes (except for errors), so that it is quieter. If you liked having all those messages, tell me and I'll put them back in. ;) dgen-sdl-1.23/INSTALL 644 1750 1750 17227 7027317553 7350 Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. dgen-sdl-1.23/Makefile.am 644 1750 1750 1553 7245054735 10330 # DGen/SDL v1.20+ include $(top_srcdir)/Makefile.asm.am DIST_SUBDIRS = star musa mz80 sdl SUBDIRS = @CPUDIRS@ @INTERFACE@ INCLUDES += -I$(top_srcdir)/@INTERFACE@ bin_PROGRAMS = dgen tobin man_MANS = dgen.1 dgenrc.5 tobin.1 EXTRA_DIST = sample.dgenrc $(man_MANS) Makefile.asm.am # dgen dgen_SOURCES = rc.cpp romload.c md.cpp mdfr.cpp md-joe.cpp decode.c vdp.cpp \ save.cpp graph.cpp myfm.cpp fm.c sn76496.c ras.cpp main.cpp \ rc.h md-phil.h rc-vars.h md.h mz80.h fm.h decode.h mem.cpp \ ras-drawplane.h pd.h driver.h sn76496.h \ mz80.h starcpu.h m68k.h m68kconf.h dgen_LDADD = -L@INTERFACE@ -lpd @STAR@ @MUSA@ @MZ80@ @SDL_LIBS@ @EXTRAOBJS@ dgen_DEPENDENCIES = @EXTRAOBJS@ EXTRA_dgen_SOURCES = asm_tiles.asmu ctv.asmu asm_memcpy.asmu mmx_memcpy.asmu \ sn76496u.c zz80.c md-phil.cpp # tobin tobin_SOURCES = tobin.c romload.c dgen-sdl-1.23/acinclude.m4 644 1750 1750 13624 7027317553 10505 # Configure paths for SDL # Sam Lantinga 9/21/99 # stolen from Manish Singh # stolen back from Frank Belew # stolen from Manish Singh # Shamelessly stolen from Owen Taylor dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl AC_DEFUN(AM_PATH_SDL, [dnl dnl Get the cflags and libraries from the sdl-config script dnl AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], sdl_prefix="$withval", sdl_prefix="") AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], sdl_exec_prefix="$withval", sdl_exec_prefix="") AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], , enable_sdltest=yes) if test x$sdl_exec_prefix != x ; then sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config fi fi if test x$sdl_prefix != x ; then sdl_args="$sdl_args --prefix=$sdl_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_prefix/bin/sdl-config fi fi AC_PATH_PROG(SDL_CONFIG, sdl-config, no) min_sdl_version=ifelse([$1], ,0.11.0,$1) AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) no_sdl="" if test "$SDL_CONFIG" = "no" ; then no_sdl=yes else SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_sdltest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" dnl dnl Now check if the installed SDL is sufficiently new. (Also sanity dnl checks the results of sdl-config to some extent dnl rm -f conf.sdltest AC_TRY_RUN([ #include #include #include #include char* my_strdup (char *str) { char *new_str; if (str) { new_str = malloc ((strlen (str) + 1) * sizeof(char)); strcpy (new_str, str); } else new_str = NULL; return new_str; } int main (int argc, char *argv[]) { int major, minor, micro; char *tmp_version; /* This hangs on some systems (?) system ("touch conf.sdltest"); */ { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = my_strdup("$min_sdl_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_sdl_version"); exit(1); } if (($sdl_major_version > major) || (($sdl_major_version == major) && ($sdl_minor_version > minor)) || (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) { return 0; } else { printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); printf("*** best to upgrade to the required version.\n"); printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); printf("*** to point to the correct copy of sdl-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } ],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_sdl" = x ; then AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$SDL_CONFIG" = "no" ; then echo "*** The sdl-config script installed by SDL could not be found" echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the SDL_CONFIG environment variable to the" echo "*** full path to sdl-config." else if test -f conf.sdltest ; then : else echo "*** Could not run SDL test program, checking why..." CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" AC_TRY_LINK([ #include #include ], [ return 0; ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi SDL_CFLAGS="" SDL_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(SDL_CFLAGS) AC_SUBST(SDL_LIBS) rm -f conf.sdltest ]) dgen-sdl-1.23/aclocal.m4 644 1750 1750 23013 7320137254 10137 dnl aclocal.m4 generated automatically by aclocal 1.4 dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A dnl PARTICULAR PURPOSE. # Configure paths for SDL # Sam Lantinga 9/21/99 # stolen from Manish Singh # stolen back from Frank Belew # stolen from Manish Singh # Shamelessly stolen from Owen Taylor dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl AC_DEFUN(AM_PATH_SDL, [dnl dnl Get the cflags and libraries from the sdl-config script dnl AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], sdl_prefix="$withval", sdl_prefix="") AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], sdl_exec_prefix="$withval", sdl_exec_prefix="") AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], , enable_sdltest=yes) if test x$sdl_exec_prefix != x ; then sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config fi fi if test x$sdl_prefix != x ; then sdl_args="$sdl_args --prefix=$sdl_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_prefix/bin/sdl-config fi fi AC_PATH_PROG(SDL_CONFIG, sdl-config, no) min_sdl_version=ifelse([$1], ,0.11.0,$1) AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) no_sdl="" if test "$SDL_CONFIG" = "no" ; then no_sdl=yes else SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_sdltest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" dnl dnl Now check if the installed SDL is sufficiently new. (Also sanity dnl checks the results of sdl-config to some extent dnl rm -f conf.sdltest AC_TRY_RUN([ #include #include #include #include char* my_strdup (char *str) { char *new_str; if (str) { new_str = malloc ((strlen (str) + 1) * sizeof(char)); strcpy (new_str, str); } else new_str = NULL; return new_str; } int main (int argc, char *argv[]) { int major, minor, micro; char *tmp_version; /* This hangs on some systems (?) system ("touch conf.sdltest"); */ { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = my_strdup("$min_sdl_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_sdl_version"); exit(1); } if (($sdl_major_version > major) || (($sdl_major_version == major) && ($sdl_minor_version > minor)) || (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) { return 0; } else { printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); printf("*** best to upgrade to the required version.\n"); printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); printf("*** to point to the correct copy of sdl-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } ],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_sdl" = x ; then AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$SDL_CONFIG" = "no" ; then echo "*** The sdl-config script installed by SDL could not be found" echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the SDL_CONFIG environment variable to the" echo "*** full path to sdl-config." else if test -f conf.sdltest ; then : else echo "*** Could not run SDL test program, checking why..." CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" AC_TRY_LINK([ #include #include ], [ return 0; ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi SDL_CFLAGS="" SDL_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(SDL_CFLAGS) AC_SUBST(SDL_LIBS) rm -f conf.sdltest ]) # Do all the work for Automake. This macro actually does too much -- # some checks are only needed if your package does certain things. # But this isn't really a big deal. # serial 1 dnl Usage: dnl AM_INIT_AUTOMAKE(package,version, [no-define]) AC_DEFUN(AM_INIT_AUTOMAKE, [AC_REQUIRE([AC_PROG_INSTALL]) PACKAGE=[$1] AC_SUBST(PACKAGE) VERSION=[$2] AC_SUBST(VERSION) dnl test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi ifelse([$3],, AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) AC_REQUIRE([AM_SANITY_CHECK]) AC_REQUIRE([AC_ARG_PROGRAM]) dnl FIXME This is truly gross. missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_REQUIRE([AC_PROG_MAKE_SET])]) # # Check to make sure that the build environment is sane. # AC_DEFUN(AM_SANITY_CHECK, [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftestfile # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` if test "[$]*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftestfile` fi if test "[$]*" != "X $srcdir/configure conftestfile" \ && test "[$]*" != "X conftestfile $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "[$]2" = conftestfile ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi rm -f conftest* AC_MSG_RESULT(yes)]) dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) dnl The program must properly implement --version. AC_DEFUN(AM_MISSING_PROG, [AC_MSG_CHECKING(for working $2) # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if ($2 --version) < /dev/null > /dev/null 2>&1; then $1=$2 AC_MSG_RESULT(found) else $1="$3/missing $2" AC_MSG_RESULT(missing) fi AC_SUBST($1)]) # Define a conditional. AC_DEFUN(AM_CONDITIONAL, [AC_SUBST($1_TRUE) AC_SUBST($1_FALSE) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi]) dgen-sdl-1.23/config.guess 755 1750 1750 65320 7114255443 10630 #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Written by Per Bothner . # The master version of this file is at the FSF in /home/gd/gnu/lib. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit system type (host/target name). # # Only a few systems have been added to this list; please add others # (but try to keep the structure clean). # # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 8/24/94.) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown dummy=dummy-$$ trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. cat <$dummy.s .globl main .ent main main: .frame \$30,0,\$26,0 .prologue 0 .long 0x47e03d80 # implver $0 lda \$2,259 .long 0x47e20c21 # amask $2,$1 srl \$1,8,\$2 sll \$2,2,\$2 sll \$0,3,\$0 addl \$1,\$0,\$0 addl \$2,\$0,\$0 ret \$31,(\$26),1 .end main EOF ${CC-cc} $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then ./$dummy case "$?" in 7) UNAME_MACHINE="alpha" ;; 15) UNAME_MACHINE="alphaev5" ;; 14) UNAME_MACHINE="alphaev56" ;; 10) UNAME_MACHINE="alphapca56" ;; 16) UNAME_MACHINE="alphaev6" ;; esac fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-cbm-sysv4 exit 0;; amiga:NetBSD:*:*) echo m68k-cbm-netbsd${UNAME_RELEASE} exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; arc64:OpenBSD:*:*) echo mips64el-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hkmips:OpenBSD:*:*) echo mips-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mips-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; arm32:NetBSD:*:*) echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` exit 0 ;; SR2?01:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; atari*:NetBSD:*:*) echo m68k-atari-netbsd${UNAME_RELEASE} exit 0 ;; atari*:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3*:NetBSD:*:*) echo m68k-sun-netbsd${UNAME_RELEASE} exit 0 ;; sun3*:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:NetBSD:*:*) echo m68k-apple-netbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; macppc:NetBSD:*:*) echo powerpc-apple-netbsd${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) sed 's/^ //' << EOF >$dummy.c int main (argc, argv) int argc; char **argv; { #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF ${CC-cc} $dummy.c -o $dummy \ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i?86:AIX:*:*) echo i386-ibm-aix exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF ${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:4) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=4.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 ) sed 's/^ //' << EOF >$dummy.c #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (${CC-cc} $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` rm -f $dummy.c $dummy esac HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF ${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i?86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*X-MP:*:*:*) echo xmp-cray-unicos exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} exit 0 ;; CRAY*T3E:*:*:*) echo t3e-cray-unicosmk${UNAME_RELEASE} exit 0 ;; CRAY-2:*:*:*) echo cray2-cray-unicos exit 0 ;; F300:UNIX_System_V:*:*) FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; F301:UNIX_System_V:*:*) echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` exit 0 ;; hp3[0-9][05]:NetBSD:*:*) echo m68k-hp-netbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; i?86:BSD/386:*:* | i?86:BSD/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; *:NetBSD:*:*) echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:Linux:*:*) # uname on the ARM produces all sorts of strangeness, and we need to # filter it out. case "$UNAME_MACHINE" in arm* | sa110*) UNAME_MACHINE="arm" ;; esac # The BFD linker knows what the default object file format is, so # first see if it will tell us. ld_help_string=`ld --help 2>&1` ld_supported_emulations=`echo $ld_help_string \ | sed -ne '/supported emulations:/!d s/[ ][ ]*/ /g s/.*supported emulations: *// s/ .*// p'` case "$ld_supported_emulations" in i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;; esac if test "${UNAME_MACHINE}" = "alpha" ; then sed 's/^ //' <$dummy.s .globl main .ent main main: .frame \$30,0,\$26,0 .prologue 0 .long 0x47e03d80 # implver $0 lda \$2,259 .long 0x47e20c21 # amask $2,$1 srl \$1,8,\$2 sll \$2,2,\$2 sll \$0,3,\$0 addl \$1,\$0,\$0 addl \$2,\$0,\$0 ret \$31,(\$26),1 .end main EOF LIBC="" ${CC-cc} $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then ./$dummy case "$?" in 7) UNAME_MACHINE="alpha" ;; 15) UNAME_MACHINE="alphaev5" ;; 14) UNAME_MACHINE="alphaev56" ;; 10) UNAME_MACHINE="alphapca56" ;; 16) UNAME_MACHINE="alphaev6" ;; esac objdump --private-headers $dummy | \ grep ld.so.1 > /dev/null if test "$?" = 0 ; then LIBC="libc1" fi fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 elif test "${UNAME_MACHINE}" = "mips" ; then cat >$dummy.c </dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy else # Either a pre-BFD a.out linker (linux-gnuoldld) # or one that does not give us useful --help. # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. # If ld does not provide *any* "supported emulations:" # that means it is gnuoldld. echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 case "${UNAME_MACHINE}" in i?86) VENDOR=pc; ;; *) VENDOR=unknown; ;; esac # Determine whether the default compiler is a.out or elf cat >$dummy.c < main(argc, argv) int argc; char *argv[]; { #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); # else printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); # endif # else printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); # endif #else printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); #endif return 0; } EOF ${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy fi ;; # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions # are messed up and put the nodename in both sysname and nodename. i?86:DYNIX/ptx:4*:*) echo i386-sequent-sysv4 exit 0 ;; i?86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} fi exit 0 ;; i?86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i?86:UnixWare:*:*) if /bin/uname -X 2>/dev/null >/dev/null ; then (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 fi echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION} exit 0 ;; pc:*:*:*) # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i?86:LynxOS:2.*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:*:6*) echo mips-sony-newsos6 exit 0 ;; R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) printf ("vax-dec-bsd\n"); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF ${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi #echo '(Unable to guess system type)' 1>&2 exit 1 dgen-sdl-1.23/config.sub 755 1750 1750 46611 7114255443 10275 #! /bin/sh # Configuration validation subroutine script, version 1.1. # Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc. # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. if [ x$1 = x ] then echo Configuration name missing. 1>&2 echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 echo "or $0 ALIAS" 1>&2 echo where ALIAS is a recognized configuration type. 1>&2 exit 1 fi # First pass through any local machine types. case $1 in *local*) echo $1 exit 0 ;; *) ;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in linux-gnu*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple) os= basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \ | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ | mipstx39 | mipstx39el \ | sparc | sparclet | sparclite | sparc64 | v850) basic_machine=$basic_machine-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i[34567]86) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \ | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ | sparc64-* | mips64-* | mipsel-* \ | mips64el-* | mips64orion-* | mips64orionel-* \ | mipstx39-* | mipstx39el-* \ | f301-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-cbm ;; amigaos | amigados) basic_machine=m68k-cbm os=-amigaos ;; amigaunix | amix) basic_machine=m68k-cbm os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | ymp) basic_machine=ymp-cray os=-unicos ;; cray2) basic_machine=cray2-cray os=-unicos ;; [ctj]90-cray) basic_machine=c90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; i370-ibm* | ibm*) basic_machine=i370-ibm os=-mvs ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i[34567]86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i[34567]86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i[34567]86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i[34567]86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; miniframe) basic_machine=m68000-convergent ;; mipsel*-linux*) basic_machine=mipsel-unknown os=-linux-gnu ;; mips*-linux*) basic_machine=mips-unknown os=-linux-gnu ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; np1) basic_machine=np1-gould ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | nexen) basic_machine=i586-pc ;; pentiumpro | p6 | k6 | 6x86) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | nexen-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | k6-* | 6x86-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=rs6000-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; symmetry) basic_machine=i386-sequent os=-dynix ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; xmp) basic_machine=xmp-cray os=-unicos ;; xps | xps100) basic_machine=xps100-honeywell ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. mips) if [ x$os = x-linux-gnu ]; then basic_machine=mips-unknown else basic_machine=mips-mips fi ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sparc) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -rhapsody* \ | -openstep*) # Remember, each alternative MUST END IN *, to match a version number. ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -ctix* | -uts*) os=-sysv ;; -ns2 ) os=-nextstep2 ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -xenix) os=-xenix ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-semi) os=-aout ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f301-fujitsu) os=-uxpv ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -hpux*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks*) vendor=wrs ;; -aux*) vendor=apple ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os dgen-sdl-1.23/configure 755 1750 1750 325543 7320137255 10244 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --with-extra-opt Add extra optimizations (egcs/GCC >= 2.95 only)" ac_help="$ac_help --with-sdl-prefix=PFX Prefix where SDL is installed (optional)" ac_help="$ac_help --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)" ac_help="$ac_help --disable-sdltest Do not try to compile and run a test SDL program" ac_help="$ac_help --with-x use the X Window System" ac_help="$ac_help --without-opengl Don't use SDL OpenGL support" ac_help="$ac_help --without-nasm Don't use NASM for assembler routines" ac_help="$ac_help --without-mmx Don't use MMX routines, even if supported" ac_help="$ac_help --without-star Don't use StarScream assembler CPU core if available" ac_help="$ac_help --without-musa Don't use Musashi C CPU core" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=decode.c # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break fi done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # Do some error checking and defaulting for the host and target type. # The inputs are: # configure --host=HOST --target=TARGET --build=BUILD NONOPT # # The rules are: # 1. You are not allowed to specify --host, --target, and nonopt at the # same time. # 2. Host defaults to nonopt. # 3. If nonopt is not specified, then host defaults to the current host, # as determined by config.guess. # 4. Target and build default to nonopt. # 5. If nonopt is not specified, then target and build default to host. # The aliases save the names the user supplied, while $host etc. # will get canonicalized. case $host---$target---$nonopt in NONE---*---* | *---NONE---* | *---*---NONE) ;; *) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; esac # Make sure we can run config.sub. if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 echo "configure:593: checking host system type" >&5 host_alias=$host case "$host_alias" in NONE) case $nonopt in NONE) if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } fi ;; *) host_alias=$nonopt ;; esac ;; esac host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 echo "configure:614: checking target system type" >&5 target_alias=$target case "$target_alias" in NONE) case $nonopt in NONE) target_alias=$host_alias ;; *) target_alias=$nonopt ;; esac ;; esac target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 echo "configure:632: checking build system type" >&5 build_alias=$build case "$build_alias" in NONE) case $nonopt in NONE) build_alias=$host_alias ;; *) build_alias=$nonopt ;; esac ;; esac build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$build" 1>&6 test "$host_alias" != "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- machtype=$target_cpu # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:668: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 echo "configure:721: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftestfile` fi if test "$*" != "X $srcdir/configure conftestfile" \ && test "$*" != "X conftestfile $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { echo "configure: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" 1>&2; exit 1; } fi test "$2" = conftestfile ) then # Ok. : else { echo "configure: error: newly created file is older than distributed files! Check your system clock" 1>&2; exit 1; } fi rm -f conftest* echo "$ac_t""yes" 1>&6 if test "$program_transform_name" = s,x,x,; then program_transform_name= else # Double any \ or $. echo might interpret backslashes. cat <<\EOF_SED > conftestsed s,\\,\\\\,g; s,\$,$$,g EOF_SED program_transform_name="`echo $program_transform_name|sed -f conftestsed`" rm -f conftestsed fi test "$program_prefix" != NONE && program_transform_name="s,^,${program_prefix},; $program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" # sed with no file args requires a program. test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo "configure:778: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftestmake <<\EOF all: @echo 'ac_maketemp="${MAKE}"' EOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftestmake fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$ac_t""yes" 1>&6 SET_MAKE= else echo "$ac_t""no" 1>&6 SET_MAKE="MAKE=${MAKE-make}" fi PACKAGE=dgen-sdl VERSION=1.23 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } fi cat >> confdefs.h <> confdefs.h <&6 echo "configure:824: checking for working aclocal" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (aclocal --version) < /dev/null > /dev/null 2>&1; then ACLOCAL=aclocal echo "$ac_t""found" 1>&6 else ACLOCAL="$missing_dir/missing aclocal" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 echo "configure:837: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (autoconf --version) < /dev/null > /dev/null 2>&1; then AUTOCONF=autoconf echo "$ac_t""found" 1>&6 else AUTOCONF="$missing_dir/missing autoconf" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working automake""... $ac_c" 1>&6 echo "configure:850: checking for working automake" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (automake --version) < /dev/null > /dev/null 2>&1; then AUTOMAKE=automake echo "$ac_t""found" 1>&6 else AUTOMAKE="$missing_dir/missing automake" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 echo "configure:863: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (autoheader --version) < /dev/null > /dev/null 2>&1; then AUTOHEADER=autoheader echo "$ac_t""found" 1>&6 else AUTOHEADER="$missing_dir/missing autoheader" echo "$ac_t""missing" 1>&6 fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 echo "configure:876: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. if (makeinfo --version) < /dev/null > /dev/null 2>&1; then MAKEINFO=makeinfo echo "$ac_t""found" 1>&6 else MAKEINFO="$missing_dir/missing makeinfo" echo "$ac_t""missing" 1>&6 fi # Check whether --with-extra-opt or --without-extra-opt was given. if test "${with_extra_opt+set}" = set; then withval="$with_extra_opt" ADD_OPT=$withval else ADD_OPT=no fi if test x$ADD_OPT \!= xno; then case $machtype in i?86) CFLAGS="$CFLAGS -O3 -mpentium -march=pentium -fstrength-reduce -fomit-frame-pointer -frerun-cse-after-loop -funroll-loops -ffast-math -malign-functions=5 -malign-jumps=5 -malign-loops=5 -malign-double -fno-exceptions -fno-rtti" CXXFLAGS="$CXXFLAGS -O3 -mpentium -march=pentium -fstrength-reduce -fomit-frame-pointer -frerun-cse-after-loop -funroll-loops -ffast-math -malign-functions=5 -malign-jumps=5 -malign-loops=5 -malign-double -fno-exceptions -fno-rtti" ;; *) CFLAGS="$CFLAGS -O3 -ffast-math -fomit-frame-pointer -fno-exceptions -fno-rtti -funroll-loops -frerun-cse-after-loop" CXXFLAGS="$CXXFLAGS -O3 -ffast-math -fomit-frame-pointer -fno-exceptions -fno-rtti -funroll-loops -frerun-cse-after-loop" ;; esac fi for ac_prog in mawk gawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:917: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_AWK="$ac_prog" break fi done IFS="$ac_save_ifs" fi fi AWK="$ac_cv_prog_AWK" if test -n "$AWK"; then echo "$ac_t""$AWK" 1>&6 else echo "$ac_t""no" 1>&6 fi test -n "$AWK" && break done # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:949: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:979: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:1030: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:1062: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 1073 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:1078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:1104: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:1109: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:1137: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:1169: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1190: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1207: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1224: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:1253: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CXX="$ac_prog" break fi done IFS="$ac_save_ifs" fi fi CXX="$ac_cv_prog_CXX" if test -n "$CXX"; then echo "$ac_t""$CXX" 1>&6 else echo "$ac_t""no" 1>&6 fi test -n "$CXX" && break done test -n "$CXX" || CXX="gcc" echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:1285: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cxx_cross cat > conftest.$ac_ext << EOF #line 1296 "configure" #include "confdefs.h" int main(){return(0);} EOF if { (eval echo configure:1301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cxx_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cxx_cross=no else ac_cv_prog_cxx_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cxx_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 if test $ac_cv_prog_cxx_works = no; then { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:1327: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 cross_compiling=$ac_cv_prog_cxx_cross echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 echo "configure:1332: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.C <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no fi fi echo "$ac_t""$ac_cv_prog_gxx" 1>&6 if test $ac_cv_prog_gxx = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS="${CXXFLAGS+set}" ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 echo "configure:1360: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.cc if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then ac_cv_prog_cxx_g=yes else ac_cv_prog_cxx_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6 if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS="$ac_save_CXXFLAGS" elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 echo "configure:1392: checking how to run the C++ preprocessor" >&5 if test -z "$CXXCPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cxx_cross CXXCPP="${CXX-g++} -E" cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1410: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CXXCPP=/lib/cpp fi rm -f conftest* ac_cv_prog_CXXCPP="$CXXCPP" ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross fi fi CXXCPP="$ac_cv_prog_CXXCPP" echo "$ac_t""$CXXCPP" 1>&6 # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:1446: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 echo "configure:1499: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftestdata if ln -s X conftestdata 2>/dev/null then rm -f conftestdata ac_cv_prog_LN_S="ln -s" else ac_cv_prog_LN_S=ln fi fi LN_S="$ac_cv_prog_LN_S" if test "$ac_cv_prog_LN_S" = "ln -s"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:1522: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_RANLIB="ranlib" break fi done IFS="$ac_save_ifs" test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" fi fi RANLIB="$ac_cv_prog_RANLIB" if test -n "$RANLIB"; then echo "$ac_t""$RANLIB" 1>&6 else echo "$ac_t""no" 1>&6 fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo "configure:1551: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftestmake <<\EOF all: @echo 'ac_maketemp="${MAKE}"' EOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftestmake fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$ac_t""yes" 1>&6 SET_MAKE= else echo "$ac_t""no" 1>&6 SET_MAKE="MAKE=${MAKE-make}" fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 echo "configure:1587: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include int main() { #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN bogus endian macros #endif ; return 0; } EOF if { (eval echo configure:1605: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include int main() { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } EOF if { (eval echo configure:1620: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_bigendian=no fi rm -f conftest* else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* if test $ac_cv_c_bigendian = unknown; then if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_c_bigendian=yes fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_c_bigendian" 1>&6 if test $ac_cv_c_bigendian = yes; then cat >> confdefs.h <<\EOF #define WORDS_BIGENDIAN 1 EOF fi # Check whether --with-sdl-prefix or --without-sdl-prefix was given. if test "${with_sdl_prefix+set}" = set; then withval="$with_sdl_prefix" sdl_prefix="$withval" else sdl_prefix="" fi # Check whether --with-sdl-exec-prefix or --without-sdl-exec-prefix was given. if test "${with_sdl_exec_prefix+set}" = set; then withval="$with_sdl_exec_prefix" sdl_exec_prefix="$withval" else sdl_exec_prefix="" fi # Check whether --enable-sdltest or --disable-sdltest was given. if test "${enable_sdltest+set}" = set; then enableval="$enable_sdltest" : else enable_sdltest=yes fi if test x$sdl_exec_prefix != x ; then sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config fi fi if test x$sdl_prefix != x ; then sdl_args="$sdl_args --prefix=$sdl_prefix" if test x${SDL_CONFIG+set} != xset ; then SDL_CONFIG=$sdl_prefix/bin/sdl-config fi fi # Extract the first word of "sdl-config", so it can be a program name with args. set dummy sdl-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:1718: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case "$SDL_CONFIG" in /*) ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a path. ;; ?:/*) ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a dos path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_path_SDL_CONFIG="$ac_dir/$ac_word" break fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_SDL_CONFIG" && ac_cv_path_SDL_CONFIG="no" ;; esac fi SDL_CONFIG="$ac_cv_path_SDL_CONFIG" if test -n "$SDL_CONFIG"; then echo "$ac_t""$SDL_CONFIG" 1>&6 else echo "$ac_t""no" 1>&6 fi min_sdl_version=1.0.0 echo $ac_n "checking for SDL - version >= $min_sdl_version""... $ac_c" 1>&6 echo "configure:1753: checking for SDL - version >= $min_sdl_version" >&5 no_sdl="" if test "$SDL_CONFIG" = "no" ; then no_sdl=yes else SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` if test "x$enable_sdltest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" rm -f conf.sdltest if test "$cross_compiling" = yes; then echo $ac_n "cross compiling; assumed OK... $ac_c" else cat > conftest.$ac_ext < #include #include #include char* my_strdup (char *str) { char *new_str; if (str) { new_str = malloc ((strlen (str) + 1) * sizeof(char)); strcpy (new_str, str); } else new_str = NULL; return new_str; } int main (int argc, char *argv[]) { int major, minor, micro; char *tmp_version; /* This hangs on some systems (?) system ("touch conf.sdltest"); */ { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = my_strdup("$min_sdl_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_sdl_version"); exit(1); } if (($sdl_major_version > major) || (($sdl_major_version == major) && ($sdl_minor_version > minor)) || (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) { return 0; } else { printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); printf("*** best to upgrade to the required version.\n"); printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); printf("*** to point to the correct copy of sdl-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } EOF if { (eval echo configure:1838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* no_sdl=yes fi rm -fr conftest* fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_sdl" = x ; then echo "$ac_t""yes" 1>&6 true else echo "$ac_t""no" 1>&6 if test "$SDL_CONFIG" = "no" ; then echo "*** The sdl-config script installed by SDL could not be found" echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the SDL_CONFIG environment variable to the" echo "*** full path to sdl-config." else if test -f conf.sdltest ; then : else echo "*** Could not run SDL test program, checking why..." CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" cat > conftest.$ac_ext < #include int main() { return 0; ; return 0; } EOF if { (eval echo configure:1882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" fi rm -f conftest* CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi SDL_CFLAGS="" SDL_LIBS="" { echo "configure: error: *** SDL version >= 1.0.0 not found." 1>&2; exit 1; } fi rm -f conf.sdltest CFLAGS="$CFLAGS $SDL_CFLAGS" CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" INTERFACE=sdl OLD_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SDL_CFLAGS" EXTRAOBJS= JOYSTICK_SUPPORT=no ac_safe=`echo "SDL_joystick.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for SDL_joystick.h""... $ac_c" 1>&6 echo "configure:1928: checking for SDL_joystick.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1938: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 JOYSTICK_SUPPORT=SDL else echo "$ac_t""no" 1>&6 ac_safe=`echo "linux/joystick.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for linux/joystick.h""... $ac_c" 1>&6 echo "configure:1959: checking for linux/joystick.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1969: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 JOYSTICK_SUPPORT=LINUX else echo "$ac_t""no" 1>&6 fi fi # If we find X, set shell vars x_includes and x_libraries to the # paths, otherwise set no_x=yes. # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 echo "configure:1998: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then withval="$with_x" : fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then # Both variables are already set. have_x=yes else if eval "test \"`echo '$''{'ac_cv_have_x'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=NO ac_x_libraries=NO rm -fr conftestdir if mkdir conftestdir; then cd conftestdir # Make sure to not put "make" in the Imakefile rules, since we grep it out. cat > Imakefile <<'EOF' acfindx: @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' EOF if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl; do if test ! -f $ac_im_usrlibdir/libX11.$ac_extension && test -f $ac_im_libdir/libX11.$ac_extension; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case "$ac_im_incroot" in /usr/include) ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;; esac case "$ac_im_usrlibdir" in /usr/lib | /lib) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;; esac fi cd .. rm -fr conftestdir fi if test "$ac_x_includes" = NO; then # Guess where to find include files, by looking for this one X11 .h file. test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h # First, try using that file with no special directory specified. cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:2065: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* # We can compile using X headers with no special include directory. ac_x_includes= else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* # Look for the header file in a standard set of common directories. # Check X11 before X11Rn because it is often a symlink to the current release. for ac_dir in \ /usr/X11/include \ /usr/X11R6/include \ /usr/X11R5/include \ /usr/X11R4/include \ \ /usr/include/X11 \ /usr/include/X11R6 \ /usr/include/X11R5 \ /usr/include/X11R4 \ \ /usr/local/X11/include \ /usr/local/X11R6/include \ /usr/local/X11R5/include \ /usr/local/X11R4/include \ \ /usr/local/include/X11 \ /usr/local/include/X11R6 \ /usr/local/include/X11R5 \ /usr/local/include/X11R4 \ \ /usr/X386/include \ /usr/x386/include \ /usr/XFree86/include/X11 \ \ /usr/include \ /usr/local/include \ /usr/unsupported/include \ /usr/athena/include \ /usr/local/x11r5/include \ /usr/lpp/Xamples/include \ \ /usr/openwin/include \ /usr/openwin/share/include \ ; \ do if test -r "$ac_dir/$x_direct_test_include"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest* fi # $ac_x_includes = NO if test "$ac_x_libraries" = NO; then # Check for the libraries. test -z "$x_direct_test_library" && x_direct_test_library=Xt test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. ac_x_libraries= else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$ac_save_LIBS" # First see if replacing the include by lib works. # Check X11 before X11Rn because it is often a symlink to the current release. for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \ /usr/X11/lib \ /usr/X11R6/lib \ /usr/X11R5/lib \ /usr/X11R4/lib \ \ /usr/lib/X11 \ /usr/lib/X11R6 \ /usr/lib/X11R5 \ /usr/lib/X11R4 \ \ /usr/local/X11/lib \ /usr/local/X11R6/lib \ /usr/local/X11R5/lib \ /usr/local/X11R4/lib \ \ /usr/local/lib/X11 \ /usr/local/lib/X11R6 \ /usr/local/lib/X11R5 \ /usr/local/lib/X11R4 \ \ /usr/X386/lib \ /usr/x386/lib \ /usr/XFree86/lib/X11 \ \ /usr/lib \ /usr/local/lib \ /usr/unsupported/lib \ /usr/athena/lib \ /usr/local/x11r5/lib \ /usr/lpp/Xamples/lib \ /lib/usr/lib/X11 \ \ /usr/openwin/lib \ /usr/openwin/share/lib \ ; \ do for ac_extension in a so sl; do if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f conftest* fi # $ac_x_libraries = NO if test "$ac_x_includes" = NO || test "$ac_x_libraries" = NO; then # Didn't find X anywhere. Cache the known absence of X. ac_cv_have_x="have_x=no" else # Record where we found X for the cache. ac_cv_have_x="have_x=yes \ ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries" fi fi fi eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then echo "$ac_t""$have_x" 1>&6 no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes \ ac_x_includes=$x_includes ac_x_libraries=$x_libraries" echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6 fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. cat >> confdefs.h <<\EOF #define X_DISPLAY_MISSING 1 EOF X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . case "`(uname -sr) 2>/dev/null`" in "SunOS 5"*) echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 echo "configure:2247: checking whether -R must be followed by a space" >&5 ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_nospace=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_R_nospace=no fi rm -f conftest* if test $ac_R_nospace = yes; then echo "$ac_t""no" 1>&6 X_LIBS="$X_LIBS -R$x_libraries" else LIBS="$ac_xsave_LIBS -R $x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_space=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_R_space=no fi rm -f conftest* if test $ac_R_space = yes; then echo "$ac_t""yes" 1>&6 X_LIBS="$X_LIBS -R $x_libraries" else echo "$ac_t""neither works" 1>&6 fi fi LIBS="$ac_xsave_LIBS" esac fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X # libraries were built with DECnet support. And karl@cs.umb.edu says # the Alpha needs dnet_stub (dnet does not exist). echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 echo "configure:2312: checking for dnet_ntoa in -ldnet" >&5 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" else echo "$ac_t""no" 1>&6 fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 echo "configure:2353: checking for dnet_ntoa in -ldnet_stub" >&5 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldnet_stub $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" else echo "$ac_t""no" 1>&6 fi fi # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to dickey@clark.net. echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 echo "configure:2401: checking for gethostbyname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostbyname(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) choke me #else gethostbyname(); #endif ; return 0; } EOF if { (eval echo configure:2429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_gethostbyname=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 fi if test $ac_cv_func_gethostbyname = no; then echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 echo "configure:2450: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" else echo "$ac_t""no" 1>&6 fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says simon@lia.di.epfl.ch: it contains # gethostby* variants that don't use the nameserver (or something). # -lsocket must be given before -lnsl if both are needed. # We assume that if connect needs -lnsl, so does gethostbyname. echo $ac_n "checking for connect""... $ac_c" 1>&6 echo "configure:2499: checking for connect" >&5 if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char connect(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_connect) || defined (__stub___connect) choke me #else connect(); #endif ; return 0; } EOF if { (eval echo configure:2527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_connect=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_connect=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 fi if test $ac_cv_func_connect = no; then echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 echo "configure:2548: checking for connect in -lsocket" >&5 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" else echo "$ac_t""no" 1>&6 fi fi # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. echo $ac_n "checking for remove""... $ac_c" 1>&6 echo "configure:2591: checking for remove" >&5 if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char remove(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_remove) || defined (__stub___remove) choke me #else remove(); #endif ; return 0; } EOF if { (eval echo configure:2619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_remove=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_remove=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 fi if test $ac_cv_func_remove = no; then echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 echo "configure:2640: checking for remove in -lposix" >&5 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lposix $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" else echo "$ac_t""no" 1>&6 fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. echo $ac_n "checking for shmat""... $ac_c" 1>&6 echo "configure:2683: checking for shmat" >&5 if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shmat(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shmat) || defined (__stub___shmat) choke me #else shmat(); #endif ; return 0; } EOF if { (eval echo configure:2711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_shmat=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_shmat=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 fi if test $ac_cv_func_shmat = no; then echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 echo "configure:2732: checking for shmat in -lipc" >&5 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lipc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" else echo "$ac_t""no" 1>&6 fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS="$LDFLAGS" test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 echo "configure:2784: checking for IceConnectionNumber in -lICE" >&5 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" else echo "$ac_t""no" 1>&6 fi LDFLAGS="$ac_save_LDFLAGS" fi CFLAGS="$CFLAGS $X_CFLAGS" CXXFLAGS="$CXXFLAGS $X_CFLAGS" LIBS="$LIBS $X_LIBS" # Check whether --with-opengl or --without-opengl was given. if test "${with_opengl+set}" = set; then withval="$with_opengl" OPENGL_SUPPORT=$withval else OPENGL_SUPPORT=yes fi if test x$OPENGL_SUPPORT \!= xno; then echo $ac_n "checking for OpenGL support in SDL""... $ac_c" 1>&6 echo "configure:2841: checking for OpenGL support in SDL" >&5 cat > conftest.$ac_ext < int main() { int foo() { int x = SDL_OPENGL; } ; return 0; } EOF if { (eval echo configure:2850: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* OPENGL_SUPPORT=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* OPENGL_SUPPORT=no fi rm -f conftest* echo "$ac_t""$OPENGL_SUPPORT" 1>&6 # Check for the GL libs if test x$OPENGL_SUPPORT \!= xno; then oldCPPFLAGS=$CPPFLAGS oldLIBS=$LIBS CPPFLAGS="$CPPFLAGS $X_CFLAGS" LIBS="$LIBS $SDL_LIBS" echo $ac_n "checking for glBegin in -lGL""... $ac_c" 1>&6 echo "configure:2868: checking for glBegin in -lGL" >&5 ac_lib_var=`echo GL'_'glBegin | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lGL $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_safe=`echo "GL/gl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for GL/gl.h""... $ac_c" 1>&6 echo "configure:2904: checking for GL/gl.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:2914: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 : else echo "$ac_t""no" 1>&6 OPENGL_SUPPORT=no fi else echo "$ac_t""no" 1>&6 OPENGL_SUPPORT=no fi LIBS=$oldLIBS CPPFLAGS=$oldCPPFLAGS fi fi if test x$OPENGL_SUPPORT \!= xno; then cat >> confdefs.h <<\EOF #define SDL_OPENGL_SUPPORT 1 EOF SDL_LIBS="$SDL_LIBS -lGL" fi CPPFLAGS=$OLD_CPPFLAGS if test x$JOYSTICK_SUPPORT \!= xno; then cat >> confdefs.h <<\EOF #define JOYSTICK_SUPPORT 1 EOF cat >> confdefs.h <&6 echo "configure:2975: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:3003: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done LIBS=$oldLIBS echo $ac_n "checking for x86 processor""... $ac_c" 1>&6 echo "configure:3030: checking for x86 processor" >&5 case $machtype in i?86|BePC) echo "$ac_t""yes" 1>&6 # Check whether --with-nasm or --without-nasm was given. if test "${with_nasm+set}" = set; then withval="$with_nasm" USENASM=$withval else USENASM=yes fi if test x$USENASM \!= xno; then # Extract the first word of "nasm", so it can be a program name with args. set dummy nasm; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:3046: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_NASM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$NASM"; then ac_cv_prog_NASM="$NASM" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_NASM="nasm" break fi done IFS="$ac_save_ifs" test -z "$ac_cv_prog_NASM" && ac_cv_prog_NASM="not found" fi fi NASM="$ac_cv_prog_NASM" if test -n "$NASM"; then echo "$ac_t""$NASM" 1>&6 else echo "$ac_t""no" 1>&6 fi if test x$NASM \!= "xnot found"; then echo $ac_n "checking for NASM object format""... $ac_c" 1>&6 echo "configure:3075: checking for NASM object format" >&5 cat >___DgSdFmTTeSt.asm <&5 then NASM_FMT=$FMT break fi done rm ___DgSdFmTTeSt* if test \! -z "$NASM_FMT"; then echo "$ac_t""$NASM_FMT" 1>&6 ASM=true if test x$NASM_FMT = xelf; then CHOP_="sed -e '/^_/s/^_//' -e '/_/s/\([][,.+ *:-]\)_/\1/g'" else CHOP_=cat fi if test x$NASM_FMT = xelf; then NO_USCORE_TRUE= NO_USCORE_FALSE='#' else NO_USCORE_TRUE='#' NO_USCORE_FALSE= fi # Check whether --with-mmx or --without-mmx was given. if test "${with_mmx+set}" = set; then withval="$with_mmx" USEMMX=$withval else USEMMX=yes fi echo $ac_n "checking for MMX""... $ac_c" 1>&6 echo "configure:3127: checking for MMX" >&5 cat >___DgSdMmXTeSt.asm <&5 ./___DgSdMmXTeSt MMXE=$? rm ___DgSdMmXTeSt* if test x$USEMMX \!= xno -a x$MMXE = x0; then MMX=true echo "$ac_t""yes" 1>&6 else MMX=false echo "$ac_t""no" 1>&6 fi else echo "$ac_t""not found" 1>&6 ASM=false MMX=false fi else ASM=false MMX=false fi else ASM=false MMX=false fi if test x$ASM = xfalse; then { echo "configure: error: *** NASM is necessary on x86 platforms for assembler optimizations. *** A package most likely came with your Unix distribution, but if one didn't, *** it can be found at http://www.web-sites.co.uk/nasm/ (or at *** http://www.bebits.com/ for BeOS) " 1>&2; exit 1; } fi ;; *) echo "$ac_t""no" 1>&6 ASM=false MMX=false ;; esac if $ASM; then EXTRAOBJS="$EXTRAOBJS asm_tiles.o ctv.o" cat >> confdefs.h <<\EOF #define ASM_TILES 1 EOF cat >> confdefs.h <<\EOF #define ASM_CTV 1 EOF if $MMX; then EXTRAOBJS="$EXTRAOBJS mmx_memcpy.o" cat >> confdefs.h <<\EOF #define MMX 1 EOF cat >> confdefs.h <<\EOF #define memcpy mmx_memcpy EOF else EXTRAOBJS="$EXTRAOBJS asm_memcpy.o" cat >> confdefs.h <<\EOF #define memcpy asm_memcpy EOF fi if test -f mz80/makez80.c; then CPUDIRS=mz80 MZ80="mz80/mz80.o" fi fi echo $ac_n "checking whether MZ80 is available""... $ac_c" 1>&6 echo "configure:3217: checking whether MZ80 is available" >&5 if test -z "$MZ80"; then echo "$ac_t""no" 1>&6 EXTRAOBJS="$EXTRAOBJS zz80.o" else echo "$ac_t""yes" 1>&6 fi # Check whether --with-star or --without-star was given. if test "${with_star+set}" = set; then withval="$with_star" USESTAR=$withval else USESTAR=yes fi # Check whether --with-musa or --without-musa was given. if test "${with_musa+set}" = set; then withval="$with_musa" USEMUSA=$withval else USEMUSA=yes fi echo $ac_n "checking whether StarScream is available""... $ac_c" 1>&6 echo "configure:3243: checking whether StarScream is available" >&5 if test x$ASM = xfalse -o \! -f star/star.c -o x$USESTAR = xno; then echo "$ac_t""no" 1>&6 if test x$USEMUSA = xno; then { echo "configure: error: *** You have disabled both CPU cores. You need at least one." 1>&2; exit 1; } fi CPUDIRS="$CPUDIRS musa" MUSA="-Lmusa -lmusa68" cat >> confdefs.h <<\EOF #define COMPILE_WITH_MUSA 1 EOF else echo "$ac_t""yes" 1>&6 if test x$USEMUSA \!= xno; then CPUDIRS="$CPUDIRS musa" MUSA="-Lmusa -lmusa68" cat >> confdefs.h <<\EOF #define COMPILE_WITH_MUSA 1 EOF fi CPUDIRS="$CPUDIRS star" STAR="star/starcpu.o" cat >> confdefs.h <<\EOF #define COMPILE_WITH_STAR 1 EOF fi trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. cat > conftest.defs <<\EOF s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g s%\[%\\&%g s%\]%\\&%g s%\$%$$%g EOF DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` rm -f conftest.defs # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo " Makefile star/Makefile musa/Makefile mz80/Makefile sdl/Makefile " | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@host@%$host%g s%@host_alias@%$host_alias%g s%@host_cpu@%$host_cpu%g s%@host_vendor@%$host_vendor%g s%@host_os@%$host_os%g s%@target@%$target%g s%@target_alias@%$target_alias%g s%@target_cpu@%$target_cpu%g s%@target_vendor@%$target_vendor%g s%@target_os@%$target_os%g s%@build@%$build%g s%@build_alias@%$build_alias%g s%@build_cpu@%$build_cpu%g s%@build_vendor@%$build_vendor%g s%@build_os@%$build_os%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@PACKAGE@%$PACKAGE%g s%@VERSION@%$VERSION%g s%@ACLOCAL@%$ACLOCAL%g s%@AUTOCONF@%$AUTOCONF%g s%@AUTOMAKE@%$AUTOMAKE%g s%@AUTOHEADER@%$AUTOHEADER%g s%@MAKEINFO@%$MAKEINFO%g s%@SET_MAKE@%$SET_MAKE%g s%@AWK@%$AWK%g s%@CC@%$CC%g s%@CPP@%$CPP%g s%@CXX@%$CXX%g s%@CXXCPP@%$CXXCPP%g s%@LN_S@%$LN_S%g s%@RANLIB@%$RANLIB%g s%@SDL_CONFIG@%$SDL_CONFIG%g s%@SDL_CFLAGS@%$SDL_CFLAGS%g s%@SDL_LIBS@%$SDL_LIBS%g s%@X_CFLAGS@%$X_CFLAGS%g s%@X_PRE_LIBS@%$X_PRE_LIBS%g s%@X_LIBS@%$X_LIBS%g s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g s%@NASM@%$NASM%g s%@NO_USCORE_TRUE@%$NO_USCORE_TRUE%g s%@NO_USCORE_FALSE@%$NO_USCORE_FALSE%g s%@INTERFACE@%$INTERFACE%g s%@NASM_FMT@%$NASM_FMT%g s%@CHOP_@%$CHOP_%g s%@CPUDIRS@%$CPUDIRS%g s%@MUSA@%$MUSA%g s%@STAR@%$STAR%g s%@MZ80@%$MZ80%g s%@EXTRAOBJS@%$EXTRAOBJS%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac case "$ac_given_INSTALL" in [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 dgen-sdl-1.23/configure.in 644 1750 1750 16562 7320137252 10621 dnl DGen/SDL v1.22 dnl At long last, the configure script! AC_INIT(decode.c) dnl We'll need machine type later AC_CANONICAL_SYSTEM machtype=$target_cpu AM_INIT_AUTOMAKE(dgen-sdl, 1.23) dnl Before we check for cc and c++, check for the --with-extra-opt switch, so dnl we can add the optimizations. AC_ARG_WITH(extra-opt, [ --with-extra-opt Add extra optimizations (egcs/GCC >= 2.95 only)], ADD_OPT=$withval, ADD_OPT=no) if test x$ADD_OPT \!= xno; then case $machtype in i?86) CFLAGS="$CFLAGS -O3 -mpentium -march=pentium -fstrength-reduce -fomit-frame-pointer -frerun-cse-after-loop -funroll-loops -ffast-math -malign-functions=5 -malign-jumps=5 -malign-loops=5 -malign-double -fno-exceptions -fno-rtti" CXXFLAGS="$CXXFLAGS -O3 -mpentium -march=pentium -fstrength-reduce -fomit-frame-pointer -frerun-cse-after-loop -funroll-loops -ffast-math -malign-functions=5 -malign-jumps=5 -malign-loops=5 -malign-double -fno-exceptions -fno-rtti" ;; *) CFLAGS="$CFLAGS -O3 -ffast-math -fomit-frame-pointer -fno-exceptions -fno-rtti -funroll-loops -frerun-cse-after-loop" CXXFLAGS="$CXXFLAGS -O3 -ffast-math -fomit-frame-pointer -fno-exceptions -fno-rtti -funroll-loops -frerun-cse-after-loop" ;; esac fi dnl Check for standard programs AC_PROG_AWK AC_PROG_CC AC_PROG_CPP AC_PROG_CXX AC_PROG_CXXCPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_RANLIB dnl Set the value of make, if make doesn't already AC_PROG_MAKE_SET dnl We're using C AC_LANG_C dnl Check endianness AC_C_BIGENDIAN dnl Check for SDL libs AM_PATH_SDL(1.0.0, true, AC_MSG_ERROR([*** SDL version >= 1.0.0 not found.])) CFLAGS="$CFLAGS $SDL_CFLAGS" CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" INTERFACE=sdl dnl Add SDL cflags to CPPFLAGS, just to check for SDL_joystick header OLD_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SDL_CFLAGS" EXTRAOBJS= dnl Check for SDL joystick JOYSTICK_SUPPORT=no AC_CHECK_HEADER(SDL_joystick.h, JOYSTICK_SUPPORT=SDL, dnl Check for Linux joystick as a backup AC_CHECK_HEADER(linux/joystick.h, JOYSTICK_SUPPORT=LINUX)) dnl Check for X (so we can find the OpenGL headers) AC_PATH_XTRA CFLAGS="$CFLAGS $X_CFLAGS" CXXFLAGS="$CXXFLAGS $X_CFLAGS" LIBS="$LIBS $X_LIBS" dnl Check for OpenGL support in SDL AC_ARG_WITH(opengl, [ --without-opengl Don't use SDL OpenGL support], OPENGL_SUPPORT=$withval, OPENGL_SUPPORT=yes) if test x$OPENGL_SUPPORT \!= xno; then AC_MSG_CHECKING([for OpenGL support in SDL]) AC_TRY_COMPILE([#include ], [int foo() { int x = SDL_OPENGL; }], OPENGL_SUPPORT=yes, OPENGL_SUPPORT=no) AC_MSG_RESULT($OPENGL_SUPPORT) # Check for the GL libs if test x$OPENGL_SUPPORT \!= xno; then oldCPPFLAGS=$CPPFLAGS oldLIBS=$LIBS CPPFLAGS="$CPPFLAGS $X_CFLAGS" LIBS="$LIBS $SDL_LIBS" AC_CHECK_LIB(GL, glBegin, AC_CHECK_HEADER(GL/gl.h, , OPENGL_SUPPORT=no), OPENGL_SUPPORT=no ) LIBS=$oldLIBS CPPFLAGS=$oldCPPFLAGS fi fi if test x$OPENGL_SUPPORT \!= xno; then AC_DEFINE(SDL_OPENGL_SUPPORT) SDL_LIBS="$SDL_LIBS -lGL" fi CPPFLAGS=$OLD_CPPFLAGS if test x$JOYSTICK_SUPPORT \!= xno; then AC_DEFINE(JOYSTICK_SUPPORT) AC_DEFINE_UNQUOTED(${JOYSTICK_SUPPORT}_JOYSTICK_SUPPORT) EXTRAOBJS="$EXTRAOBJS md-phil.o" fi oldLIBS=$LIBS LIBS="$LIBS $SDL_LIBS" dnl Check for the SDL_WM_ToggleFullScreen function AC_CHECK_FUNCS(SDL_WM_ToggleFullScreen) LIBS=$oldLIBS dnl Check for an Intel chip AC_MSG_CHECKING([for x86 processor]) case $machtype in i?86|BePC) AC_MSG_RESULT([yes]) dnl Check if the user explicitly asked to not use nasm AC_ARG_WITH(nasm, [ --without-nasm Don't use NASM for assembler routines], USENASM=$withval, USENASM=yes) if test x$USENASM \!= xno; then dnl Check for NASM AC_CHECK_PROG(NASM, nasm, nasm, [not found]) if test x$NASM \!= "xnot found"; then dnl Find NASM object format AC_MSG_CHECKING([for NASM object format]) cat >___DgSdFmTTeSt.asm <&5 then NASM_FMT=$FMT break fi done rm ___DgSdFmTTeSt* if test \! -z "$NASM_FMT"; then AC_MSG_RESULT([$NASM_FMT]) ASM=true dnl ELF doesn't use underscores, aout&coff do if test x$NASM_FMT = xelf; then changequote(<<,>>) CHOP_="sed -e '/^_/s/^_//' -e '/_/s/\([][,.+ *:-]\)_/\1/g'" changequote([,]) else CHOP_=cat fi AM_CONDITIONAL(NO_USCORE, test x$NASM_FMT = xelf) dnl Check for MMX AC_ARG_WITH(mmx, [ --without-mmx Don't use MMX routines, even if supported], USEMMX=$withval, USEMMX=yes) AC_MSG_CHECKING([for MMX]) cat >___DgSdMmXTeSt.asm <&5 ./___DgSdMmXTeSt MMXE=$? rm ___DgSdMmXTeSt* if test x$USEMMX \!= xno -a x$MMXE = x0; then MMX=true AC_MSG_RESULT([yes]) else MMX=false AC_MSG_RESULT([no]) fi else AC_MSG_RESULT([not found]) ASM=false MMX=false fi else ASM=false MMX=false fi else ASM=false MMX=false fi if test x$ASM = xfalse; then AC_MSG_ERROR([ *** NASM is necessary on x86 platforms for assembler optimizations. *** A package most likely came with your Unix distribution, but if one didn't, *** it can be found at http://www.web-sites.co.uk/nasm/ (or at *** http://www.bebits.com/ for BeOS) ]) fi ;; *) AC_MSG_RESULT([no]) ASM=false MMX=false ;; esac dnl We are free to use assembler! :) if $ASM; then EXTRAOBJS="$EXTRAOBJS asm_tiles.o ctv.o" AC_DEFINE(ASM_TILES) AC_DEFINE(ASM_CTV) if $MMX; then EXTRAOBJS="$EXTRAOBJS mmx_memcpy.o" AC_DEFINE(MMX) AC_DEFINE(memcpy, mmx_memcpy) else EXTRAOBJS="$EXTRAOBJS asm_memcpy.o" AC_DEFINE(memcpy, asm_memcpy) fi if test -f mz80/makez80.c; then CPUDIRS=mz80 MZ80="mz80/mz80.o" fi fi dnl Use ZZ80 if MZ80 isn't here AC_MSG_CHECKING([whether MZ80 is available]) if test -z "$MZ80"; then AC_MSG_RESULT([no]) EXTRAOBJS="$EXTRAOBJS zz80.o" else AC_MSG_RESULT([yes]) fi dnl Figure out what emus we're using (StarScream, Musashi, or both) AC_ARG_WITH(star, [ --without-star Don't use StarScream assembler CPU core if available], USESTAR=$withval, USESTAR=yes) AC_ARG_WITH(musa, [ --without-musa Don't use Musashi C CPU core], USEMUSA=$withval, USEMUSA=yes) AC_MSG_CHECKING([whether StarScream is available]) if test x$ASM = xfalse -o \! -f star/star.c -o x$USESTAR = xno; then AC_MSG_RESULT([no]) dnl We have to use musa if test x$USEMUSA = xno; then AC_MSG_ERROR([*** You have disabled both CPU cores. You need at least one.]) fi CPUDIRS="$CPUDIRS musa" MUSA="-Lmusa -lmusa68" AC_DEFINE(COMPILE_WITH_MUSA) else AC_MSG_RESULT([yes]) if test x$USEMUSA \!= xno; then CPUDIRS="$CPUDIRS musa" MUSA="-Lmusa -lmusa68" AC_DEFINE(COMPILE_WITH_MUSA) fi CPUDIRS="$CPUDIRS star" STAR="star/starcpu.o" AC_DEFINE(COMPILE_WITH_STAR) fi dnl Output variables AC_SUBST(INTERFACE) AC_SUBST(NASM) AC_SUBST(NASM_FMT) AC_SUBST(CHOP_) AC_SUBST(CPUDIRS) AC_SUBST(MUSA) AC_SUBST(STAR) AC_SUBST(MZ80) AC_SUBST(EXTRAOBJS) dnl Done! AC_OUTPUT([ Makefile star/Makefile musa/Makefile mz80/Makefile sdl/Makefile ]) dgen-sdl-1.23/install-sh 755 1750 1750 12736 7027317554 10324 #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 dgen-sdl-1.23/missing 755 1750 1750 14213 7027317555 7710 #! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright (C) 1996, 1997 Free Software Foundation, Inc. # Franc,ois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing - GNU libit 0.0" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`configure.in'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`configure.in'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`configure.in'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 dgen-sdl-1.23/mkinstalldirs 755 1750 1750 1322 7027317555 11074 #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here dgen-sdl-1.23/rc.cpp 644 1750 1750 31773 7320151253 7416 // This parses the RC file. #include #include #include #include #include #include #include "rc.h" #include "pd-defs.h" #include "md-phil.h" // CTV names char *ctv_names[NUM_CTV] = { "off", "blur", "scanline", "interlace" }; // The table of strings and the keysyms they map to. // The order is a bit weird, since this was originally a mapping for the SVGALib // scancodes, and I just added the SDL stuff on top of it. struct rc_keysym { char *name; long keysym; } keysyms[] = { { "ESCAPE", PDK_ESCAPE }, { "1", PDK_1 }, { "2", PDK_2 }, { "3", PDK_3 }, { "4", PDK_4 }, { "5", PDK_5 }, { "6", PDK_6 }, { "7", PDK_7 }, { "8", PDK_8 }, { "9", PDK_9 }, { "0", PDK_0 }, { "-", PDK_MINUS }, { "=", PDK_EQUALS }, { "+", PDK_EQUALS }, { "BACKSPACE", PDK_BACKSPACE }, { "TAB", PDK_TAB }, { "Q", PDK_q }, { "W", PDK_w }, { "E", PDK_e }, { "R", PDK_r }, { "T", PDK_t }, { "Y", PDK_y }, { "U", PDK_u }, { "I", PDK_i }, { "O", PDK_o }, { "P", PDK_p }, { "[", PDK_LEFTBRACKET }, { "{", PDK_LEFTBRACKET }, { "]", PDK_RIGHTBRACKET }, { "}", PDK_RIGHTBRACKET }, { "RETURN", PDK_RETURN }, { "ENTER", PDK_RETURN }, { "A", PDK_a }, { "S", PDK_s }, { "D", PDK_d }, { "F", PDK_f }, { "G", PDK_g }, { "H", PDK_h }, { "J", PDK_j }, { "K", PDK_k }, { "L", PDK_l }, { ";", PDK_SEMICOLON }, { ":", PDK_SEMICOLON }, { "'", PDK_QUOTE }, { "\"", PDK_QUOTE }, { "`", PDK_BACKQUOTE }, { "~", PDK_BACKQUOTE }, { "\\", PDK_BACKSLASH }, { "|", PDK_BACKSLASH }, { "Z", PDK_z }, { "X", PDK_x }, { "C", PDK_c }, { "V", PDK_v }, { "B", PDK_b }, { "N", PDK_n }, { "M", PDK_m }, { ",", PDK_COMMA }, { "<", PDK_COMMA }, { ".", PDK_PERIOD }, { ">", PDK_PERIOD }, { "/", PDK_SLASH }, { "?", PDK_SLASH }, { "KP_MULTIPLY", PDK_KP_MULTIPLY }, { "SPACE", PDK_SPACE }, { "F1", PDK_F1 }, { "F2", PDK_F2 }, { "F3", PDK_F3 }, { "F4", PDK_F4 }, { "F5", PDK_F5 }, { "F6", PDK_F6 }, { "F7", PDK_F7 }, { "F8", PDK_F8 }, { "F9", PDK_F9 }, { "F10", PDK_F10 }, { "KP_7", PDK_KP7 }, { "KP_HOME", PDK_KP7 }, { "KP_8", PDK_KP8 }, { "KP_UP", PDK_KP8 }, { "KP_9", PDK_KP9 }, { "KP_PAGE_UP", PDK_KP9 }, { "KP_PAGEUP", PDK_KP9 }, { "KP_MINUS", PDK_KP_MINUS }, { "KP_4", PDK_KP4 }, { "KP_LEFT", PDK_KP4 }, { "KP_5", PDK_KP5 }, { "KP_6", PDK_KP6 }, { "KP_RIGHT", PDK_KP6 }, { "KP_PLUS", PDK_KP_PLUS }, { "KP_1", PDK_KP1 }, { "KP_END", PDK_KP1 }, { "KP_2", PDK_KP2 }, { "KP_DOWN", PDK_KP2 }, { "KP_3", PDK_KP3 }, { "KP_PAGE_DOWN", PDK_KP3 }, { "KP_PAGEDOWN", PDK_KP3 }, { "KP_0", PDK_KP0 }, { "KP_INSERT", PDK_KP0 }, { "KP_PERIOD", PDK_KP_PERIOD }, { "KP_DELETE", PDK_KP_PERIOD }, { "F11", PDK_F11 }, { "F12", PDK_F12 }, { "KP_ENTER", PDK_KP_ENTER }, { "KP_DIVIDE", PDK_KP_DIVIDE }, { "HOME", PDK_HOME }, { "UP", PDK_UP }, { "PAGE_UP", PDK_PAGEUP }, { "PAGEUP", PDK_PAGEUP }, { "LEFT", PDK_LEFT }, { "RIGHT", PDK_RIGHT }, { "END", PDK_END }, { "DOWN", PDK_DOWN }, { "PAGE_DOWN", PDK_PAGEDOWN }, { "PAGEDOWN", PDK_PAGEDOWN }, { "INSERT", PDK_INSERT }, { "DELETE", PDK_DELETE }, { "NUMLOCK", PDK_NUMLOCK }, { "NUM_LOCK", PDK_NUMLOCK }, { "CAPSLOCK", PDK_CAPSLOCK }, { "CAPS_LOCK", PDK_CAPSLOCK }, { "SCROLLOCK", PDK_SCROLLOCK }, { "SCROLL_LOCK", PDK_SCROLLOCK }, { "LSHIFT", PDK_LSHIFT }, { "SHIFT_L", PDK_LSHIFT }, { "RSHIFT", PDK_RSHIFT }, { "SHIFT_R", PDK_RSHIFT }, { "LCTRL", PDK_LCTRL }, { "CTRL_L", PDK_LCTRL }, { "RCTRL", PDK_RCTRL }, { "CTRL_R", PDK_RCTRL }, { "LALT", PDK_LALT }, { "ALT_L", PDK_LALT }, { "RALT", PDK_RALT }, { "ALT_R", PDK_RALT }, { "LMETA", PDK_LMETA }, { "META_L", PDK_LMETA }, { "RMETA", PDK_RMETA }, { "META_R", PDK_RMETA }, { NULL, 0 } // Terminator }; // Phew! ;) /* Define all the external RC variables */ #include "rc-vars.h" long js_map_button[2][16] = { { MD_A_MASK, MD_C_MASK, MD_A_MASK, MD_B_MASK, MD_Y_MASK, MD_Z_MASK, MD_X_MASK, MD_X_MASK, MD_START_MASK, MD_MODE_MASK, 0, 0, 0, 0, 0, 0 }, { MD_A_MASK, MD_C_MASK, MD_A_MASK, MD_B_MASK, MD_Y_MASK, MD_Z_MASK, MD_X_MASK, MD_X_MASK, MD_START_MASK, MD_MODE_MASK, 0, 0, 0, 0, 0, 0 } }; /* Parse a keysym. * If the string matches one of the strings in the keysym table above, * return the keysym, otherwise -1. */ static long keysym(const char *code) { struct rc_keysym *s = keysyms; long r = 0; // Check for modifier prefixes shift-, ctrl-, alt-, meta- for(;;) { if(!strncasecmp("shift-", code, 6)) { r |= KEYSYM_MOD_SHIFT; code += 6; continue; } if(!strncasecmp("ctrl-", code, 5)) { r |= KEYSYM_MOD_CTRL; code += 5; continue; } if(!strncasecmp("alt-", code, 4)) { r |= KEYSYM_MOD_ALT; code += 4; continue; } if(!strncasecmp("meta-", code, 5)) { r |= KEYSYM_MOD_META; code += 5; continue; } break; } do { if(!strcasecmp(s->name, code)) return r |= s->keysym; } while ((++s)->name); /* No match */ return -1; } /* Parse a boolean value. * If the string is "yes" or "true", return 1. * If the string is "no" or "false", return 0. * Otherwise, just return atoi(value). */ static long boolean(const char *value) { if(!strcasecmp(value, "yes") || !strcasecmp(value, "true")) return 1; if(!strcasecmp(value, "no") || !strcasecmp(value, "false")) return 0; return atoi(value); } // Made GCC happy about unused things when we don't want a joystick. :) [PKH] // Cheesy hack to set joystick mappings from the RC file. [PKH] static long jsmap(const char *value) { if(!strcasecmp(value, "mode")) snprintf((char*)value, 2, "%c", 'm'); if(!strcasecmp(value, "start")) snprintf((char*)value, 2, "%c", 's'); switch(*value) { case 'A': case 'a': return(MD_A_MASK); break; case 'B': case 'b': return(MD_B_MASK); break; case 'C': case 'c': return(MD_C_MASK); break; case 'X': case 'x': return(MD_X_MASK); break; case 'Y': case 'y': return(MD_Y_MASK); break; case 'Z': case 'z': return(MD_Z_MASK); break; case 'M': case 'm': return(MD_MODE_MASK); break; case 'S': case 's': return(MD_START_MASK); break; default: return(0); } } /* Parse the CTV type. As new CTV filters get submitted expect this to grow ;) * Current values are: * off - No CTV * blur - blur bitmap (from DirectX DGen), by Dave * scanline - attenuates every other line, looks cool! by Phillip K. Hornung */ static long ctv(const char *value) { for(int i = 0; i < NUM_CTV; ++i) if(!strcasecmp(value, ctv_names[i])) return i; return -1; } static long number(const char *value) { return atoi(value); } /* This is a table of all the RC options, the variables they affect, and the * functions to parse their values. */ struct rc_field { char *fieldname; long (*parser)(const char*); long *variable; } rc_fields[] = { { "key_pad1_up", keysym, &pad1_up }, { "key_pad1_down", keysym, &pad1_down }, { "key_pad1_left", keysym, &pad1_left }, { "key_pad1_right", keysym, &pad1_right }, { "key_pad1_a", keysym, &pad1_a }, { "key_pad1_b", keysym, &pad1_b }, { "key_pad1_c", keysym, &pad1_c }, { "key_pad1_x", keysym, &pad1_x }, { "key_pad1_y", keysym, &pad1_y }, { "key_pad1_z", keysym, &pad1_z }, { "key_pad1_mode", keysym, &pad1_mode }, { "key_pad1_start", keysym, &pad1_start }, { "key_pad2_up", keysym, &pad2_up }, { "key_pad2_down", keysym, &pad2_down }, { "key_pad2_left", keysym, &pad2_left }, { "key_pad2_right", keysym, &pad2_right }, { "key_pad2_a", keysym, &pad2_a }, { "key_pad2_b", keysym, &pad2_b }, { "key_pad2_c", keysym, &pad2_c }, { "key_pad2_x", keysym, &pad2_x }, { "key_pad2_y", keysym, &pad2_y }, { "key_pad2_z", keysym, &pad2_z }, { "key_pad2_mode", keysym, &pad2_mode }, { "key_pad2_start", keysym, &pad2_start }, { "key_fix_checksum", keysym, &dgen_fix_checksum }, { "key_quit", keysym, &dgen_quit }, { "key_splitscreen_toggle", keysym, &dgen_splitscreen_toggle }, { "key_craptv_toggle", keysym, &dgen_craptv_toggle }, { "key_screenshot", keysym, &dgen_screenshot }, { "key_reset", keysym, &dgen_reset }, { "key_slot_0", keysym, &dgen_slot_0 }, { "key_slot_1", keysym, &dgen_slot_1 }, { "key_slot_2", keysym, &dgen_slot_2 }, { "key_slot_3", keysym, &dgen_slot_3 }, { "key_slot_4", keysym, &dgen_slot_4 }, { "key_slot_5", keysym, &dgen_slot_5 }, { "key_slot_6", keysym, &dgen_slot_6 }, { "key_slot_7", keysym, &dgen_slot_7 }, { "key_slot_8", keysym, &dgen_slot_8 }, { "key_slot_9", keysym, &dgen_slot_9 }, { "key_save", keysym, &dgen_save }, { "key_load", keysym, &dgen_load }, { "key_cpu_toggle", keysym, &dgen_cpu_toggle }, { "key_stop", keysym, &dgen_stop }, { "key_fullscreen_toggle", keysym, &dgen_fullscreen_toggle }, { "bool_splitscreen_startup", boolean, &dgen_splitscreen_startup }, { "bool_autoload", boolean, &dgen_autoload }, { "bool_autosave", boolean, &dgen_autosave }, { "bool_frameskip", boolean, &dgen_frameskip }, { "bool_show_carthead", boolean, &dgen_show_carthead }, { "ctv_craptv_startup", ctv, &dgen_craptv }, { "bool_sound", boolean, &dgen_sound }, { "int_soundrate", number, &dgen_soundrate }, { "bool_16bit", boolean, &dgen_16bit }, { "int_soundsegs", number, &dgen_soundsegs }, { "int_nice", number, &dgen_nice }, { "bool_fullscreen", boolean, &dgen_fullscreen }, { "int_scale", number, &dgen_scale }, { "bool_opengl", boolean, &dgen_opengl }, { "int_opengl_width", number, &dgen_opengl_width }, { "int_opengl_height", number, &dgen_opengl_height }, { "bool_joystick", boolean, &dgen_joystick }, { "joypad1_b0", jsmap, &js_map_button[0][0] }, { "joypad1_b1", jsmap, &js_map_button[0][1] }, { "joypad1_b2", jsmap, &js_map_button[0][2] }, { "joypad1_b3", jsmap, &js_map_button[0][3] }, { "joypad1_b4", jsmap, &js_map_button[0][4] }, { "joypad1_b5", jsmap, &js_map_button[0][5] }, { "joypad1_b6", jsmap, &js_map_button[0][6] }, { "joypad1_b7", jsmap, &js_map_button[0][7] }, { "joypad1_b8", jsmap, &js_map_button[0][8] }, { "joypad1_b9", jsmap, &js_map_button[0][9] }, { "joypad1_b10", jsmap, &js_map_button[0][10] }, { "joypad1_b11", jsmap, &js_map_button[0][11] }, { "joypad1_b12", jsmap, &js_map_button[0][12] }, { "joypad1_b13", jsmap, &js_map_button[0][13] }, { "joypad1_b14", jsmap, &js_map_button[0][14] }, { "joypad1_b15", jsmap, &js_map_button[0][15] }, { "joypad2_b0", jsmap, &js_map_button[1][0] }, { "joypad2_b1", jsmap, &js_map_button[1][1] }, { "joypad2_b2", jsmap, &js_map_button[1][2] }, { "joypad2_b3", jsmap, &js_map_button[1][3] }, { "joypad2_b4", jsmap, &js_map_button[1][4] }, { "joypad2_b5", jsmap, &js_map_button[1][5] }, { "joypad2_b6", jsmap, &js_map_button[1][6] }, { "joypad2_b7", jsmap, &js_map_button[1][7] }, { "joypad2_b8", jsmap, &js_map_button[1][8] }, { "joypad2_b9", jsmap, &js_map_button[1][9] }, { "joypad2_b10", jsmap, &js_map_button[1][10] }, { "joypad2_b11", jsmap, &js_map_button[1][11] }, { "joypad2_b12", jsmap, &js_map_button[1][12] }, { "joypad2_b13", jsmap, &js_map_button[1][13] }, { "joypad2_b14", jsmap, &js_map_button[1][14] }, { "joypad2_b15", jsmap, &js_map_button[1][15] }, { NULL, NULL, NULL } // Terminator }; /* Parse the rc file */ void parse_rc(const char *file) { FILE *rc; char temp[1024] = "", line[2048] = "", field[1024] = "", value[1024] = ""; /* If the filename is NULL, use default of $HOME/.dgen/dgenrc */ if(!file) { strncat(temp, getenv("HOME"), 1023); strncat(temp, "/.dgen/dgenrc", 1023 - strlen(temp)); file = temp; } /* Open the file. If it's "-", open standard input instead. */ rc = fopen(file, "r"); if(!rc) { fprintf(stderr, "rc: Couldn't open rc file %s, trying to create\n", file); strncat(field, getenv("HOME"), 1023); strncat(field, "/.dgen", 1023 - strlen(field)); mkdir(field, 0777); /* Create the .dgen directory */ rc = fopen(file, "w"); if(!rc) { fprintf(stderr, "rc: Couldn't create rc file %s!\n", file); return; } fclose(rc); fopen(file, "r"); return; } while(fgets(line, 2047, rc)) { struct rc_field *s; s = rc_fields; /* If it starts with hash (#) or is blank, we have a comment */ if(*line == '#' || *line == '\0' || *line == '\n') continue; /* Each line is in the format field=value */ sscanf(line, " %s = %s", field, value); /* Check field against all supported fields */ do { if(!strcasecmp(s->fieldname, field)) { int potential; potential = (*(s->parser))(value); /* If we got a bad value, discard and warn user */ if(potential == -1) fprintf(stderr, "rc: Invalid RC value for %s: %s\n", field, value); else *(s->variable) = potential; break; } } while((++s)->fieldname); // If we reached the end of the table, bad field, bad line if(!s->fieldname) fprintf(stderr, "rc: Invalid RC line: %s", line); } fclose(rc); return; } dgen-sdl-1.23/romload.c 644 1750 1750 11375 7232423013 10101 // DGen/SDL v1.15+ // Module for loading in the different rom image types (.bin/.smd) #include #include #include #include #include static int load_bin_into(char *name,unsigned char *into) { FILE *hand=NULL; int file_size=0; hand=fopen(name,"rb"); if (hand==NULL) return -1; fseek(hand,0,SEEK_END); file_size=ftell(hand); fseek(hand,0,SEEK_SET); if (into==NULL) return file_size; fread(into,1,file_size,hand); fclose(hand); return 0; } /* WHAT YOU FIND IN THE 512 BYTES HEADER: 0: Number of blocks 1 1: H03 * 2: SPLIT? 2 8: HAA * 9: HBB * ALL OTHER BYTES: H00 1: This first byte should have the number of 16KB blocks the rom has. The header isn't part of the formula, so this number is: [size of rom-512]/16386 If the size is more than 255, the value should be H00. 2: This byte indicates if the ROM is a part of a splitted rom series. If the rom is the last part of the series (or isn't a splitted rom at all), this byte should be H00. In other cases should be H40. See "CREATING SPLITTED ROMS" for details on this format. */ // 16k chunks, even bytes first then odd static int load_smd_into(char *name,unsigned char *into) { unsigned char head[512]={0}; FILE *hand=NULL; int chunk_count=0,file_chunks=0; int file_size=0; unsigned char *chunk_buf=NULL; int got_to=0,i; hand=fopen(name,"rb"); if (hand==NULL) return -1; fseek(hand,0,SEEK_END); file_size=ftell(hand); fseek(hand,0,SEEK_SET); if (fread(head,1,512,hand)!=512) { fclose(hand); return -1; } //chunk_count=head[0]; // Sometimes header is wrong apparently file_chunks=((file_size-512)/16384); chunk_count=file_chunks; //if (chunk_count>file_chunks) chunk_count=file_chunks; if (into==NULL) return (chunk_count*16384); chunk_buf=malloc(16384); if (chunk_buf==NULL) {printf ("out of mem\n"); fclose(hand); return -1;} for (got_to=0,i=0; i %s", name, temp2); /* If gzip returned an error, stop */ if(system(temp)) { remove(temp2); return -1; }; /* Recurse with the new file */ len = load_rom_into(temp2, into); remove(temp2); sync(); return len; } /* Do bzip2 also */ if(magicbuf[0] == 'B' && magicbuf[1] == 'Z' && magicbuf[2] == 'h') { /* Damn, this looks almost like the gzip stuff above. *lol* :) */ char temp[0x100], temp2[0x80]; srand(time(NULL)); /* Go through bzip2 */ sprintf(temp2, "/tmp/dgenrom_%d_%d", rand(), rand()); sprintf(temp, "bzip2 -cd %s > %s", name, temp2); /* If we got an error, stop */ if(system(temp)) { remove(temp2); return -1; }; /* Recurse with the uncompressed file */ len = load_rom_into(temp2, into); remove(temp2); sync(); return len; } /* Next check for SMD magic */ if(magicbuf[8] == 0xaa && magicbuf[9] == 0xbb) format = 1; /* Otherwise we can only hope it's binary */ else format = 0; switch (format) { case 1: return load_smd_into(name,into); default: return load_bin_into(name,into); } return -1; } dgen-sdl-1.23/md.cpp 644 1750 1750 41747 7232431163 7417 // DGen/SDL v1.17+ // Megadrive C++ module #include #include #include #include "md.h" // This is the 'static' StarScream/MZ80 multitasker // which detects which megadrive is active (by which star_mz80_on() has been called // and forwards to the appropriate misc_read/writebyte/word/z80 function // of the appropriate instance (grrrr - bloody C++) static md* which=0; int md::star_mz80_on() { #ifdef COMPILE_WITH_STAR s68000SetContext(&cpu); #endif mz80SetContext(&z80); which=this; return 0; } int md::star_mz80_off() { which=0; #ifdef COMPILE_WITH_STAR s68000GetContext(&cpu); #endif mz80GetContext(&z80); return 0; } extern "C" { unsigned root_readbyte(unsigned a) { if (which) return which->misc_readbyte(a); else return 0x00; } unsigned root_readword(unsigned a) { if (which) return which->misc_readword(a); else return 0x0000; } unsigned root_readlong(unsigned a) { return (root_readword(a)<<16)+root_readword(a+2); } void root_writebyte(unsigned a,unsigned d) { if (which) which->misc_writebyte(a,d); } void root_writeword(unsigned a,unsigned d) { if (which) which->misc_writeword(a,d); } void root_writelong(unsigned a,unsigned d) { root_writeword(a,(d>>16)&0xffff); root_writeword(a+2,d&0xffff); } } #ifdef COMPILE_WITH_MUSA // Okay: a bit for MUSASHI extern "C" { // read/write functions called by the CPU to access memory. // while values used are 32 bits, only the appropriate number // of bits are relevant (i.e. in write_memory_8, only the lower 8 bits // of value should be written to memory). // address will be a 24-bit value. /* Read from anywhere */ int m68k_read_memory_8(int address) { return root_readbyte(address); } int m68k_read_memory_16(int address) { return root_readword(address); } int m68k_read_memory_32(int address) { return root_readlong(address); } /* Read data immediately following the PC */ int m68k_read_immediate_8(int address) { return root_readbyte(address); } int m68k_read_immediate_16(int address) { return root_readword(address); } int m68k_read_immediate_32(int address) { return root_readlong(address); } /* Read an instruction (16-bit word immeditately after PC) */ int m68k_read_instruction(int address) { return root_readword(address); } /* Write to anywhere */ void m68k_write_memory_8(int address, int value) { root_writebyte(address,value); } void m68k_write_memory_16(int address, int value) { root_writeword(address,value); } void m68k_write_memory_32(int address, int value) { root_writelong(address,value); } } #endif // The same thing for 68KEM #ifdef COMPILE_WITH_M68KEM extern "C" { int cpu_readmem24(int address) { return root_readbyte(address); } int cpu_readmem24_word(int address) { return root_readword(address); } int cpu_readmem24_dword(int address) { return root_readlong(address); } void cpu_writemem24(int address, int val) { root_writebyte(address, val); } void cpu_writemem24_word(int address, int val) { root_writeword(address, val); } void cpu_writemem24_dword(int address, int val) { root_writelong(address, val); } unsigned char *OP_ROM, *OP_RAM; void cpu_setOPbase24(int pc) { if(!which) return; // star_mz80_on() wasn't called! :0 if (pc < 0xa00000) // ROM area OP_ROM = which->rom; if (pc >= 0xe00000) // RAM OP_ROM = which->ram - (pc & 0xff0000); } } #endif UINT8 root_z80_read(UINT32 a,struct MemoryReadByte *huh) { (void)(huh); if (which) return which->z80_read(a); return 0x00; } void root_z80_write(UINT32 a,UINT8 d,struct MemoryWriteByte *huh) { (void)(huh); if (which) which->z80_write(a,d); } UINT16 root_z80_port_read(UINT16 a, struct z80PortRead *huh) { (void)(huh); if (which) return which->z80_port_read(a); return 0x0000; } void root_z80_port_write(UINT16 a,UINT8 d, struct z80PortWrite *huh) { (void)(huh); if (which) which->z80_port_write(a,d); } extern FILE *debug_log; extern "C" { int mega_dacout=0,mega_dacen=0; } #ifdef COMPILE_WITH_STAR int md::memory_map() { int i=0,j=0; int rommax=romlen; if (rommax>0xa00000) rommax=0xa00000; if (rommax<0) rommax=0; // FETCH: Set up 2 or 3 FETCH sections i=0; if (rommax>0) { fetch[i].lowaddr=0x000000; fetch[i].highaddr=rommax-1; fetch[i].offset=(unsigned)rom-0x000000; i++; } fetch[i].lowaddr=0xff0000; fetch[i].highaddr=0xffffff; fetch[i].offset=(unsigned)ram- 0xff0000; i++; // Testing fetch[i].lowaddr=0xffff0000; fetch[i].highaddr=0xffffffff; fetch[i].offset=(unsigned)ram-0xffff0000; i++; // Testing 2 fetch[i].lowaddr=0xff000000; fetch[i].highaddr=0xff000000+rommax-1; fetch[i].offset=(unsigned)rom-0xff000000; i++; fetch[i].lowaddr=fetch[i].highaddr=0xffffffff; fetch[i].offset=0; i++; if (debug_log!=NULL) fprintf (debug_log,"StarScream memory_map has %d fetch sections\n",i); i=0; j=0; #if 0 // Simple version *************** readbyte[i].lowaddr= readword[i].lowaddr= writebyte[j].lowaddr= writeword[j].lowaddr= 0; readbyte[i].highaddr= readword[i].highaddr= writebyte[j].highaddr= writeword[j].highaddr= 0xffffffff; readbyte[i].memorycall=(void *) root_readbyte; readword[i].memorycall=(void *) root_readword; writebyte[j].memorycall=(void *)root_writebyte; writeword[j].memorycall=(void *)root_writeword; readbyte[i].userdata= readword[i].userdata= writebyte[j].userdata= writeword[j].userdata= NULL; i++; j++; // Simple version end *************** #else // Faster version *************** // IO: Set up 3/4 read sections, and 2/3 write sections if (rommax>0) { // Cartridge save RAM memory if(save_len) { readbyte[i].lowaddr= readword[i].lowaddr= writebyte[j].lowaddr= writeword[j].lowaddr= save_start; readbyte[i].highaddr= readword[i].highaddr= writebyte[j].highaddr= writeword[j].highaddr= save_start+save_len-1; readbyte[i].memorycall= (void*)root_readbyte; readword[j].memorycall= (void*)root_readword; writebyte[i].memorycall=(void*)root_writebyte; writeword[j].memorycall=(void*)root_writeword; readbyte[i].userdata= readword[i].userdata= writebyte[j].userdata= writeword[j].userdata= NULL; i++; j++; } // Cartridge ROM memory (read only) readbyte[i].lowaddr= readword[i].lowaddr= 0x000000; readbyte[i].highaddr= readword[i].highaddr= rommax-1; readbyte[i].memorycall=readword[i].memorycall=NULL; readbyte[i].userdata= readword[i].userdata= rom; i++; // misc memory (e.g. aoo and coo) through root_rw readbyte[i].lowaddr= readword[i].lowaddr= writebyte[j].lowaddr= writeword[j].lowaddr= rommax; } else readbyte[i].lowaddr= readword[i].lowaddr= writebyte[j].lowaddr= writeword[j].lowaddr= 0; readbyte[i].highaddr= readword[i].highaddr= writebyte[j].highaddr= writeword[j].highaddr= 0xfeffff; readbyte[i].memorycall=(void *) root_readbyte; readword[i].memorycall=(void *) root_readword; writebyte[j].memorycall=(void *)root_writebyte; writeword[j].memorycall=(void *)root_writeword; readbyte[i].userdata= readword[i].userdata= writebyte[j].userdata= writeword[j].userdata= NULL; i++; j++; // scratch RAM memory readbyte[i].lowaddr = readword[i].lowaddr = writebyte[j].lowaddr = writeword[j].lowaddr = 0xff0000; readbyte[i].highaddr= readword[i].highaddr= writebyte[j].highaddr= writeword[j].highaddr= 0xffffff; readbyte[i].memorycall= readword[i].memorycall= writebyte[j].memorycall=writeword[j].memorycall= NULL; readbyte[i].userdata= readword[i].userdata = writebyte[j].userdata= writeword[j].userdata = ram; i++; j++; // Faster version end *************** #endif // The end readbyte[i].lowaddr = readword[i].lowaddr = writebyte[j].lowaddr = writeword[j].lowaddr = readbyte[i].highaddr = readword[i].highaddr = writebyte[j].highaddr = writeword[j].highaddr = 0xffffffff; readbyte[i].memorycall= readword[i].memorycall= writebyte[j].memorycall= writeword[j].memorycall= readbyte[i].userdata= readword[i].userdata = writebyte[j].userdata= writeword[j].userdata = NULL; i++; j++; if (debug_log!=NULL) fprintf (debug_log,"StarScream memory_map has %d read sections and %d write sections\n",i,j); return 0; } #endif int md::reset() { star_mz80_on(); #ifdef COMPILE_WITH_STAR if (cpu_emu==0) s68000reset(); #endif #ifdef COMPILE_WITH_MUSA if (cpu_emu==1) m68k_pulse_reset(NULL); #endif #ifdef COMPILE_WITH_M68KEM if (cpu_emu==2) m68000_reset(NULL); #endif if (debug_log) fprintf (debug_log,"reset()\n"); mz80reset(); // zero = natural state of select line? z80_bank68k=z80_online=z80_extra_cycles =coo_waiting=coo_cmd=aoo3_toggle=aoo5_toggle=aoo3_six=aoo5_six =aoo3_six_timeout=aoo5_six_timeout =coo4=coo5=pause=0; pad[0]=pad[1]=0xf303f; // Untouched pad // Reset FM registers { int s, r; for(s=0;s<2;s++) for(r=0;r<0x100;r++) fm_reg[s][r]=0; } fm_sel[0] = fm_sel[1] = fm_tover[0] = fm_tover[1] = 0; dac_init(); odo=odo_line_start=odo_line_end=ras=0; //odo_frame_max=0; hint_countdown=0; z80_int_pending=0; star_mz80_off(); return 0; } static struct MemoryReadByte mem_read[]= { {0x2000,0xffff,root_z80_read}, {(UINT32) -1,(UINT32) -1,NULL} }; static struct MemoryWriteByte mem_write[]= { {0x2000,0xffff,root_z80_write}, {(UINT32) -1,(UINT32) -1,NULL} }; static struct z80PortRead io_read[] ={ {0x00,0x00ff,root_z80_port_read}, {(UINT16) -1,(UINT16) -1,NULL} }; static struct z80PortWrite io_write[]={ {0x00,0x00ff,root_z80_port_write}, {(UINT16) -1,(UINT16) -1,NULL} }; int md::z80_init() { // Set up the z80 star_mz80_on(); mz80reset(); // Modify the default context mz80GetContext(&z80); // point mz80 stuff z80.z80Base=z80ram; z80.z80MemRead=mem_read; z80.z80MemWrite=mem_write; z80.z80IoRead=io_read; z80.z80IoWrite=io_write; mz80SetContext(&z80); mz80reset(); star_mz80_off(); return 0; } md::md() { romlen=0; mem=rom=ram=z80ram=saveram=NULL; save_start=save_len=save_prot=save_active=0; pal = frame = 0; fm_sel[0]=fm_sel[1]=fm_tover[0]=fm_tover[1]=0; snd_mute=0; memset(&fm_reg,0,sizeof(fm_reg)); memset(&ras_fm_ticker,0,sizeof(ras_fm_ticker)); #ifdef COMPILE_WITH_STAR fetch=NULL; readbyte=readword=writebyte=writeword=NULL; memset(&cpu,0,sizeof(cpu)); #endif memset(&z80,0,sizeof(z80)); romfilename[0]=0; country_ver=0xff0; layer_sel = 0xff; memset(romfilename,0,sizeof(romfilename)); ok=0; if (!vdp.okay()) return; vdp.belongs=this; // Format of pad is: __SA____ UDLRBC__ rom=mem=ram=z80ram=NULL; mem=(unsigned char *)malloc(0x20000); if (mem==NULL) return; memset(mem,0,0x20000); ram= mem+0x00000; z80ram=mem+0x10000; romlen=0; star_mz80_on(); // VERY IMPORTANT - Must call before using stars/mz80!! #ifdef COMPILE_WITH_STAR if (s68000init()!=0) { printf ("s68000init failed!\n"); return; } #endif star_mz80_off(); // VERY IMPORTANT - Must call after using stars/mz80!! cpu_emu=-1; // Do we have a cpu emu? #ifdef COMPILE_WITH_STAR // Dave: Rich said doing point star stuff is done after s68000init // in Asgard68000, so just in case... fetch= new STARSCREAM_PROGRAMREGION[6]; if (!fetch) return; readbyte= new STARSCREAM_DATAREGION[5]; if (!readbyte) return; readword= new STARSCREAM_DATAREGION[5]; if (!readword) return; writebyte=new STARSCREAM_DATAREGION[5]; if (!writebyte) return; writeword=new STARSCREAM_DATAREGION[5]; if (!writeword) return; memory_map(); // point star stuff cpu.s_fetch = cpu.u_fetch = fetch; cpu.s_readbyte = cpu.u_readbyte = readbyte; cpu.s_readword = cpu.u_readword = readword; cpu.s_writebyte = cpu.u_writebyte = writebyte; cpu.s_writeword = cpu.u_writeword = writeword; cpu_emu=0; // zero=starscream, one=musashi, two=68kem #else #ifdef COMPILE_WITH_MUSA cpu_emu=1; // zero=starscream, one=musash, two=68kemi #endif #ifdef COMPILE_WITH_M68KEM cpu_emu=2; // zero=starscream, one=musash, two=68kemi #endif #endif #ifdef COMPILE_WITH_MUSA m68k_pulse_reset(NULL); #endif #ifdef COMPILE_WITH_M68KEM m68000_reset(NULL); #endif z80_init(); reset(); // reset megadrive ok=1; } md::~md() { romfilename[0]=0; if (rom!=NULL) unplug(); free(mem); rom=mem=ram=z80ram=NULL; #ifdef COMPILE_WITH_STAR if (fetch) delete[] fetch; if (readbyte) delete[] readbyte; if (readword) delete[] readword; if (writebyte) delete[] writebyte; if (writeword) delete[] writeword; #endif ok=0; } // Byteswaps memory int byteswap_memory(unsigned char *start,int len) { int i; unsigned char tmp; for (i=0;i= romlen) save_active = 1; } else { save_start = save_len = 0; saveram = NULL; } } else { save_start = save_len = 0; saveram = NULL; } #ifdef COMPILE_WITH_STAR memory_map(); // Update memory map to include this cartridge #endif reset(); // Reset megadrive return 0; } int md::unplug() { if (rom==NULL) return 1; if (romlen<=0) return 1; free(rom); free(saveram); romlen = save_start = save_len = 0; #ifdef COMPILE_WITH_STAR memory_map(); // Update memory map to include no rom #endif memset(romfilename,0,sizeof(romfilename)); reset(); return 0; } extern "C" int load_rom_into(char *name,unsigned char *into); int md::load(char *name) { // Convenience function - calls romload.c functions unsigned char *temp=NULL; int len=0; if (name==NULL) return 1; len=load_rom_into(name,NULL); if (len<=0) return 1; temp=(unsigned char *)malloc(len); if (temp==NULL) return 1; load_rom_into(name,temp); // Register name strncpy(romfilename,name,255); // Fill the header with ROM info (god this is ugly) memcpy((void*)cart_head.system_name, (void*)(temp + 0x100), 0x10); memcpy((void*)cart_head.copyright, (void*)(temp + 0x110), 0x10); memcpy((void*)cart_head.domestic_name,(void*)(temp + 0x120), 0x30); memcpy((void*)cart_head.overseas_name,(void*)(temp + 0x150), 0x30); memcpy((void*)cart_head.product_no, (void*)(temp + 0x180), 0x0e); cart_head.checksum = temp[0x18e]<<8 | temp[0x18f]; // ugly, but endian-neutral memcpy((void*)cart_head.control_data, (void*)(temp + 0x190), 0x10); cart_head.rom_start = temp[0x1a0]<<24 | temp[0x1a1]<<16 | temp[0x1a2]<<8 | temp[0x1a3]; cart_head.rom_end = temp[0x1a4]<<24 | temp[0x1a5]<<16 | temp[0x1a6]<<8 | temp[0x1a7]; cart_head.ram_start = temp[0x1a8]<<24 | temp[0x1a9]<<16 | temp[0x1aa]<<8 | temp[0x1ab]; cart_head.ram_end = temp[0x1ac]<<24 | temp[0x1ad]<<16 | temp[0x1ae]<<8 | temp[0x1af]; cart_head.save_magic = temp[0x1b0]<<8 | temp[0x1b1]; cart_head.save_flags = temp[0x1b2]<<8 | temp[0x1b3]; cart_head.save_start = temp[0x1b4]<<24 | temp[0x1b5]<<16 | temp[0x1b6]<<8 | temp[0x1b7]; cart_head.save_end = temp[0x1b8]<<24 | temp[0x1b9]<<16 | temp[0x1ba]<<8 | temp[0x1bb]; memcpy((void*)cart_head.memo, (void*)(temp + 0x1c8), 0x28); memcpy((void*)cart_head.countries, (void*)(temp + 0x1f0), 0x10); // Plug it into the memory map plug_in(temp,len); // md then deallocates it when it's done return 0; } int md::change_cpu_emu(int to) { // Note - stars/mz80 isn't run here, so star_mz80_on() not necessary #ifdef COMPILE_WITH_STAR #ifdef COMPILE_WITH_MUSA if (cpu_emu==0 && to==1) { int i; for (i=0;i<8;i++) m68k_poke_dr(i,cpu.dreg[i]); for (i=0;i<8;i++) m68k_poke_ar(i,cpu.areg[i]); m68k_poke_pc(cpu.pc); m68k_poke_sr(cpu.sr); } if (cpu_emu==1 && to==0) { int i; for (i=0;i<8;i++) cpu.dreg[i]=m68k_peek_dr(i); for (i=0;i<8;i++) cpu.areg[i]=m68k_peek_ar(i); cpu.pc=m68k_peek_pc(); cpu.sr=m68k_peek_sr(); } #endif #endif cpu_emu=to; return 0; } int md::z80dump() { FILE *hand; hand=fopen("dgz80ram","wb"); if (hand!=NULL) { fwrite(z80ram,1,0x10000,hand); fclose(hand); } return 0; } dgen-sdl-1.23/mdfr.cpp 644 1750 1750 17212 7176126365 7751 // DGen/SDL v1.18+ // Megadrive 1 Frame module // Many, many thanks to John Stiles for the new structure of this module! :) #include #include #include #include #include "md.h" int split_screen=0; #ifdef COMPILE_WITH_STAR void md::run_to_odo_star(int odo_to) { int odo_start = s68000readOdometer(); s68000exec(odo_to - odo_start); } #endif #ifdef COMPILE_WITH_MUSA void md::run_to_odo_musa(int odo_to) { odo += m68k_execute(odo_to - odo); } #endif #ifdef COMPILE_WITH_M68KEM void md::run_to_odo_m68kem(int odo_to) { odo += m68000_execute(odo_to - odo); } #endif void md::run_to_odo_z80(int odo_to) { if(z80_online) { odo_to >>= 1; int odo_start = mz80GetElapsedTicks(0); mz80exec(odo_to - odo_start); } } #define LINES_PER_FRAME_NTSC 0x106 // Number of scanlines in NTSC (w/ vblank) #define LINES_PER_FRAME_PAL 0x138 // Number of scanlines in PAL (w/ vblank) #define LINES_PER_FRAME (pal? LINES_PER_FRAME_PAL : LINES_PER_FRAME_NTSC) #define VBLANK_LINE_NTSC 0xE0 // vblank location for NTSC (and PAL 28-cel mode) #define VBLANK_LINE_PAL 0xF0 // vblank location for PAL 30-cel mode #define VBLANK_LINE ((pal && (vdp.reg[1] & 8))? \ VBLANK_LINE_PAL : VBLANK_LINE_NTSC) #define scanlength (pal? (7189547/50/0x138) : (8000000/60/0x106)) #ifdef COMPILE_WITH_STAR int md::one_frame_star(struct bmap *bm, unsigned char retpal[256], struct sndinfo *sndi) { int hints, odom = 0; star_mz80_on(); // VERY IMPORTANT! Must call before using star/mz80 // Clear odos s68000tripOdometer(); mz80GetElapsedTicks(1); // Raster zero causes special things to happen :) coo4 = 0x37; // Init status register if(vdp.reg[12] & 0x2) coo5 ^= 0x10; // Toggle odd/even for interlace if(vdp.reg[1] & 0x40) coo5 &= ~0x88; // Clear vblank and vint if(!(vdp.reg[1] & 0x20)) coo5 |= 0x80; // If vint disabled, vint happened // is permanently set hints = vdp.reg[10]; // Set hint counter // Video display! :D for(ras = 0; ras < VBLANK_LINE; ++ras) { fm_timer_callback(); // update sound timers if((vdp.reg[0] & 0x10) && (--hints < 0)) { // Trigger hint s68000interrupt(4, -1); hints = vdp.reg[10]; may_want_to_get_pic(bm, retpal, 1); } else may_want_to_get_pic(bm, retpal, 0); coo5 |= 4; // hblank comes before, about 36/209 of the whole scanline run_to_odo_star(odom + (scanlength * 36/209)); // Do hdisplay now odom += scanlength; coo5 &= ~4; run_to_odo_star(odom); // Do Z80 run_to_odo_z80(odom); } // Now we're in vblank, more special things happen :) // Blank everything, and trigger vint coo5 |= 0x8C; if(vdp.reg[1] & 0x20) s68000interrupt(6, -1); if(z80_online) mz80int(0); // Run the course of vblank for(; ras < LINES_PER_FRAME; ++ras) { fm_timer_callback(); // No interrupts happen in vblank odom += scanlength; run_to_odo_star(odom); run_to_odo_z80(odom); } // Fill the sound buffers if(sndi) may_want_to_get_sound(sndi); // Shut off mz80/star - VERY IMPORTANT! star_mz80_off(); return 0; } #endif // COMPILE_WITH_STAR #ifdef COMPILE_WITH_MUSA int md::one_frame_musa(struct bmap *bm, unsigned char retpal[256], struct sndinfo *sndi) { int hints, odom = 0; star_mz80_on(); // VERY IMPORTANT! Must call before using star/mz80 // Clear odos odo = 0; mz80GetElapsedTicks(1); // Raster zero causes special things to happen :) coo4 = 0x37; // Init status register if(vdp.reg[12] & 0x2) coo5 ^= 0x10; // Toggle odd/even for interlace if(vdp.reg[1] & 0x40) coo5 &= ~0x88; // Clear vblank and vint if(!(vdp.reg[1] & 0x20)) coo5 |= 0x80; // If vint disabled, vint happened // is permanently set hints = vdp.reg[10]; // Set hint counter // Video display! :D for(ras = 0; ras < VBLANK_LINE; ++ras) { fm_timer_callback(); // update sound timers if((vdp.reg[0] & 0x10) && (--hints < 0)) { // Trigger hint m68k_assert_irq(4); m68k_clear_irq(4); hints = vdp.reg[10]; may_want_to_get_pic(bm, retpal, 1); } else may_want_to_get_pic(bm, retpal, 0); coo5 |= 4; // hblank comes before, about 36/209 of the whole scanline run_to_odo_musa(odom + (scanlength * 36/209)); // Do hdisplay now odom += scanlength; coo5 &= ~4; run_to_odo_musa(odom); // Do Z80 run_to_odo_z80(odom); } // Now we're in vblank, more special things happen :) // Blank everything, and trigger vint coo5 |= 0x8C; if(vdp.reg[1] & 0x20) { m68k_assert_irq(6); m68k_clear_irq(6); } if(z80_online) mz80int(0); // Run the course of vblank for(; ras < LINES_PER_FRAME; ++ras) { fm_timer_callback(); // No interrupts happen in vblank :) odom += scanlength; run_to_odo_musa(odom); run_to_odo_z80(odom); } // Fill the sound buffers if(sndi) may_want_to_get_sound(sndi); // Shut off mz80/star - VERY IMPORTANT! star_mz80_off(); return 0; } #endif // COMPILE_WITH_MUSA // FIXME: I'm not going to do this until I figure out 68kem better #ifdef COMPILE_WITH_M68KEM int md::one_frame_m68kem(struct bmap *bm, unsigned char retpal[256], struct sndinfo *sndi) {} #endif int md::one_frame( struct bmap *bm,unsigned char retpal[256], struct sndinfo *sndi) { ++frame; switch(cpu_emu) { #ifdef COMPILE_WITH_STAR case 0: return one_frame_star(bm, retpal, sndi); #endif #ifdef COMPILE_WITH_MUSA case 1: return one_frame_musa(bm, retpal, sndi); #endif #ifdef COMPILE_WITH_M68KEM case 2: return one_frame_m68kem(bm, retpal, sndi); #endif // Something's screwy here... default: return 1; } } int md::calculate_hcoord() { int x=0,hcoord; // c00009 is the H counter (I believe it's (h-coord>>1)&0xff) #ifdef COMPILE_WITH_STAR if (cpu_emu==0) x = s68000readOdometer() - (ras * scanlength); #endif #if defined(COMPILE_WITH_MUSA) || defined(COMPILE_WITH_M68KEM) if (cpu_emu==1) x = odo - (ras * scanlength); #endif // hcoord=-56 (inclusive) to 364 (inclusive) in 40 column mode hcoord=(x*416)/scanlength; hcoord-=56; return hcoord; } unsigned char md::calculate_coo8() { int hvcount; hvcount=ras; // c00008 is the V counter if (calculate_hcoord()>=330) hvcount++; // v counter seems to be a bit ahead of where h counter wraps if (hvcount>(VBLANK_LINE+0xa)) hvcount-=6; // vcounter E5-EA appears twice! hvcount&=0xff; return hvcount; } unsigned char md::calculate_coo9() { int coo9; coo9=(calculate_hcoord()>>1)&0xff; return coo9; } // ************************************* // May want to get pic or sound // ************************************* inline int md::may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int/*mark*/) { if (bm==NULL) return 0; if (ras>=0 && raslen; int in_dac, cur_dac = 0, acc_dac = len; int *dac = dac_data - 1; // Get the PSG SN76496Update_16(0, sndi->l, len); // We bring in the dac, but stretch it out to fit the real length. for(i = 0; i < len; ++i) { acc_dac += LINES_PER_FRAME; if(acc_dac >= len) { acc_dac -= len; in_dac = *(++dac); if(in_dac != 1) cur_dac = in_dac; } sndi->l[i] += cur_dac; } // Copy mono signal to center channel memcpy(sndi->r, sndi->l, len * sizeof(short)); // Add in the stereo FM buffer FMSAMPLE *buf[2]; buf[0] = (FMSAMPLE*) sndi->l; buf[1] = (FMSAMPLE*) sndi->r; YM2612UpdateOne(0, (void**)buf, len); // Clear the dac for next frame dac_clear(); return 0; } dgen-sdl-1.23/md-joe.cpp 644 1750 1750 3511 7027317555 10147 // DGen/SDL v1.15+ #include #include #include #include "md.h" #include "decode.h" // These are my (Joe's) functions added to the md class. // This takes a comma or whitespace-separated list of Game Genie and/or hex // codes to patch the ROM with. void md::patch(const char *list) { static const char delims[] = " \t\n,"; char *worklist, *tok; struct patch p; // Copy the given list to a working list so we can strtok it worklist = (char*)malloc(strlen(list)+1); strcpy(worklist, list); for(tok = strtok(worklist, delims); tok; tok = strtok(NULL, delims)) { // If it's empty, toss it if(*tok == '\0') continue; // Decode it decode(tok, &p); // Discard it if it was bad code if((signed)p.addr == -1) { printf("Bad patch \"%s\"\n", tok); continue; } // Put it into the ROM (remember byteswapping) printf("Patch \"%s\" -> %06X:%04X\n", tok, p.addr, p.data); rom[p.addr] = (char)(p.data & 0xFF); rom[p.addr+1] = (char)((p.data & 0xFF00) >> 8); } // Done! free(worklist); return; } // Get/put saveram from/to FILE*'s void md::get_save_ram(FILE *from) { // Pretty simple, just read the saveram raw fread((void*)saveram, 1, save_len, from); } void md::put_save_ram(FILE *into) { // Just the opposite of the above :) fwrite((void*)saveram, 1, save_len, into); } // Dave: This is my code, but I thought it belonged here // Joe: Thanks Dave! No problem ;) static unsigned short calculate_checksum(unsigned char *rom,int len) { unsigned short checksum=0; int i; for (i=512;i<=(len-2);i+=2) { checksum+=(rom[i+1]<<8); checksum+=rom[i+0]; } return checksum; } void md::fix_rom_checksum() { unsigned short cs; cs=calculate_checksum(rom,romlen); if (romlen>=0x190) { rom[0x18f]=cs>>8; rom[0x18e]=cs&255; } } dgen-sdl-1.23/decode.c 644 1750 1750 13531 7027317553 7700 /* Decode a Game Genie code into an M68000 address/data pair. * The Game Genie code is made of the characters * ABCDEFGHJKLMNPRSTVWXYZ0123456789 (notice the missing I, O, Q and U). * Where A = 00000, B = 00001, C = 00010, ... , on to 9 = 11111. * * These come out to a very scrambled bit pattern like this: * (SCRA-MBLE is just an example) * * S C R A - M B L E * 01111 00010 01110 00000 01011 00001 01010 00100 * ijklm nopIJ KLMNO PABCD EFGHd efgha bcQRS TUVWX * * Our goal is to rearrange that to this: * * 0000 0101 1001 1100 0100 0100 : 1011 0000 0111 1000 * ABCD EFGH IJKL MNOP QRST UVWX : abcd efgh ijkl mnop * * which in Hexadecimal is 059C44:B078. Simple, huh? ;) * * So, then, we dutifully change memory location 059C44 to B078! * (of course, that's handled by a different source file :) */ #include #include #include "decode.h" static char genie_chars[] = "AaBbCcDdEeFfGgHhJjKkLlMmNnPpRrSsTtVvWwXxYyZz0O1I2233445566778899"; /* genie_decode * This function converts a Game Genie code to an address:data pair. * The code is given as an 8-character string, like "BJX0SA1C". It need not * be null terminated, since only the first 8 characters are taken. It is * assumed that the code is already made of valid characters, i.e. there are no * Q's, U's, or symbols. If such a character is * encountered, the function will return with a warning on stderr. * * The resulting address:data pair is returned in the struct patch pointed to * by result. If an error results, both the address and data will be set to -1. */ static void genie_decode(const char* code, struct patch* result) { int i = 0, n; char* x; for(; i < 8; ++i) { /* If strchr returns NULL, we were given a bad character */ if(!(x = strchr(genie_chars, code[i]))) { result->addr = -1; result->data = -1; return; } n = (x - genie_chars) >> 1; /* Now, based on which character this is, fit it into the result */ switch(i) { case 0: /* ____ ____ ____ ____ ____ ____ : ____ ____ ABCD E___ */ result->data |= n << 3; break; case 1: /* ____ ____ DE__ ____ ____ ____ : ____ ____ ____ _ABC */ result->data |= n >> 2; result->addr |= (n & 3) << 14; break; case 2: /* ____ ____ __AB CDE_ ____ ____ : ____ ____ ____ ____ */ result->addr |= n << 9; break; case 3: /* BCDE ____ ____ ___A ____ ____ : ____ ____ ____ ____ */ result->addr |= (n & 0xF) << 20 | (n >> 4) << 8; break; case 4: /* ____ ABCD ____ ____ ____ ____ : ___E ____ ____ ____ */ result->data |= (n & 1) << 12; result->addr |= (n >> 1) << 16; break; case 5: /* ____ ____ ____ ____ ____ ____ : E___ ABCD ____ ____ */ result->data |= (n & 1) << 15 | (n >> 1) << 8; break; case 6: /* ____ ____ ____ ____ CDE_ ____ : _AB_ ____ ____ ____ */ result->data |= (n >> 3) << 13; result->addr |= (n & 7) << 5; break; case 7: /* ____ ____ ____ ____ ___A BCDE : ____ ____ ____ ____ */ result->addr |= n; break; } /* Go around again */ } return; } /* "Decode" an address/data pair into a structure. This is for "012345:ABCD" * type codes. You're more likely to find Genie codes circulating around, but * there's a chance you could come on to one of these. Which is nice, since * they're MUCH easier to implement ;) Once again, the input should be depunc- * tuated already. */ static char hex_chars[] = "00112233445566778899AaBbCcDdEeFf"; static void hex_decode(const char *code, struct patch *result) { char *x; int i; /* 6 digits for address */ for(i = 0; i < 6; ++i) { if(!(x = strchr(hex_chars, code[i]))) { result->addr = result->data = -1; return; } result->addr = (result->addr << 4) | ((x - hex_chars) >> 1); } /* 4 digits for data */ for(i = 6; i < 10; ++i) { if(!(x = strchr(hex_chars, code[i]))) { result->addr = result->data = -1; return; } result->data = (result->data << 4) | ((x - hex_chars) >> 1); } } /* THIS is the function you call from the MegaDrive or whatever. This figures * out whether it's a genie or hex code, depunctuates it, and calls the proper * decoder. */ void decode(const char* code, struct patch* result) { int len = strlen(code), i, j; char code_to_pass[16], *x; const char *ad, *da; int adl, dal; /* Initialize the result */ result->addr = result->data = 0; /* If it's 9 chars long and the 5th is a hyphen, we have a Game Genie * code. */ if(len == 9 && code[4] == '-') { /* Remove the hyphen and pass to genie_decode */ code_to_pass[0] = code[0]; code_to_pass[1] = code[1]; code_to_pass[2] = code[2]; code_to_pass[3] = code[3]; code_to_pass[4] = code[5]; code_to_pass[5] = code[6]; code_to_pass[6] = code[7]; code_to_pass[7] = code[8]; code_to_pass[8] = '\0'; genie_decode(code_to_pass, result); return; } /* Otherwise, we assume it's a hex code. * Find the colon so we know where address ends and data starts. If there's * no colon, then we haven't a code at all! */ if(!(x = strchr(code, ':'))) goto bad_code; ad = code; da = x + 1; adl = x - code; dal = len - adl - 1; /* If a section is empty or too long, toss it */ if(adl == 0 || adl > 6 || dal == 0 || dal > 4) goto bad_code; /* Pad the address with zeros, then fill it with the value */ for(i = 0; i < (6 - adl); ++i) code_to_pass[i] = '0'; for(j = 0; i < 6; ++i, ++j) code_to_pass[i] = ad[j]; /* Do the same for data */ for(i = 6; i < (10 - dal); ++i) code_to_pass[i] = '0'; for(j = 0; i < 10; ++i, ++j) code_to_pass[i] = da[j]; code_to_pass[10] = '\0'; /* Decode and goodbye */ hex_decode(code_to_pass, result); return; bad_code: /* AGH! Invalid code! */ result->data = result->addr = -1; return; } dgen-sdl-1.23/vdp.cpp 644 1750 1750 13062 7027317556 7610 // DGen v1.13+ // Megadrive's VDP C++ module #include #include #include #include "md.h" int md_vdp::get_screen_info(struct dgen_sinfo *si) { // Release the pointers to vdp Data to an external function si->vram=vram; si->cram=cram; si->vsram=vsram; si->vdp_reg=reg; // NB - if you change anything, remember to set 'dirt' accordingly return 0; } int md_vdp::reset() { if (!ok) return 1; rw_mode=0x00; rw_addr=0; rw_dma=0; memset(mem,0,0x10100); memset(reg,0,0x20); memset(dirt,0xff,0x35); // mark everything as changed return 0; } md_vdp::md_vdp() { ok=0; belongs=0; // Don't know which megadrive vdp belongs to yet mem=vram=cram=vsram=NULL; mem=new unsigned char[0x10100+0x35]; //0x20+0x10+0x4+1 for dirt if (mem==0) return; vram=mem+0x00000; cram=mem+0x10000; vsram=mem+0x10080; dirt=mem+0x10100; // VRAM/CRAM/Reg dirty buffer bitfield // Also in 0x34 are global dirt flags (inclduing VSRAM this time) highpal=new unsigned int[64]; if (highpal==0) return; Bpp = Bpp_times8 = 0; ok=1; reset(); } md_vdp::~md_vdp() { free(mem); mem=vram=cram=vsram=NULL; ok=0; } int md_vdp::dma_len() { return (reg[0x14]<<8)+reg[0x13]; } int md_vdp::dma_addr() { int addr=0; addr=(reg[0x17]&0x7f)<<17; addr+=reg[0x16]<<9; addr+=reg[0x15]<<1; return addr; } // DMA can read from anywhere unsigned char md_vdp::dma_mem_read(int addr) { return belongs->misc_readbyte(addr); } // Must go through these calls to update the dirty flags int md_vdp::poke_vram(int addr,unsigned char d) { // Keeping GCC happy over unused vars. [PKH] // int diff=0; addr&=0xffff; if (vram[addr]!=d) { // Store dirty information down to 256 byte level in bits int byt,bit; byt=addr>>8; bit=byt&7; byt>>=3; byt&=0x1f; dirt[0x00+byt]|=(1<>=3; byt&=0x0f; dirt[0x20+byt]|=(1<>8); poke_vram (rw_addr+1,d&0xff); break; case 0x0c: poke_cram (rw_addr+0,d>>8); poke_cram (rw_addr+1,d&0xff); break; case 0x14: poke_vsram(rw_addr+0,d>>8); poke_vsram(rw_addr+1,d&0xff); break; } rw_addr+=reg[15]; return 0; } int md_vdp::putbyte(unsigned char d) { // int diff=0; // Called by dma or a straight write switch(rw_mode) { case 0x04: poke_vram (rw_addr,d>>8); break; case 0x0c: poke_cram (rw_addr,d>>8); break; case 0x14: poke_vsram(rw_addr,d>>8); break; } rw_addr+=reg[15]; return 0; } #undef MAYCHANGE unsigned short md_vdp::readword() { // Called by a straight read only unsigned short result=0x0000; switch(rw_mode) { case 0x00: result=( vram[(rw_addr+0)&0xffff]<<8)+ vram[(rw_addr+1)&0xffff]; break; case 0x20: result=( cram[(rw_addr+0)&0x007f]<<8)+ cram[(rw_addr+1)&0x007f]; break; case 0x10: result=(vsram[(rw_addr+0)&0x007f]<<8)+ vsram[(rw_addr+1)&0x007f]; break; } rw_addr+=reg[15]; return result; } unsigned char md_vdp::readbyte() { // Called by a straight read only unsigned char result=0x00; switch(rw_mode) { case 0x00: result= vram[(rw_addr+0)&0xffff]; break; case 0x20: result= cram[(rw_addr+0)&0x007f]; break; case 0x10: result=vsram[(rw_addr+0)&0x007f]; break; } rw_addr+=reg[15]; return result; } int md_vdp::command(unsigned int cmd) { // Decode 32-bit VDP command rw_dma=((cmd&0x80)==0x80); rw_mode= cmd&0x00000070; rw_mode|=(cmd&0xc0000000)>>28; // mode writes: 04=VRAM 0C=CRAM 14=VSRAM // mode reads: 00=VRAM 20=CRAM 10=VSRAM rw_addr= (cmd&0x00000003)<<14; rw_addr|=(cmd&0x3fff0000)>>16; // If not dma (or we need a fill), // we are set up to write any data sent to vdp data reg // if it's a dma request do it straight away if (rw_dma) { int mode=(reg[0x17]>>6)&3; int s=0,d=0,i=0,len=0; s=dma_addr(); d=rw_addr; len=dma_len(); switch (mode) { case 0: case 1: for (i=0;i>6)&3)==2) { int i,len; len=dma_len(); for (i=0;i>6)&3)==2) { int i,len; len=dma_len(); for (i=0;i #include #include "md.h" /* gs0 genecyst save file INfo GST\0 to start with 80-9f = d0-d7 almost certain a0-bf = a0-a7 almost certain c8 = pc fairly certain d0 = sr fairly certain 112 Start of cram len 0x80 192 Start of vsram len 0x50 1e2-474 UNKNOWN sound info? Start of z80 ram at 474 (they store 2000) Start of RAM at 2478 almost certain (BYTE SWAPPED) Start of VRAM at 12478 end of VRAM */ // NB - for load and save you don't need to use star_mz80_on/off // Because stars/mz80 isn't actually used #define fput(x,y) { if (fwrite(x,1,y,hand)!=y) goto save_error; } #define fget(x,y) if (fread(x,1,y,hand)!=y) goto load_error; extern int byteswap_memory(unsigned char *start,int len); int md::import_gst(FILE *hand) { #ifdef COMPILE_WITH_STAR if (cpu_emu==0) { fseek(hand,0x80,SEEK_SET); fget(cpu.dreg,8*4); fget(cpu.areg,8*4); fseek(hand,0xc8,SEEK_SET); fget(&cpu.pc,4); fseek(hand,0xd0,SEEK_SET); fget(&cpu.sr,4); } #endif #ifdef COMPILE_WITH_MUSA if (cpu_emu==1) { int i,t; fseek(hand,0x80,SEEK_SET); for (i=0;i<8;i++) { fget(&t,4); m68k_poke_dr(i,t); } for (i=0;i<8;i++) { fget(&t,4); m68k_poke_ar(i,t); } fseek(hand,0xc8,SEEK_SET); fget(&t,4); m68k_poke_pc(t); fseek(hand,0xd0,SEEK_SET); fget(&t,4); m68k_poke_sr(t); } #endif fseek(hand,0xfa,SEEK_SET); fget(vdp.reg,0x18); fseek(hand,0x112,SEEK_SET); fget(vdp.cram ,0x00080); byteswap_memory(vdp.cram,0x80); fget(vdp.vsram,0x00050); byteswap_memory(vdp.vsram,0x50); fseek(hand,0x474,SEEK_SET); fget(z80ram, 0x02000); fseek(hand,0x2478,SEEK_SET); fget(ram, 0x10000); byteswap_memory(ram,0x10000); fget(vdp.vram ,0x10000); memset(vdp.dirt,0xff,0x35); // mark everything as changed return 0; load_error: return 1; } int md::export_gst(FILE *hand) { int i; static unsigned char gst_head[0x80]= { 0x47,0x53,0x54,0,0,0,0xe0,0x40 // 00 00 00 00 00 00 00 00 00 00 00 00 00 21 80 fa <.............!..> }; unsigned char *zeros=gst_head+0x40; // 0x40 zeros fseek(hand,0x00,SEEK_SET); // Make file size 0x22478 with zeros for (i=0;i<0x22440;i+=0x40) fput(zeros,0x40); fput(zeros,0x38); fseek(hand,0x00,SEEK_SET); fput(gst_head,0x80); #ifdef COMPILE_WITH_STAR if (cpu_emu==0) { fseek(hand,0x80,SEEK_SET); fput(cpu.dreg,8*4); fput(cpu.areg,8*4); fseek(hand,0xc8,SEEK_SET); fput(&cpu.pc,4); fseek(hand,0xd0,SEEK_SET); fput(&cpu.sr,4); } #endif #ifdef COMPILE_WITH_MUSA if (cpu_emu==1) { int i,t; fseek(hand,0x80,SEEK_SET); for (i=0;i<8;i++) { t=m68k_peek_dr(i); fput(&t,4);} for (i=0;i<8;i++) { t=m68k_peek_ar(i); fput(&t,4);} fseek(hand,0xc8,SEEK_SET); t=m68k_peek_pc(); fput(&t,4); fseek(hand,0xd0,SEEK_SET); t=m68k_peek_sr(); fput(&t,4); } #endif fseek(hand,0xfa,SEEK_SET); fput(vdp.reg,0x18); fseek(hand,0x112,SEEK_SET); byteswap_memory(vdp.cram,0x80); fput(vdp.cram ,0x00080); byteswap_memory(vdp.cram,0x80); byteswap_memory(vdp.vsram,0x50); fput(vdp.vsram,0x00050); byteswap_memory(vdp.vsram,0x50); fseek(hand,0x474,SEEK_SET); fput(z80ram, 0x02000); fseek(hand,0x2478,SEEK_SET); byteswap_memory(ram,0x10000); fput(ram, 0x10000); byteswap_memory(ram,0x10000); fput(vdp.vram ,0x10000); return 0; save_error: return 1; } dgen-sdl-1.23/graph.cpp 644 1750 1750 717 7027317554 10061 // DGen v1.13+ #include #include "md.h" // This allows you to get the palette, mess around with it // (e.g. contrast/brightness) // and then pass it back int get_md_palette(unsigned char pal[256],unsigned char *cram) { int c; if (pal==NULL) return 1; for (c=0;c<64;c++) { int r,g,b; b=(cram[c*2+0]&0x0e)<<4; g=(cram[c*2+1]&0xe0); r=(cram[c*2+1]&0x0e)<<4; pal[c*4+0]=r; pal[c*4+1]=g; pal[c*4+2]=b; } return 0; } dgen-sdl-1.23/myfm.cpp 644 1750 1750 4415 7027317555 7750 // DGen v1.06+ // MYFM.CPP - interface to YM2612Update #include #include #include "md.h" extern int sound_is_okay; // md.h also has include fm.h // REMEMBER NOT TO USE ANY STATIC variables, because they // will exist thoughout ALL megadrives! int md::flush_fm_to_mame() { int sid,r; // If we reset mame's ym2612 code, we need to pass all the values // to it again for (sid=0;sid<2;sid++) { for (r=0;r<0x100;r++) { if (sound_is_okay) { if (fm_reg[sid][r]!=-1) { YM2612Write(0,sid*2+0,r); // select reg r YM2612Write(0,sid*2+1,fm_reg[sid][r]); // Write data } } } } return 0; } int md::myfm_write(int a,int v,int md) { int sid=0; int mame_can_have_it=1; (void)md; a&=3; sid=(a&2)?1:0; if ((a&1)==0) fm_sel[sid]=v; else { // stash all values fm_reg[sid] [fm_sel[sid]&0xff] = v; if (fm_sel[sid]==0x2a) { dac_submit(v); mame_can_have_it=0; } if (fm_sel[sid]==0x2b) { dac_enable(v); mame_can_have_it=0; } if ((fm_sel[sid]&0xfc)==0x24) { mame_can_have_it=0; } if (fm_sel[sid]==0x27) { if (v&0x10) fm_tover[0]&=~1; if (v&0x20) fm_tover[0]&=~2; // timer ack? } } if (sound_is_okay && mame_can_have_it) YM2612Write(0,a&3,v); return 0; } int md::myfm_read(int a) { if ((a&1)==0) return fm_tover[0]; else { if (sound_is_okay) YM2612Read(0,a&3); } return 0; } int md::mysn_write(int d) { if (sound_is_okay) SN76496Write(0,d); return 0; } // This called once per raster int md::fm_timer_callback() { int amax,bmax, i; // Our raster lasts 63.61323 microseconds for (i=0;i<4;i++) ras_fm_ticker[i]+=64; // if (sound_is_okay) ret=YM2612Read(0,a&3); // period of timer a is // 18 * (1024 - ((fm_reg[0][0x24]<<2)+(fm_reg[0][0x25])&3))) microsecs amax=18 * (1024 - ((fm_reg[0][0x24]<<2)+(fm_reg[0][0x25]&3)) ); bmax=288*(256-fm_reg[0][0x26]); if (bmax<=0) bmax=1; if (amax<=0) amax=1; if (ras_fm_ticker[0]>=amax) { fm_tover[0]|=1; ras_fm_ticker[0]-=amax; } if (ras_fm_ticker[1]>=bmax) { fm_tover[0]|=2; ras_fm_ticker[1]-=bmax; } return 0; } dgen-sdl-1.23/fm.c 644 1750 1750 164300 7027317554 7101 #define YM2610B_WARNING /* YM2608 rhythm data is PCM ,not an ADPCM */ #define YM2608_RHYTHM_PCM /* ** ** File: fm.c -- software implementation of FM sound generator ** ** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmurator development ** ** Version 0.35f ** */ /* **** change log. (hiro-shi) **** ** 08-12-98: ** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA ** move ROM limit check.(CALC_CH? -> 2610Write1/2) ** test program (ADPCMB_TEST) ** move ADPCM A/B end check. ** ADPCMB repeat flag(no check) ** change ADPCM volume rate (8->16) (32->48). ** ** 09-12-98: ** change ADPCM volume. (8->16, 48->64) ** replace ym2610 ch0/3 (YM-2610B) ** init cur_chip (restart bug fix) ** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff. ** add ADPCM_SHIFT_MASK ** change ADPCMA_DECODE_MIN/MAX. */ /* no check: YM2608 rhythm sound OPN SSG type envelope YM2612 DAC output mode YM2151 CSM speech mode no support: status busy flag (already not busy) LFO contoller (YM2612/YM2610/YM2608/YM2151) YM2151 noise mode YM2608 DELTA-T-ADPCM and RYTHM YM2610 DELTA-T-ADPCM with PCM port YM2610 PCM memory data access YM2608 status mask (register :0x110) preliminary : key scale level rate (?) attack rate time rate , curve (?) decay rate time rate , curve (?) self feedback calcration YM2610 ADPCM mixing level Problem : note: OPN OPM fnum fMus * 2^20 / (fM/(12*n)) TimerOverA (12*n)*(1024-NA)/fFM 64*(1024-Na)/fm TimerOverB (12*n)*(256-NB)/fFM 1024*(256-Nb)/fm output bits 10bit<<3bit 16bit * 2ch (YM3012=10bit<<3bit) sampling rate fFM / (12*6) ? fFM / 64 lfo freq ( fM*2^(LFRQ/16) ) / (4295*10^6) */ /************************************************************************/ /* comment of hiro-shi(Hiromitsu Shioya) */ /* YM2610(B) = (OPN-B */ /* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ /* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ /************************************************************************/ //#define INLINE __inline__ #include #include #include #include #include #include "driver.h" #include "fm.h" #ifndef PI #define PI 3.14159265357989 #endif /***** shared function building option ****/ #define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2612) #define BUILD_OPNB (BUILD_YM2610||BUILD_YM2610B) #define BUILD_FM_ADPCMA (BUILD_YM2608||BUILD_YM2610) #define BUILD_FM_ADPCMB (BUILD_YM2608||BUILD_YM2610) /**** YM2610 ADPCM defines ****/ #define ADPCMA_VOLUME_RATE (1) #define ADPCMB_VOLUME_RATE (2) /* DELTA-T volume rate */ #define ADPCM_SHIFT (16) //#define AUDIO_CONV(A) ((A)) //#define AUDIO_CONV16(A) ((A)) /* ------------------------------------------------------------------ */ //#ifdef __RAINE__ #define INTERNAL_TIMER /* use internal timer */ //#endif /* -------------------- speed up optimize switch -------------------- */ /* ---------- Enable ---------- */ #define TL_SAVE_MEM /* save some memories for total level */ /* ---------- Disable ---------- */ #if 0 #define SEG_SUPPORT /* OPN SSG type envelope support */ #define LFO_SUPPORT /* LFO support */ #endif /* -------------------- preliminary define section --------------------- */ /* attack/decay rate time rate */ #define OPM_ARRATE 399128 #define OPM_DRRATE 5514396 /* It is not checked , because I haven't YM2203 rate */ #define OPN_ARRATE OPM_ARRATE #define OPN_DRRATE OPM_DRRATE #define FREQ_BITS 24 /* frequency turn */ /* counter bits = 21 , octerve 7 */ #define FREQ_RATE (1<<(FREQ_BITS-21)) #define TL_BITS (FREQ_BITS+2) /* final output shift , limit minimum and maximum */ #define OPN_OUTSB (TL_BITS+2-16) /* OPN output final shift 16bit */ #define OPN_MAXOUT (0x7fff<>2)&3) #define OPM_CHAN(N) (N&7) #define OPM_SLOT(N) ((N>>3)&3) /* slot number */ #define SLOT1 0 #define SLOT2 2 #define SLOT3 1 #define SLOT4 3 /* envelope phase */ #define ENV_MOD_OFF 0x00 #define ENV_MOD_RR 0x01 #define ENV_MOD_SR 0x02 #define ENV_MOD_DR 0x03 #define ENV_MOD_AR 0x04 #define ENV_SSG_SR 0x05 #define ENV_SSG_DR 0x06 #define ENV_SSG_AR 0x07 /* bit0 = right enable , bit1 = left enable (FOR YM2612) */ #define OPN_RIGHT 1 #define OPN_LEFT 2 #define OPN_CENTER 3 /* bit0 = left enable , bit1 = right enable */ #define OPM_LEFT 1 #define OPM_RIGHT 2 #define OPM_CENTER 3 /* */ /* YM2608 Rhythm Number */ #define RY_BD 0 #define RY_SD 1 #define RY_TOP 2 #define RY_HH 3 #define RY_TOM 4 #define RY_RIM 5 /* FM timer model */ #define FM_TIMER_SINGLE (0) #define FM_TIMER_INTERVAL (1) /* ---------- OPN / OPM one channel ---------- */ typedef struct fm_slot { int *DT; /* detune :DT_TABLE[DT] */ int DT2; /* multiple,Detune2:(DT2<<4)|ML for OPM*/ int TL; /* total level :TL << 8 */ signed int TLL; /* adjusted now TL */ unsigned char KSR; /* key scale rate :3-KSR */ int *AR; /* attack rate :&AR_TABLE[AR<<1] */ int *DR; /* decay rate :&DR_TALBE[DR<<1] */ int *SR; /* sustin rate :&DR_TABLE[SR<<1] */ int SL; /* sustin level :SL_TALBE[SL] */ int *RR; /* release rate :&DR_TABLE[RR<<2+2] */ unsigned char SEG; /* SSG EG type :SSGEG */ unsigned char ksr; /* key scale rate :kcode>>(3-KSR) */ unsigned int mul; /* multiple :ML_TABLE[ML] */ unsigned int Cnt; /* frequency count : */ unsigned int Incr; /* frequency step : */ /* envelope generator state */ unsigned char evm; /* envelope phase */ signed int evc; /* envelope counter */ signed int eve; /* envelope counter end point */ signed int evs; /* envelope counter step */ signed int evsa; /* envelope step for AR */ signed int evsd; /* envelope step for DR */ signed int evss; /* envelope step for SR */ signed int evsr; /* envelope step for RR */ /* LFO */ unsigned char ams; unsigned char pms; }FM_SLOT; typedef struct fm_chan { FM_SLOT SLOT[4]; unsigned char PAN; /* PAN NONE,LEFT,RIGHT or CENTER */ unsigned char ALGO; /* algorythm */ unsigned char FB; /* feed back :&FB_TABLE[FB<<8] */ int op1_out; /* op1 output foe beedback */ /* algorythm state */ int *connect1; /* operator 1 connection pointer */ int *connect2; /* operator 2 connection pointer */ int *connect3; /* operator 3 connection pointer */ int *connect4; /* operator 4 connection pointer */ /* phase generator state */ unsigned int fc; /* fnum,blk :calcrated */ unsigned char fn_h; /* freq latch : */ unsigned char kcode; /* key code : */ } FM_CH; /* OPN/OPM common state */ typedef struct fm_state { unsigned char index; /* chip index (number of chip) */ int clock; /* master clock (Hz) */ int rate; /* sampling rate (Hz) */ int freqbase; /* frequency base */ double TimerBase; /* Timer base time */ unsigned char address; /* address register */ unsigned char irq; /* interrupt level */ unsigned char irqmask; /* irq mask */ unsigned char status; /* status flag */ unsigned int mode; /* mode CSM / 3SLOT */ int TA; /* timer a */ int TAC; /* timer a counter */ unsigned char TB; /* timer b */ int TBC; /* timer b counter */ /* speedup customize */ /* time tables */ signed int DT_TABLE[8][32]; /* detune tables */ signed int AR_TABLE[94]; /* atttack rate tables */ signed int DR_TABLE[94]; /* decay rate tables */ /* LFO */ unsigned int LFOCnt; unsigned int LFOIncr; /* Extention Timer and IRQ handler */ FM_TIMERHANDLER Timer_Handler; FM_IRQHANDLER IRQ_Handler; /* timer model single / interval */ unsigned char timermodel; }FM_ST; /* OPN 3slot struct */ typedef struct opn_3slot { unsigned int fc[3]; /* fnum3,blk3 :calcrated */ unsigned char fn_h[3]; /* freq3 latch */ unsigned char kcode[3]; /* key code : */ }FM_3SLOT; /* adpcm type A and type B struct */ typedef struct adpcm_state { unsigned char flag; /* port state */ unsigned char flagMask; /* arrived */ unsigned char now_data; unsigned int now_addr; unsigned int now_step; unsigned int step; unsigned int start; unsigned int end; unsigned int delta; int IL; int volume; int *pan; /* &outd[OPN_xxxx] */ int /*adpcmm,*/ adpcmx, adpcmd; int adpcml; /* hiro-shi!! */ /* leveling and re-sampling state for DELTA-T */ int volume_w_step; /* volume with step rate */ int next_leveling; /* leveling value */ int sample_step; /* step of re-sampling */ }ADPCM_CH; /* OPN/A/B common state */ typedef struct opn_f { unsigned char type; /* chip type */ FM_ST ST; /* general state */ FM_3SLOT SL3; /* 3 slot mode state */ FM_CH *P_CH; /* pointer of CH */ unsigned int FN_TABLE[2048]; /* fnumber -> increment counter */ } FM_OPN; /* here's the virtual YM2203(OPN) (Used by YM2608 / YM2612) */ typedef struct ym2203_f { FM_OPN OPN; /* OPN state */ /* FMSAMPLE *Buf;*/ /* sound buffer */ FM_CH CH[3]; /* channel state */ } YM2203; /* here's the virtual YM2610 */ typedef struct ym2610_f { FM_OPN OPN; /* OPN state */ /* FMSAMPLE *Buf[YM2610_NUMBUF];*/ /* sound buffer */ FM_CH CH[6]; /* channel state */ int address1; /* address register1 */ /**** ADPCM control ****/ char *pcmbuf[2]; unsigned int pcm_size[2]; int *TL_adpcmb; ADPCM_CH adpcm[7]; /* normal ADPCM & deltaT ADPCM */ unsigned int adpcmreg[2][0x30]; int port0state, port0control, port0shift; int port1state, port1control, port1shift; unsigned char adpcm_arrivedEndAddress,adpcm_statusmask; } YM2610; /* here's the virtual YM2608 */ typedef YM2610 YM2608; /* here's the virtual YM2612 */ typedef struct ym2612_f { FM_OPN OPN; /* OPN state */ /* FMSAMPLE *Buf[YM2612_NUMBUF];*/ /* sound buffer */ FM_CH CH[6]; /* channel state */ int address1; /* address register1 */ /* dac output (YM2612) */ int dacen; int dacout; } YM2612; /* here's the virtual YM2151(OPM) */ typedef struct ym2151_f { /* FMSAMPLE *Buf[YM2151_NUMBUF];*//* sound buffers */ FM_ST ST; /* general state */ FM_CH CH[8]; /* channel state */ unsigned char NReg; /* noise enable,freq */ unsigned char pmd; /* LFO pmd level */ unsigned char amd; /* LFO amd level */ unsigned char ctw; /* CT0,1 and waveform */ unsigned int KC_TABLE[8*12*64+950];/* keycode,keyfunction -> count */ void (*PortWrite)(int offset,int data);/* callback when write CT0/CT1 */ } YM2151; /* -------------------- tables --------------------- */ /* key scale level */ /* !!!!! preliminary !!!!! */ #define DV (1/EG_STEP) static const unsigned char KSL[32]= { #if 1 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 #else 0.000/DV , 0.000/DV , 0.000/DV , 0.000/DV , /* OCT 0 */ 0.000/DV , 0.000/DV , 0.000/DV , 1.875/DV , /* OCT 1 */ 0.000/DV , 0.000/DV , 3.000/DV , 4.875/DV , /* OCT 2 */ 0.000/DV , 3.000/DV , 6.000/DV , 7.875/DV , /* OCT 3 */ 0.000/DV , 6.000/DV , 9.000/DV ,10.875/DV , /* OCT 4 */ 0.000/DV , 9.000/DV ,12.000/DV ,13.875/DV , /* OCT 5 */ 0.000/DV ,12.000/DV ,15.000/DV ,16.875/DV , /* OCT 6 */ 0.000/DV ,15.000/DV ,18.000/DV ,19.875/DV /* OCT 7 */ #endif }; #undef DV /* OPN key frequency number -> key code follow table */ /* fnum higher 4bit -> keycode lower 2bit */ static const char OPN_FKTABLE[16]={0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; static const int KC_TO_SEMITONE[16]={ /*translate note code KC into more usable number of semitone*/ 0*64, 1*64, 2*64, 3*64, 3*64, 4*64, 5*64, 6*64, 6*64, 7*64, 8*64, 9*64, 9*64,10*64,11*64,12*64 }; static const int DT2_TABLE[4]={ /* 4 DT2 values */ /* * DT2 defines offset in cents from base note * * The table below defines offset in deltas table... * User's Manual page 22 * Values below were calculated using formula: value = orig.val * 1.5625 * * DT2=0 DT2=1 DT2=2 DT2=3 * 0 600 781 950 */ 0, 384, 500, 608 }; /* sustain lebel table (3db per step) */ /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ #define SC(db) (db*((3/EG_STEP)*(1< max ) val = max; else if ( val < min ) val = min; return val; } /* status set and IRQ handling */ INLINE void FM_STATUS_SET(FM_ST *ST,int flag) { /* set status flag */ ST->status |= flag; if ( !(ST->irq) && (ST->status & ST->irqmask) ) { ST->irq = 1; /* callback user interrupt handler (IRQ is OFF to ON) */ if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,1); } } /* status reset and IRQ handling */ INLINE void FM_STATUS_RESET(FM_ST *ST,int flag) { /* reset status flag */ ST->status &=~flag; if ( (ST->irq) && !(ST->status & ST->irqmask) ) { ST->irq = 0; /* callback user interrupt handler (IRQ is ON to OFF) */ if(ST->IRQ_Handler) (ST->IRQ_Handler)(ST->index,0); } } /* IRQ mask set */ INLINE void FM_IRQMASK_SET(FM_ST *ST,int flag) { ST->irqmask = flag; /* IRQ handling check */ FM_STATUS_SET(ST,0); FM_STATUS_RESET(ST,0); } /* ----- key on ----- */ INLINE void FM_KEYON(FM_CH *CH , int s ) { FM_SLOT *SLOT = &CH->SLOT[s]; if( SLOT->evm<= ENV_MOD_RR) { /* set envelope counter from envleope output */ /* sin wave restart */ SLOT->Cnt = 0; if( s == SLOT1 ) CH->op1_out = 0; /* set attack */ #ifdef SEG_SUPPORT if( SLOT->SEG&8 ) ENV_SSG_AR; else #endif SLOT->evm = ENV_MOD_AR; SLOT->evs = SLOT->evsa; #if 0 /* convert decay count to attack count */ /* --- This caused the problem by credit sound of paper boy. --- */ SLOT->evc = EG_AST + DRAR_TABLE[ENV_CURVE[SLOT->evc>>ENV_BITS]];/* + SLOT->evs;*/ #else /* reset attack counter */ SLOT->evc = EG_AST; #endif SLOT->eve = EG_AED; } } /* ----- key off ----- */ INLINE void FM_KEYOFF(FM_CH *CH , int s ) { FM_SLOT *SLOT = &CH->SLOT[s]; if( SLOT->evm > ENV_MOD_RR) { /* set envelope counter from envleope output */ SLOT->evm = ENV_MOD_RR; if( !(SLOT->evc&EG_DST) ) SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<eve = EG_DED; SLOT->evs = SLOT->evsr; } } /* ---------- calcrate Envelope Generator & Phase Generator ---------- */ /* return : envelope output */ INLINE signed int FM_CALC_SLOT( FM_SLOT *SLOT ) { /* calcrate phage generator */ SLOT->Cnt += SLOT->Incr; /* calcrate envelope generator */ if( (SLOT->evc+=SLOT->evs) >= SLOT->eve ) { switch( SLOT->evm ){ case ENV_MOD_AR: /* ATTACK -> DECAY1 */ /* next DR */ SLOT->evm = ENV_MOD_DR; SLOT->evc = EG_DST; SLOT->eve = SLOT->SL; SLOT->evs = SLOT->evsd; break; case ENV_MOD_DR: /* DECAY -> SUSTAIN */ SLOT->evm = ENV_MOD_SR; SLOT->evc = SLOT->SL; SLOT->eve = EG_DED; SLOT->evs = SLOT->evss; break; case ENV_MOD_RR: /* RR -> OFF & STOP */ SLOT->evm = ENV_MOD_OFF; case ENV_MOD_SR: /* SR -> OFF & STOP */ SLOT->evc = EG_OFF; SLOT->eve = EG_OFF+1; SLOT->evs = 0; break; #ifdef SEG_SUPPORT case ENV_SSG_AR: /* SSG ATTACK */ if( SLOT->SEG&4){ /* start direction */ /* next SSG-SR (upside start ) */ SLOT->evm = ENV_SSG_SR; SLOT->evc = SLOT->SL + (EG_UST - EG_DST); SLOT->eve = EG_UED; SLOT->evs = SLOT->evss; }else{ /* next SSG-DR (downside start ) */ SLOT->evm = ENV_SSG_DR; SLOT->evc = EG_DST; SLOT->eve = EG_DED; SLOT->evs = SLOT->evsd; } break; case ENV_SSG_DR: /* SEG down side */ if( SLOT->SEG&2){ /* reverce */ SLOT->evm = ENV_SSG_SR; SLOT->evc = SLOT->SL + (EG_UST - EG_DST); SLOT->eve = EG_UED; SLOT->evs = SLOT->evss; }else{ /* again */ SLOT->evc = EG_DST; } /* hold */ if( SLOT->SEG&1) SLOT->evs = 0; break; case ENV_SSG_SR: /* upside */ if( SLOT->SEG&2){ /* reverce */ SLOT->evm = ENV_SSG_DR; SLOT->evc = EG_DST; SLOT->eve = EG_DED; SLOT->evs = SLOT->evsd; }else{ /* again */ SLOT->evc = SLOT->SL + (EG_UST - EG_DST); } /* hold check */ if( SLOT->SEG&1) SLOT->evs = 0; break; #endif } } /* calcrate envelope */ #if 0 /* ifdef TL_SAVE_MEM */ signed int env_out = SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]; /* LFO_out[SLOT->AMS] */ if(env_out >= (EG_ENT-1) ) return EG_ENT-1; return env_out; #else return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]; /* LFO_out[SLOT->AMS] */ #endif } /* set algorythm connection */ static void set_algorythm( FM_CH *CH ) { signed int *carrier = &outd[CH->PAN]; /* setup connect algorythm */ switch( CH->ALGO ){ case 0: /* PG---S1---S2---S3---S4---OUT */ CH->connect1 = &feedback2; CH->connect2 = &feedback3; CH->connect3 = &feedback4; break; case 1: /* PG---S1-+-S3---S4---OUT */ /* PG---S2-+ */ CH->connect1 = &feedback3; CH->connect2 = &feedback3; CH->connect3 = &feedback4; break; case 2: /* PG---S1------+-S4---OUT */ /* PG---S2---S3-+ */ CH->connect1 = &feedback4; CH->connect2 = &feedback3; CH->connect3 = &feedback4; break; case 3: /* PG---S1---S2-+-S4---OUT */ /* PG---S3------+ */ CH->connect1 = &feedback2; CH->connect2 = &feedback4; CH->connect3 = &feedback4; break; case 4: /* PG---S1---S2-+--OUT */ /* PG---S3---S4-+ */ CH->connect1 = &feedback2; CH->connect2 = carrier; CH->connect3 = &feedback4; break; case 5: /* +-S2-+ */ /* PG---S1-+-S3-+-OUT */ /* +-S4-+ */ CH->connect1 = 0; /* special mark */ CH->connect2 = carrier; CH->connect3 = carrier; break; case 6: /* PG---S1---S2-+ */ /* PG--------S3-+-OUT */ /* PG--------S4-+ */ CH->connect1 = &feedback2; CH->connect2 = carrier; CH->connect3 = carrier; break; case 7: /* PG---S1-+ */ /* PG---S2-+-OUT */ /* PG---S3-+ */ /* PG---S4-+ */ CH->connect1 = carrier; CH->connect2 = carrier; CH->connect3 = carrier; } CH->connect4 = carrier; } /* set detune & multiple */ INLINE void set_det_mul(FM_ST *ST,FM_CH *CH,FM_SLOT *SLOT,int v) { SLOT->mul = MUL_TABLE[v&0x0f]; SLOT->DT = ST->DT_TABLE[(v>>4)&7]; CH->SLOT[SLOT1].Incr=-1; } /* set total level */ INLINE void set_tl(FM_CH *CH,FM_SLOT *SLOT , int v,int csmflag) { v &= 0x7f; v = (v<<7)|v; /* 7bit -> 14bit */ SLOT->TL = (v*EG_ENT)>>14; if( !csmflag ) { /* not CSM latch total level */ SLOT->TLL = SLOT->TL + KSL[CH->kcode]; } } /* set attack rate & key scale */ INLINE void set_ar_ksr(FM_CH *CH,FM_SLOT *SLOT,int v,signed int *ar_table) { SLOT->KSR = 3-(v>>6); SLOT->AR = (v&=0x1f) ? &ar_table[v<<1] : RATE_0; SLOT->evsa = SLOT->AR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa; CH->SLOT[SLOT1].Incr=-1; } /* set decay rate */ INLINE void set_dr(FM_SLOT *SLOT,int v,signed int *dr_table) { SLOT->DR = (v&=0x1f) ? &dr_table[v<<1] : RATE_0; SLOT->evsd = SLOT->DR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd; } /* set sustain rate */ INLINE void set_sr(FM_SLOT *SLOT,int v,signed int *dr_table) { SLOT->SR = (v&=0x1f) ? &dr_table[v<<1] : RATE_0; SLOT->evss = SLOT->SR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_SR ) SLOT->evs = SLOT->evss; } /* set release rate */ INLINE void set_sl_rr(FM_SLOT *SLOT,int v,signed int *dr_table) { SLOT->SL = SL_TABLE[(v>>4)]; SLOT->RR = &dr_table[((v&0x0f)<<2)|2]; SLOT->evsr = SLOT->RR[SLOT->ksr]; if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr; } /* operator output calcrator */ #define OP_OUT(slot,env,con) SIN_TABLE[((slot.Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env] /* ---------- calcrate one of channel ---------- */ INLINE void FM_CALC_CH( FM_CH *CH ) { int op_out; int env_out; feedback2 = feedback3 = feedback4 = 0; /* SLOT 1 */ env_out=FM_CALC_SLOT(&CH->SLOT[SLOT1]); if( env_out < EG_ENT-1 ) { if( CH->FB ){ /* with self feed back */ op_out = CH->op1_out; CH->op1_out = OP_OUT(CH->SLOT[SLOT1],env_out,(CH->op1_out>>CH->FB) /* +LFOOut[SLOT->AMS]*/ ); op_out = (op_out + CH->op1_out)/2; }else{ /* without self feed back */ op_out = OP_OUT(CH->SLOT[SLOT1],env_out,0 /* +LFOOut[SLOT->AMS]*/ ); } /* output slot1 */ if( !CH->connect1 ) { /* algorythm 5 */ feedback2 = feedback3 = feedback4 = op_out; }else{ /* other algorythm */ *CH->connect1 += op_out; } } /* SLOT 2 */ env_out=FM_CALC_SLOT(&CH->SLOT[SLOT2]); if( env_out < EG_ENT-1 ) *CH->connect2 += OP_OUT(CH->SLOT[SLOT2],env_out, feedback2 /* +LFOOut[SLOT->AMS]*/ ); /* SLOT 3 */ env_out=FM_CALC_SLOT(&CH->SLOT[SLOT3]); if( env_out < EG_ENT-1 ) *CH->connect3 += OP_OUT(CH->SLOT[SLOT3],env_out, feedback3 /* +LFOOut[SLOT->AMS]*/ ); /* SLOT 4 */ env_out=FM_CALC_SLOT(&CH->SLOT[SLOT4]); if( env_out < EG_ENT-1 ) *CH->connect4 += OP_OUT(CH->SLOT[SLOT4],env_out, feedback4 /* +LFOOut[SLOT->AMS]*/ ); } /* ---------- frequency counter for operater update ---------- */ INLINE void CALC_FCSLOT(FM_SLOT *SLOT , int fc , int kc ) { int ksr; /* frequency step counter */ SLOT->Incr= (fc+SLOT->DT[kc])*SLOT->mul; ksr = kc >> SLOT->KSR; if( SLOT->ksr != ksr ) { SLOT->ksr = ksr; /* attack , decay rate recalcration */ SLOT->evsa = SLOT->AR[ksr]; SLOT->evsd = SLOT->DR[ksr]; SLOT->evss = SLOT->SR[ksr]; SLOT->evsr = SLOT->RR[ksr]; } SLOT->TLL = SLOT->TL + KSL[kc]; } /* ---------- frequency counter ---------- */ INLINE void CALC_FCOUNT(FM_CH *CH ) { if( CH->SLOT[SLOT1].Incr==-1){ int fc = CH->fc; int kc = CH->kcode; CALC_FCSLOT(&CH->SLOT[SLOT1] , fc , kc ); CALC_FCSLOT(&CH->SLOT[SLOT2] , fc , kc ); CALC_FCSLOT(&CH->SLOT[SLOT3] , fc , kc ); CALC_FCSLOT(&CH->SLOT[SLOT4] , fc , kc ); } } /* ---------- frequency counter ---------- */ INLINE void OPM_CALC_FCOUNT(YM2151 *OPM , FM_CH *CH ) { if( CH->SLOT[SLOT1].Incr==-1) { int fc = CH->fc; int kc = CH->kcode; CALC_FCSLOT(&CH->SLOT[SLOT1] , OPM->KC_TABLE[fc + CH->SLOT[SLOT1].DT2] , kc ); CALC_FCSLOT(&CH->SLOT[SLOT2] , OPM->KC_TABLE[fc + CH->SLOT[SLOT2].DT2] , kc ); CALC_FCSLOT(&CH->SLOT[SLOT3] , OPM->KC_TABLE[fc + CH->SLOT[SLOT3].DT2] , kc ); CALC_FCSLOT(&CH->SLOT[SLOT4] , OPM->KC_TABLE[fc + CH->SLOT[SLOT4].DT2] , kc ); } } /* ----------- initialize time tabls ----------- */ static void init_timetables( FM_ST *ST , char *DTTABLE , int ARRATE , int DRRATE ) { int i,d; double rate; /* make detune table */ for (d = 0;d <= 3;d++){ for (i = 0;i <= 31;i++){ rate = (double)DTTABLE[d*32 + i] * ST->freqbase / 4096 * FREQ_RATE; ST->DT_TABLE[d][i] = rate; ST->DT_TABLE[d+4][i] = -rate; } } /* make attack rate & decay rate tables */ for (i = 0;i < 4;i++) ST->AR_TABLE[i] = ST->DR_TABLE[i] = 0; for (i = 4;i < 64;i++){ rate = (double)ST->freqbase / 4096.0; /* frequency rate */ if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */ rate *= (double)(EG_ENT<AR_TABLE[i] = rate / ARRATE; ST->DR_TABLE[i] = rate / DRRATE; } ST->AR_TABLE[62] = EG_AED-1; ST->AR_TABLE[63] = EG_AED-1; for (i = 64;i < 94 ;i++){ /* make for overflow area */ ST->AR_TABLE[i] = ST->AR_TABLE[63]; ST->DR_TABLE[i] = ST->DR_TABLE[63]; } #if 0 for (i = 0;i < 64 ;i++){ /* make for overflow area */ Log(LOG_WAR,"rate %2d , ar %f ms , dr %f ms \n",i, ((double)(EG_ENT<AR_TABLE[i]) * (1000.0 / ST->rate), ((double)(EG_ENT<DR_TABLE[i]) * (1000.0 / ST->rate) ); } #endif } /* ---------- reset one of channel ---------- */ static void reset_channel( FM_ST *ST , FM_CH *CH , int chan ) { int c,s; ST->mode = 0; /* normal mode */ FM_STATUS_RESET(ST,0xff); ST->TA = 0; ST->TAC = 0; ST->TB = 0; ST->TBC = 0; for( c = 0 ; c < chan ; c++ ) { CH[c].fc = 0; CH[c].PAN = OPN_CENTER; /* or OPM_CENTER */ for(s = 0 ; s < 4 ; s++ ) { CH[c].SLOT[s].SEG = 0; CH[c].SLOT[s].evm = ENV_MOD_OFF; CH[c].SLOT[s].evc = EG_OFF; CH[c].SLOT[s].eve = EG_OFF+1; CH[c].SLOT[s].evs = 0; } } } /* ---------- generic table initialize ---------- */ static int FMInitTable( void ) { int s,t; double rate; int i,j; double pom; /* allocate total level table */ TL_TABLE = malloc(TL_MAX*2*sizeof(int)); if( TL_TABLE == 0 ) return 0; /* make total level table */ for (t = 0;t < EG_ENT-1 ;t++){ rate = ((1< voltage */ TL_TABLE[ t] = (int)rate; TL_TABLE[TL_MAX+t] = -TL_TABLE[t]; /* Log(LOG_INF,"TotalLevel(%3d) = %x\n",t,TL_TABLE[t]);*/ } /* fill volume off area */ for ( t = EG_ENT-1; t < TL_MAX ;t++){ TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0; } /* make sinwave table (total level offet) */ /* degree 0 = degree 180 = off */ SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1]; for (s = 1;s <= SIN_ENT/4;s++){ pom = sin(2*PI*s/SIN_ENT); /* sin */ pom = 20*log10(1/pom); /* decibel */ j = pom / EG_STEP; /* TL_TABLE steps */ /* degree 0 - 90 , degree 180 - 90 : plus section */ SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j]; /* degree 180 - 270 , degree 360 - 270 : minus section */ SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j]; /* Log(LOG_INF,"sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP);*/ } /* envelope counter -> envelope output table */ for (i=0; i= EG_ENT ) pom = EG_ENT-1; */ ENV_CURVE[i] = (int)pom; /* DECAY ,RELEASE curve */ ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i; #ifdef SEG_SUPPORT /* DECAY UPSIDE (SSG ENV) */ ENV_CURVE[(EG_UST>>ENV_BITS)+i]= EG_ENT-1-i; #endif } /* off */ ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1; /* decay to reattack envelope converttable */ j = EG_ENT-1; for (i=0; i>ENV_BITS] ); */ } return 1; } static void FMCloseTable( void ) { if( TL_TABLE ) free( TL_TABLE ); return; } /* OPN/OPM Mode Register Write */ INLINE void FMSetMode( FM_ST *ST ,int n,int v ) { /* b7 = CSM MODE */ /* b6 = 3 slot mode */ /* b5 = reset b */ /* b4 = reset a */ /* b3 = timer enable b */ /* b2 = timer enable a */ /* b1 = load b */ /* b0 = load a */ ST->mode = v; /* reset Timer b flag */ if( v & 0x20 ) FM_STATUS_RESET(ST,0x02); /* reset Timer a flag */ if( v & 0x10 ) FM_STATUS_RESET(ST,0x01); /* load b */ if( v & 0x02 ) { if( ST->TBC == 0 ) { ST->TBC = ( 256-ST->TB)<<4; /* External timer handler */ // if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,(double)ST->TBC,ST->TimerBase); } }else if (ST->timermodel == FM_TIMER_INTERVAL) { /* stop interbval timer */ if( ST->TBC != 0 ) { ST->TBC = 0; // if (ST->Timer_Handler) (ST->Timer_Handler)(n,1,0,ST->TimerBase); } } /* load a */ if( v & 0x01 ) { if( ST->TAC == 0 ) { ST->TAC = (1024-ST->TA); /* External timer handler */ // if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,(double)ST->TAC,ST->TimerBase); } }else if (ST->timermodel == FM_TIMER_INTERVAL) { /* stop interbval timer */ if( ST->TAC != 0 ) { ST->TAC = 0; // if (ST->Timer_Handler) (ST->Timer_Handler)(n,0,0,ST->TimerBase); } } } /* Timer A Overflow */ INLINE void TimerAOver(FM_ST *ST) { /* status set if enabled */ if(ST->mode & 0x04) FM_STATUS_SET(ST,0x01); /* clear or reload the counter */ if (ST->timermodel == FM_TIMER_INTERVAL) { ST->TAC = (1024-ST->TA); // if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,0,(double)ST->TAC,ST->TimerBase); } else ST->TAC = 0; } /* Timer B Overflow */ INLINE void TimerBOver(FM_ST *ST) { /* status set if enabled */ if(ST->mode & 0x08) FM_STATUS_SET(ST,0x02); /* clear or reload the counter */ if (ST->timermodel == FM_TIMER_INTERVAL) { ST->TBC = ( 256-ST->TB)<<4; // if (ST->Timer_Handler) (ST->Timer_Handler)(ST->index,1,(double)ST->TBC,ST->TimerBase); } else ST->TBC = 0; } /* CSM Key Controll */ INLINE void CSMKeyControll(FM_CH *CH) { int ksl = KSL[CH->kcode]; /* all key off */ FM_KEYOFF(CH,SLOT1); FM_KEYOFF(CH,SLOT2); FM_KEYOFF(CH,SLOT3); FM_KEYOFF(CH,SLOT4); /* total level latch */ CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + ksl; CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + ksl; CH->SLOT[SLOT3].TLL = CH->SLOT[SLOT3].TL + ksl; CH->SLOT[SLOT4].TLL = CH->SLOT[SLOT4].TL + ksl; /* all key on */ FM_KEYON(CH,SLOT1); FM_KEYON(CH,SLOT2); FM_KEYON(CH,SLOT3); FM_KEYON(CH,SLOT4); } #ifdef INTERNAL_TIMER /* ---------- calcrate timer A ---------- */ INLINE void CALC_TIMER_A( FM_ST *ST , FM_CH *CSM_CH ){ if( ST->TAC && (ST->Timer_Handler==0) ) if( (ST->TAC -= ST->freqbase) <= 0 ){ TimerAOver( ST ); /* CSM mode key,TL controll */ if( ST->mode & 0x80 ){ /* CSM mode total level latch and auto key on */ CSMKeyControll( CSM_CH ); } } } /* ---------- calcrate timer B ---------- */ INLINE void CALC_TIMER_B( FM_ST *ST,int step){ if( ST->TBC && (ST->Timer_Handler==0) ) if( (ST->TBC -= ST->freqbase*step) <= 0 ){ TimerBOver( ST ); } } #endif /* INTERNAL_TIMER */ #if BUILD_OPN /* ---------- priscaler set(and make time tables) ---------- */ void OPNSetPris(FM_OPN *OPN , int pris , int TimerPris, int SSGpris) { int fn; /* frequency base */ OPN->ST.freqbase = (OPN->ST.rate) ? ((double)OPN->ST.clock * 4096.0 / OPN->ST.rate) / pris : 0; /* Timer base time */ OPN->ST.TimerBase = (OPN->ST.rate) ? 1.0/((double)OPN->ST.clock / (double)TimerPris) : 0; /* SSG part priscaler set */ //if( SSGpris ) SSGClk( OPN->ST.index, OPN->ST.clock * 2 / SSGpris ); /* make time tables */ init_timetables( &OPN->ST , OPN_DTTABLE , OPN_ARRATE , OPN_DRRATE ); /* make fnumber -> increment counter table */ for( fn=0 ; fn < 2048 ; fn++ ) { /* it is freq table for octave 7 */ /* opn freq counter = 20bit */ OPN->FN_TABLE[fn] = (double)fn * OPN->ST.freqbase / 4096 * FREQ_RATE * (1<<7) / 2; } /* Log(LOG_INF,"OPN %d set priscaler %d\n",OPN->ST.index,pris);*/ } /* ---------- write a OPN mode register 0x20-0x2f ---------- */ static void OPNWriteMode(FM_OPN *OPN, int r, int v) { unsigned char c; FM_CH *CH; switch(r){ case 0x21: /* Test */ break; case 0x22: /* LFO FREQ (YM2608/YM2612) */ /* 3.98Hz,5.56Hz,6.02Hz,6.37Hz,6.88Hz,9.63Hz,48.1Hz,72.2Hz */ /* FM2608[n].LFOIncr = FM2608[n].LFO_TABLE[v&0x0f]; */ break; case 0x24: /* timer A High 8*/ OPN->ST.TA = (OPN->ST.TA & 0x03)|(((int)v)<<2); break; case 0x25: /* timer A Low 2*/ OPN->ST.TA = (OPN->ST.TA & 0x3fc)|(v&3); break; case 0x26: /* timer B */ OPN->ST.TB = v; break; case 0x27: /* mode , timer controll */ FMSetMode( &(OPN->ST),OPN->ST.index,v ); break; case 0x28: /* key on / off */ c = v&0x03; if( c == 3 ) break; if( (v&0x04) && (OPN->type & TYPE_6CH) ) c+=3; CH = OPN->P_CH; CH = &CH[c]; /* csm mode */ if( c == 2 && (OPN->ST.mode & 0x80) ) break; if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1); if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2); if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3); if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4); /* Log(LOG_INF,"OPN %d:%d : KEY %02X\n",n,c,v&0xf0);*/ break; } } /* ---------- write a OPN register (0x30-0xff) ---------- */ static void OPNWriteReg(FM_OPN *OPN, int r, int v) { unsigned char c; FM_CH *CH; FM_SLOT *SLOT; /* 0x30 - 0xff */ if( (c = OPN_CHAN(r)) == 3 ) return; /* 0xX3,0xX7,0xXB,0xXF */ if( (r >= 0x100) /* && (OPN->type & TYPE_6CH) */ ) c+=3; CH = OPN->P_CH; CH = &CH[c]; SLOT = &(CH->SLOT[OPN_SLOT(r)]); switch( r & 0xf0 ) { case 0x30: /* DET , MUL */ set_det_mul(&OPN->ST,CH,SLOT,v); break; case 0x40: /* TL */ set_tl(CH,SLOT,v,(c == 2) && (OPN->ST.mode & 0x80) ); break; case 0x50: /* KS, AR */ set_ar_ksr(CH,SLOT,v,OPN->ST.AR_TABLE); break; case 0x60: /* DR */ /* bit7 = AMS ENABLE(YM2612) */ set_dr(SLOT,v,OPN->ST.DR_TABLE); break; case 0x70: /* SR */ set_sr(SLOT,v,OPN->ST.DR_TABLE); break; case 0x80: /* SL, RR */ set_sl_rr(SLOT,v,OPN->ST.DR_TABLE); break; case 0x90: /* SSG-EG */ #ifndef SEG_SUPPORT if(v&0x08) Log(LOG_ERR,"OPN %d,%d,%d :SSG-TYPE envelope selected (not supported )\n",OPN->ST.index,c,OPN_SLOT(r)); #endif SLOT->SEG = v&0x0f; break; case 0xa0: switch( OPN_SLOT(r) ){ case 0: /* 0xa0-0xa2 : FNUM1 */ { unsigned int fn = (((unsigned int)( (CH->fn_h)&7))<<8) + v; unsigned char blk = CH->fn_h>>3; /* make keyscale code */ CH->kcode = (blk<<2)|OPN_FKTABLE[(fn>>7)]; /* make basic increment counter 32bit = 1 cycle */ CH->fc = OPN->FN_TABLE[fn]>>(7-blk); CH->SLOT[SLOT1].Incr=-1; } break; case 1: /* 0xa4-0xa6 : FNUM2,BLK */ CH->fn_h = v&0x3f; break; case 2: /* 0xa8-0xaa : 3CH FNUM1 */ if( r < 0x100) { unsigned int fn = (((unsigned int)(OPN->SL3.fn_h[c]&7))<<8) + v; unsigned char blk = OPN->SL3.fn_h[c]>>3; /* make keyscale code */ OPN->SL3.kcode[c]= (blk<<2)|OPN_FKTABLE[(fn>>7)]; /* make basic increment counter 32bit = 1 cycle */ OPN->SL3.fc[c] = OPN->FN_TABLE[fn]>>(7-blk); (OPN->P_CH)[2].SLOT[SLOT1].Incr=-1; } break; case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ if( r < 0x100) OPN->SL3.fn_h[c] = v&0x3f; break; } break; case 0xb0: switch( OPN_SLOT(r) ){ case 0: /* 0xb0-0xb2 : FB,ALGO */ { int feedback = (v>>3)&7; CH->ALGO = v&7; CH->FB = feedback ? 8 - feedback : 0; set_algorythm( CH ); } break; case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2608) */ if( OPN->type & TYPE_LFOPAN) { /* b0-2 PMS */ /* 0,3.4,6.7,10,14,20,40,80(cent) */ SLOT->pms = (v>>4) & 0x07; /* b4-5 AMS */ /* 0,1.4,5.9,11.8(dB) */ SLOT->ams = v & 0x03; /* PAN */ CH->PAN = (v>>6)&0x03; /* PAN : b6 = R , b7 = L */ set_algorythm( CH ); /* Log(LOG_INF,"OPN %d,%d : PAN %d\n",n,c,CH->PAN);*/ } break; } break; } } #endif /* BUILD_OPN */ #if BUILD_YM2203 /*******************************************************************************/ /* YM2203 local section */ /*******************************************************************************/ static YM2203 *FM2203=NULL; /* array of YM2203's */ /* ---------- update one of chip ----------- */ void YM2203UpdateOne(int num, void *buffer, int length) { YM2203 *F2203 = &(FM2203[num]); FM_OPN *OPN = &(FM2203[num].OPN); int i,ch; int data; FMSAMPLE *buf = (FMSAMPLE *)buffer; State = &F2203->OPN.ST; cch[0] = &F2203->CH[0]; cch[1] = &F2203->CH[1]; cch[2] = &F2203->CH[2]; /* frequency counter channel A */ CALC_FCOUNT( cch[0] ); /* frequency counter channel B */ CALC_FCOUNT( cch[1] ); /* frequency counter channel C */ if( (State->mode & 0xc0) ){ /* 3SLOT MODE */ if( cch[2]->SLOT[SLOT1].Incr==-1){ /* 3 slot mode */ CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode ); } }else CALC_FCOUNT( cch[2] ); for( i=0; i < length ; i++ ) { /* channel A channel B channel C */ outd[OPN_CENTER] = 0; /* calcrate FM */ for( ch=0;ch<3;ch++) FM_CALC_CH( cch[ch] ); /* limit check */ data = Limit( outd[OPN_CENTER] , OPN_MAXOUT, OPN_MINOUT ); /* store to sound buffer */ buf[i] = data >> OPN_OUTSB; #ifdef INTERNAL_TIMER /* timer controll */ CALC_TIMER_A( State , cch[2] ); #endif } #ifdef INTERNAL_TIMER CALC_TIMER_B( State , length ); #endif } /* ---------- reset one of chip ---------- */ void YM2203ResetChip(int num) { int i; FM_OPN *OPN = &(FM2203[num].OPN); /* Reset Priscaler */ OPNSetPris( OPN , 6*12 , 6*12 ,4); /* 1/6 , 1/4 */ /* reset SSG section */ //SSGReset(OPN->ST.index); /* status clear */ FM_IRQMASK_SET(&OPN->ST,0x03); OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ reset_channel( &OPN->ST , FM2203[num].CH , 3 ); /* reset OPerator paramater */ for(i = 0xb6 ; i >= 0xb4 ; i-- ) OPNWriteReg(OPN,i,0xc0); /* PAN RESET */ for(i = 0xb2 ; i >= 0x30 ; i-- ) OPNWriteReg(OPN,i,0); for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); } #if 0 /* ---------- return the buffer ---------- */ FMSAMPLE *YM2203Buffer(int n) { return FM2203[n].Buf; } /* ---------- set buffer ---------- */ int YM2203SetBuffer(int n, FMSAMPLE *buf) { if( buf == 0 ) return -1; FM2203[n].Buf = buf; return 0; } #endif /* ---------- Initialize YM2203 emulator(s) ---------- */ /* 'num' is the number of virtual YM2203's to allocate */ /* 'rate' is sampling rate and 'bufsiz' is the size of the */ /* buffer that should be updated at each interval */ int YM2203Init(int num, int clock, int rate, FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler) { int i; if (FM2203) return (-1); /* duplicate init. */ cur_chip = NULL; /* hiro-shi!! */ FMNumChips = num; /* allocate ym2203 state space */ if( (FM2203 = (YM2203 *)malloc(sizeof(YM2203) * FMNumChips))==NULL) return (-1); /* clear */ memset(FM2203,0,sizeof(YM2203) * FMNumChips); /* allocate total level table (128kb space) */ if( !FMInitTable() ) { free( FM2203 ); return (-1); } for ( i = 0 ; i < FMNumChips; i++ ) { FM2203[i].OPN.ST.index = i; FM2203[i].OPN.type = TYPE_YM2203; FM2203[i].OPN.P_CH = FM2203[i].CH; FM2203[i].OPN.ST.clock = clock; FM2203[i].OPN.ST.rate = rate; /* FM2203[i].OPN.ST.irq = 0; */ /* FM2203[i].OPN.ST.satus = 0; */ FM2203[i].OPN.ST.timermodel = FM_TIMER_SINGLE; /* Extend handler */ FM2203[i].OPN.ST.Timer_Handler = TimerHandler; FM2203[i].OPN.ST.IRQ_Handler = IRQHandler; YM2203ResetChip(i); } return(0); } /* ---------- shut down emurator ----------- */ void YM2203Shutdown(void) { if (!FM2203) return; FMCloseTable(); free(FM2203); FM2203 = NULL; } /* ---------- YM2203 I/O interface ---------- */ int YM2203Write(int n,int a,int v) { FM_OPN *OPN = &(FM2203[n].OPN); if( !(a&1) ) { /* address port */ OPN->ST.address = v & 0xff; /* Write register to SSG emurator */ //if( v < 16 ) SSGWrite(n,0,v); switch(OPN->ST.address) { case 0x2d: /* divider sel */ OPNSetPris( OPN, 6*12, 6*12 ,4); /* OPN 1/6 , SSG 1/4 */ break; case 0x2e: /* divider sel */ OPNSetPris( OPN, 3*12, 3*12,2); /* OPN 1/3 , SSG 1/2 */ break; case 0x2f: /* divider sel */ OPNSetPris( OPN, 2*12, 2*12,1); /* OPN 1/2 , SSG 1/1 */ break; } } else { /* data port */ int addr = OPN->ST.address; switch( addr & 0xf0 ) { case 0x00: /* 0x00-0x0f : SSG section */ /* Write data to SSG emurator */ //SSGWrite(n,a,v); break; case 0x20: /* 0x20-0x2f : Mode section */ //YM2203UpdateReq(n); /* write register */ OPNWriteMode(OPN,addr,v); break; default: /* 0x30-0xff : OPN section */ //YM2203UpdateReq(n); /* write register */ OPNWriteReg(OPN,addr,v); } } return OPN->ST.irq; } unsigned char YM2203Read(int n,int a) { YM2203 *F2203 = &(FM2203[n]); int addr = F2203->OPN.ST.address; int ret = 0; if( !(a&1) ) { /* status port */ ret = F2203->OPN.ST.status; } else { /* data port (ONLY SSG) */ //if( addr < 16 ) ret = SSGRead(n); } return ret; } int YM2203TimerOver(int n,int c) { YM2203 *F2203 = &(FM2203[n]); if( c ) { /* Timer B */ TimerBOver( &(F2203->OPN.ST) ); } else { /* Timer A */ //YM2203UpdateReq(n); /* timer update */ TimerAOver( &(F2203->OPN.ST) ); /* CSM mode key,TL controll */ if( F2203->OPN.ST.mode & 0x80 ) { /* CSM mode total level latch and auto key on */ CSMKeyControll( &(F2203->CH[2]) ); } } return F2203->OPN.ST.irq; } #endif /* BUILD_YM2203 */ #if BUILD_YM2612 /*******************************************************************************/ /* YM2612 local section */ /*******************************************************************************/ static YM2612 *FM2612=NULL; /* array of YM2612's */ /* ---------- update one of chip ----------- */ void YM2612UpdateOne(int num, void **buffer, int length) { YM2612 *F2612 = &(FM2612[num]); FM_OPN *OPN = &(FM2612[num].OPN); int dataR,dataL; int i,ch; int dacen = F2612->dacen; int dacout = F2612->dacout; /* set bufer */ bufL = (FMSAMPLE *)buffer[0]; bufR = (FMSAMPLE *)buffer[1]; if( (void *)F2612 != cur_chip ){ cur_chip = (void *)F2612; State = &OPN->ST; cch[0] = &F2612->CH[0]; cch[1] = &F2612->CH[1]; cch[2] = &F2612->CH[2]; cch[3] = &F2612->CH[3]; cch[4] = &F2612->CH[4]; cch[5] = &F2612->CH[5]; } /* update frequency counter */ CALC_FCOUNT( cch[0] ); CALC_FCOUNT( cch[1] ); if( (State->mode & 0xc0) ){ /* 3SLOT MODE */ if( cch[2]->SLOT[SLOT1].Incr==-1){ /* 3 slot mode */ CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] ); CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] ); CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] ); CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode ); } }else CALC_FCOUNT( cch[2] ); CALC_FCOUNT( cch[3] ); CALC_FCOUNT( cch[4] ); CALC_FCOUNT( cch[5] ); /* buffering */ for( i=0; i < length ; i++ ) { /* clear output acc. */ outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0; /* calcrate channel output */ for( ch=0;ch<5;ch++) FM_CALC_CH( cch[ch] ); dacout=0; // dave temporary if( dacen ) *cch[5]->connect4 += dacout; else FM_CALC_CH( cch[5] ); /* get left & right output */ dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPN_MAXOUT, OPN_MINOUT ); dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPN_MAXOUT, OPN_MINOUT ); /* buffering */ #ifdef FM_STEREO_MIX /* stereo mixing */ /* stereo mix */ ((FMSAMPLE_MIX *)bufL)[i] += ((dataL>>OPN_OUTSB)<>OPN_OUTSB); #else /* stereo separate */ bufL[i] += ((dataL>>OPN_OUTSB)*3)>>2; // Dave: adds it in 3/4 bufR[i] += ((dataR>>OPN_OUTSB)*3)>>2; #endif #ifdef LFO_SUPPORT CALC_LOPM_LFO; #endif #ifdef INTERNAL_TIMER /* timer controll */ CALC_TIMER_A( State , cch[2] ); #endif } #ifdef INTERNAL_TIMER CALC_TIMER_B( State , length ); #endif } /* -------------------------- YM2612 ---------------------------------- */ int YM2612Init(int num, int clock, int rate, FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler) { int i,j; if (FM2612) return (-1); /* duplicate init. */ cur_chip = NULL; /* hiro-shi!! */ FMNumChips = num; /* allocate extend state space */ if( (FM2612 = (YM2612 *)malloc(sizeof(YM2612) * FMNumChips))==NULL) return (-1); /* clear */ memset(FM2612,0,sizeof(YM2612) * FMNumChips); /* allocate total level table (128kb space) */ if( !FMInitTable() ) { free( FM2612 ); return (-1); } for ( i = 0 ; i < FMNumChips; i++ ) { FM2612[i].OPN.ST.index = i; FM2612[i].OPN.type = TYPE_YM2612; FM2612[i].OPN.P_CH = FM2612[i].CH; FM2612[i].OPN.ST.clock = clock; FM2612[i].OPN.ST.rate = rate; /* FM2612[i].OPN.ST.irq = 0; */ /* FM2612[i].OPN.ST.status = 0; */ FM2612[i].OPN.ST.timermodel = FM_TIMER_SINGLE; /* Extend handler */ FM2612[i].OPN.ST.Timer_Handler = TimerHandler; FM2612[i].OPN.ST.IRQ_Handler = IRQHandler; YM2612ResetChip(i); } return 0; } /* ---------- shut down emurator ----------- */ void YM2612Shutdown() { if (!FM2612) return; FMCloseTable(); free(FM2612); FM2612 = NULL; } /* ---------- reset one of chip ---------- */ void YM2612ResetChip(int num) { int i; YM2612 *F2612 = &(FM2612[num]); FM_OPN *OPN = &(FM2612[num].OPN); OPNSetPris( OPN , 12*12, 12*12, 0); /* status clear */ FM_IRQMASK_SET(&OPN->ST,0x03); OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */ reset_channel( &OPN->ST , &F2612->CH[0] , 6 ); for(i = 0xb6 ; i >= 0xb4 ; i-- ) { OPNWriteReg(OPN,i ,0xc0); OPNWriteReg(OPN,i|0x100,0xc0); } for(i = 0xb2 ; i >= 0x30 ; i-- ) { OPNWriteReg(OPN,i ,0); OPNWriteReg(OPN,i|0x100,0); } for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0); /* DAC mode clear */ F2612->dacen = 0; } /* YM2612 write */ /* n = number */ /* a = address */ /* v = value */ int YM2612Write(int n, int a,int v) { YM2612 *F2612 = &(FM2612[n]); int addr; switch( a&3){ case 0: /* address port 0 */ F2612->OPN.ST.address = v & 0xff; break; case 1: /* data port 0 */ addr = F2612->OPN.ST.address; switch( addr & 0xf0 ) { case 0x20: /* 0x20-0x2f Mode */ switch( addr ) { case 0x2a: /* DAC data (YM2612) */ //YM2612UpdateReq(n); F2612->dacout = v<<(TL_BITS-8); { extern int mega_dacout; mega_dacout=v; } case 0x2b: /* DAC Sel (YM2612) */ /* b7 = dac enable */ F2612->dacen = v & 0x80; { extern int mega_dacen; mega_dacen=v&0x80; } break; default: /* OPN section */ //YM2612UpdateReq(n); /* write register */ OPNWriteMode(&(F2612->OPN),addr,v); } break; default: /* 0x30-0xff OPN section */ //YM2612UpdateReq(n); /* write register */ OPNWriteReg(&(F2612->OPN),addr,v); } break; case 2: /* address port 1 */ F2612->address1 = v & 0xff; break; case 3: /* data port 1 */ addr = F2612->address1; //YM2612UpdateReq(n); OPNWriteReg(&(F2612->OPN),addr|0x100,v); break; } return F2612->OPN.ST.irq; } unsigned char YM2612Read(int n,int a) { YM2612 *F2612 = &(FM2612[n]); int addr = F2612->OPN.ST.address; switch( a&3){ case 0: /* status 0 */ return F2612->OPN.ST.status; case 1: case 2: case 3: Log(LOG_WAR,"YM2612 #%d:A=%d read unmapped area\n"); return F2612->OPN.ST.status; } return 0; } int YM2612TimerOver(int n,int c) { YM2612 *F2612 = &(FM2612[n]); if( c ) { /* Timer B */ TimerBOver( &(F2612->OPN.ST) ); } else { /* Timer A */ //YM2612UpdateReq(n); /* timer update */ TimerAOver( &(F2612->OPN.ST) ); /* CSM mode key,TL controll */ if( F2612->OPN.ST.mode & 0x80 ) { /* CSM mode total level latch and auto key on */ CSMKeyControll( &(F2612->CH[2]) ); } } return F2612->OPN.ST.irq; } #if 0 /* ---------- set buffer ---------- */ int YM2612SetBuffer(int n, FMSAMPLE **buf ) { int i; for( i = 0 ; i < YM2612_NUMBUF ; i++){ FM2612[n].Buf[i] = buf[i]; if( cur_chip == &FM2612[n] ) cur_chip = NULL; } return 0; } #endif #endif /* BUILD_YM2612 */ dgen-sdl-1.23/sn76496.c 644 1750 1750 16767 7027317555 7535 /*************************************************************************** sn76496.c Routines to emulate the Texas Instruments SN76489 / SN76496 programmable tone /noise generator. Also known as (or at least compatible with) TMS9919. Noise emulation is not accurate due to lack of documentation. The noise generator uses a shift register with a XOR-feedback network, but the exact layout is unknown. It can be set for either period or white noise; again, the details are unknown. ***************************************************************************/ ///// commented out by starshine //#include "driver.h" ///// added by starshine #include "sn76496.h" #define MAX_OUTPUT 0x7fff #define AUDIO_CONV(A) (A) #define STEP 0x10000 /* Formulas for noise generator */ /* bit0 = output */ /* noise feedback for white noise mode */ #define FB_WNOISE 0x12000 /* bit15.d(16bits) = bit0(out) ^ bit2 */ //#define FB_WNOISE 0x14000 /* bit15.d(16bits) = bit0(out) ^ bit1 */ //#define FB_WNOISE 0x28000 /* bit16.d(17bits) = bit0(out) ^ bit2 (same to AY-3-8910) */ //#define FB_WNOISE 0x50000 /* bit17.d(18bits) = bit0(out) ^ bit2 */ /* noise feedback for periodic noise mode */ /* it is correct maybe (it was in the Megadrive sound manual) */ //#define FB_PNOISE 0x10000 /* 16bit rorate */ #define FB_PNOISE 0x08000 /* JH 981127 - fixes Do Run Run */ /* noise generator start preset (for periodic noise) */ #define NG_PRESET 0x0f35 struct SN76496 { int Channel; int SampleRate; unsigned int UpdateStep; int VolTable[16]; /* volume table */ int Register[8]; /* registers */ int LastRegister; /* last register written */ int Volume[4]; /* volume of voice 0-2 and noise */ unsigned int RNG; /* noise generator */ int NoiseFB; /* noise feedback mask */ int Period[4]; int Count[4]; int Output[4]; }; static struct SN76496 sn[MAX_76496]; void SN76496Write(int chip,int data) { struct SN76496 *R = &sn[chip]; /* update the output buffer before changing the registers */ ///// commented out by starshine //stream_update(R->Channel,0); if (data & 0x80) { int r = (data & 0x70) >> 4; int c = r/2; R->LastRegister = r; R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); switch (r) { case 0: /* tone 0 : frequency */ case 2: /* tone 1 : frequency */ case 4: /* tone 2 : frequency */ R->Period[c] = R->UpdateStep * R->Register[r]; if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; if (r == 4) { /* update noise shift frequency */ if ((R->Register[6] & 0x03) == 0x03) R->Period[3] = 2 * R->Period[2]; } break; case 1: /* tone 0 : volume */ case 3: /* tone 1 : volume */ case 5: /* tone 2 : volume */ case 7: /* noise : volume */ R->Volume[c] = R->VolTable[data & 0x0f]; break; case 6: /* noise : frequency, mode */ { int n = R->Register[6]; R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; n &= 3; /* N/512,N/1024,N/2048,Tone #3 output */ R->Period[3] = (n == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+n)); /* reset noise shifter */ R->RNG = NG_PRESET; R->Output[3] = R->RNG & 1; } break; } } else { int r = R->LastRegister; int c = r/2; switch (r) { case 0: /* tone 0 : frequency */ case 2: /* tone 1 : frequency */ case 4: /* tone 2 : frequency */ R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4); R->Period[c] = R->UpdateStep * R->Register[r]; if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; if (r == 4) { /* update noise shift frequency */ if ((R->Register[6] & 0x03) == 0x03) R->Period[3] = 2 * R->Period[2]; } break; } } } void SN76496_0_w(int offset,int data) { SN76496Write(0,data); } void SN76496_1_w(int offset,int data) { SN76496Write(1,data); } void SN76496_2_w(int offset,int data) { SN76496Write(2,data); } void SN76496_3_w(int offset,int data) { SN76496Write(3,data); } void SN76496Update_8(int chip,void *buffer,int length) { #define DATATYPE unsigned char #define DATACONV(A) AUDIO_CONV((A) / (STEP * 256)) #include "sn76496u.c" #undef DATATYPE #undef DATACONV } void SN76496Update_16(int chip,void *buffer,int length) { #define DATATYPE unsigned short #define DATACONV(A) ((A) / STEP) #include "sn76496u.c" #undef DATATYPE #undef DATACONV } void SN76496_set_clock(int chip,int clock) { struct SN76496 *R = &sn[chip]; /* the base clock for the tone generators is the chip clock divided by 16; */ /* for the noise generator, it is clock / 256. */ /* Here we calculate the number of steps which happen during one sample */ /* at the given sample rate. No. of events = sample rate / (clock/16). */ /* STEP is a multiplier used to turn the fraction into a fixed point */ /* number. */ R->UpdateStep = ((double)STEP * R->SampleRate * 16) / clock; } static void SN76496_set_volume(int chip,int volume,int gain) { struct SN76496 *R = &sn[chip]; int i; double out; ///// commented out by starshine //stream_set_volume(R->Channel,volume); gain &= 0xff; /* increase max output basing on gain (0.2 dB per step) */ out = MAX_OUTPUT / 3; while (gain-- > 0) out *= 1.023292992; /* = (10 ^ (0.2/20)) */ /* build volume table (2dB per step) */ for (i = 0;i < 15;i++) { /* limit volume to avoid clipping */ if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3; else R->VolTable[i] = out; out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */ } R->VolTable[15] = 0; } int SN76496_init(int chip,int clock,int sample_rate,int sample_bits) { int i; struct SN76496 *R = &sn[chip]; char name[40]; ////// commented out by starshine //sprintf(name,"SN76496 #%d",chip); //R->Channel = stream_init(msound, // name,sample_rate,sample_bits, // chip,(sample_bits == 16) ? SN76496Update_16 : SN76496Update_8); if (R->Channel == -1) return 1; R->SampleRate = sample_rate; SN76496_set_clock(chip,clock); SN76496_set_volume(chip,255,0); for (i = 0;i < 4;i++) R->Volume[i] = 0; R->LastRegister = 0; for (i = 0;i < 8;i+=2) { R->Register[i] = 0; R->Register[i + 1] = 0x0f; /* volume = 0 */ } for (i = 0;i < 4;i++) { R->Output[i] = 0; R->Period[i] = R->Count[i] = R->UpdateStep; } R->RNG = NG_PRESET; R->Output[3] = R->RNG & 1; return 0; } int SN76496_sh_start() { ///// total commenting out by starshine //int chip; //const struct SN76496interface *intf = msound->sound_interface; //for (chip = 0;chip < intf->num;chip++) //{ // if (SN76496_init(msound,chip,intf->baseclock,Machine->sample_rate,Machine->sample_bits) != 0) // return 1; // SN76496_set_volume(chip,intf->volume[chip] & 0xff,(intf->volume[chip] >> 8) & 0xff); //} return 0; } dgen-sdl-1.23/ras.cpp 644 1750 1750 65343 7027317555 7614 // DGen/SDL v1.16+ // New raster effects engine // I'd like to thank the Mac folks for giving me a good template to work from. // This is just a cheap rehash of their code, except friendlier to other bit // depths. :) I also put in a few little optimizations, like blank checking // and especially the sprites. #include #include #include "md.h" // This is marked each time the palette is updated. Handy for the 8bpp // implementation, so we don't waste time changing the palette unnecessarily. int pal_dirty; // Macros, to route draw_tile and draw_tile_solid to the right handler #define draw_tile(which, line, where) \ switch(Bpp)\ {\ case 1:\ draw_tile1((which),(line),(where)); break;\ case 2:\ draw_tile2((which),(line),(where)); break;\ case 3:\ draw_tile3((which),(line),(where)); break;\ case 4:\ draw_tile4((which),(line),(where)); break;\ } #define draw_tile_solid(which, line, where) \ switch(Bpp)\ {\ case 1:\ draw_tile1_solid((which),(line),(where)); break;\ case 2:\ draw_tile2_solid((which),(line),(where)); break;\ case 3:\ draw_tile3_solid((which),(line),(where)); break;\ case 4:\ draw_tile4_solid((which),(line),(where)); break;\ } // Silly utility function, get a big-endian word #ifdef WORDS_BIGENDIAN static inline int get_word(unsigned char *where) { return (int)(*(unsigned short*)where); } #else static inline int get_word(unsigned char *where) { return (where[0] << 8) | where[1]; } #endif // Tile pixel masks #ifdef WORDS_BIGENDIAN # define PIXEL0 (0xf0000000) # define PIXEL1 (0x0f000000) # define PIXEL2 (0x00f00000) # define PIXEL3 (0x000f0000) # define PIXEL4 (0x0000f000) # define PIXEL5 (0x00000f00) # define PIXEL6 (0x000000f0) # define PIXEL7 (0x0000000f) # define SHIFT0 (28) # define SHIFT1 (24) # define SHIFT2 (20) # define SHIFT3 (16) # define SHIFT4 (12) # define SHIFT5 ( 8) # define SHIFT6 ( 4) # define SHIFT7 ( 0) #else // WORDS_BIGENDIAN # define PIXEL0 (0x000000f0) # define PIXEL1 (0x0000000f) # define PIXEL2 (0x0000f000) # define PIXEL3 (0x00000f00) # define PIXEL4 (0x00f00000) # define PIXEL5 (0x000f0000) # define PIXEL6 (0xf0000000) # define PIXEL7 (0x0f000000) # define SHIFT0 ( 4) # define SHIFT1 ( 0) # define SHIFT2 (12) # define SHIFT3 ( 8) # define SHIFT4 (20) # define SHIFT5 (16) # define SHIFT6 (28) # define SHIFT7 (24) #endif // WORDS_BIGENDIAN #ifdef ASM_TILES extern "C" { void _asm_tiles_init(unsigned char *vram, unsigned char *reg, unsigned *highpal); void _drawtile1(int which, int line, unsigned char *where); void _drawtile1_solid(int which, int line, unsigned char *where); void _drawtile2(int which, int line, unsigned char *where); void _drawtile2_solid(int which, int line, unsigned char *where); void _drawtile3(int which, int line, unsigned char *where); void _drawtile3_solid(int which, int line, unsigned char *where); void _drawtile4(int which, int line, unsigned char *where); void _drawtile4_solid(int which, int line, unsigned char *where); } // Pass off these calls to assembler counterparts inline void md_vdp::draw_tile1_solid(int which, int line, unsigned char *where) { _drawtile1_solid(which, line, where); } inline void md_vdp::draw_tile1(int which, int line, unsigned char *where) { _drawtile1(which, line, where); } inline void md_vdp::draw_tile2_solid(int which, int line, unsigned char *where) { _drawtile2_solid(which, line, where); } inline void md_vdp::draw_tile2(int which, int line, unsigned char *where) { _drawtile2(which, line, where); } inline void md_vdp::draw_tile3_solid(int which, int line, unsigned char *where) { _drawtile3_solid(which, line, where); } inline void md_vdp::draw_tile3(int which, int line, unsigned char *where) { _drawtile3(which, line, where); } inline void md_vdp::draw_tile4_solid(int which, int line, unsigned char *where) { _drawtile4_solid(which, line, where); } inline void md_vdp::draw_tile4(int which, int line, unsigned char *where) { _drawtile4(which, line, where); } #else // ASM_TILES // Blit tile solidly, for 1 byte-per-pixel inline void md_vdp::draw_tile1_solid(int which, int line, unsigned char *where) { unsigned tile, pal; pal = (which >> 9 & 0x30); // Determine which 16-color palette if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // Blit the tile! if(which & 0x800) // x flipped { *(where ) = ((tile & PIXEL7)>>SHIFT7) | pal; *(where+1) = ((tile & PIXEL6)>>SHIFT6) | pal; *(where+2) = ((tile & PIXEL5)>>SHIFT5) | pal; *(where+3) = ((tile & PIXEL4)>>SHIFT4) | pal; *(where+4) = ((tile & PIXEL3)>>SHIFT3) | pal; *(where+5) = ((tile & PIXEL2)>>SHIFT2) | pal; *(where+6) = ((tile & PIXEL1)>>SHIFT1) | pal; *(where+7) = ((tile & PIXEL0)>>SHIFT0) | pal; } else { *(where ) = ((tile & PIXEL0)>>SHIFT0) | pal; *(where+1) = ((tile & PIXEL1)>>SHIFT1) | pal; *(where+2) = ((tile & PIXEL2)>>SHIFT2) | pal; *(where+3) = ((tile & PIXEL3)>>SHIFT3) | pal; *(where+4) = ((tile & PIXEL4)>>SHIFT4) | pal; *(where+5) = ((tile & PIXEL5)>>SHIFT5) | pal; *(where+6) = ((tile & PIXEL6)>>SHIFT6) | pal; *(where+7) = ((tile & PIXEL7)>>SHIFT7) | pal; } } // Blit tile, leaving color zero transparent, for 1 byte per pixel inline void md_vdp::draw_tile1(int which, int line, unsigned char *where) { unsigned tile, pal; pal = (which >> 9 & 0x30); // Determine which 16-color palette if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // If the tile is all 0's, why waste the time? if(!tile) return; // Blit the tile! if(which & 0x800) // x flipped { if(tile & PIXEL7) *(where ) = ((tile & PIXEL7)>>SHIFT7) | pal; if(tile & PIXEL6) *(where+1) = ((tile & PIXEL6)>>SHIFT6) | pal; if(tile & PIXEL5) *(where+2) = ((tile & PIXEL5)>>SHIFT5) | pal; if(tile & PIXEL4) *(where+3) = ((tile & PIXEL4)>>SHIFT4) | pal; if(tile & PIXEL3) *(where+4) = ((tile & PIXEL3)>>SHIFT3) | pal; if(tile & PIXEL2) *(where+5) = ((tile & PIXEL2)>>SHIFT2) | pal; if(tile & PIXEL1) *(where+6) = ((tile & PIXEL1)>>SHIFT1) | pal; if(tile & PIXEL0) *(where+7) = ((tile & PIXEL0)>>SHIFT0) | pal; } else { if(tile & PIXEL0) *(where ) = ((tile & PIXEL0)>>SHIFT0) | pal; if(tile & PIXEL1) *(where+1) = ((tile & PIXEL1)>>SHIFT1) | pal; if(tile & PIXEL2) *(where+2) = ((tile & PIXEL2)>>SHIFT2) | pal; if(tile & PIXEL3) *(where+3) = ((tile & PIXEL3)>>SHIFT3) | pal; if(tile & PIXEL4) *(where+4) = ((tile & PIXEL4)>>SHIFT4) | pal; if(tile & PIXEL5) *(where+5) = ((tile & PIXEL5)>>SHIFT5) | pal; if(tile & PIXEL6) *(where+6) = ((tile & PIXEL6)>>SHIFT6) | pal; if(tile & PIXEL7) *(where+7) = ((tile & PIXEL7)>>SHIFT7) | pal; } } // Blit tile solidly, for 2 byte-per-pixel inline void md_vdp::draw_tile2_solid(int which, int line, unsigned char *where) { unsigned tile, temp, *pal; unsigned short *wwhere = (unsigned short*)where; pal = highpal + (which >> 9 & 0x30); // Determine which 16-color palette temp = *pal; *pal = highpal[reg[7]&0x3f]; // Get background color if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // Blit the tile! if(which & 0x800) // x flipped { *(wwhere ) = pal[((tile & PIXEL7)>>SHIFT7)]; *(wwhere+1) = pal[((tile & PIXEL6)>>SHIFT6)]; *(wwhere+2) = pal[((tile & PIXEL5)>>SHIFT5)]; *(wwhere+3) = pal[((tile & PIXEL4)>>SHIFT4)]; *(wwhere+4) = pal[((tile & PIXEL3)>>SHIFT3)]; *(wwhere+5) = pal[((tile & PIXEL2)>>SHIFT2)]; *(wwhere+6) = pal[((tile & PIXEL1)>>SHIFT1)]; *(wwhere+7) = pal[((tile & PIXEL0)>>SHIFT0)]; } else { *(wwhere ) = pal[((tile & PIXEL0)>>SHIFT0)]; *(wwhere+1) = pal[((tile & PIXEL1)>>SHIFT1)]; *(wwhere+2) = pal[((tile & PIXEL2)>>SHIFT2)]; *(wwhere+3) = pal[((tile & PIXEL3)>>SHIFT3)]; *(wwhere+4) = pal[((tile & PIXEL4)>>SHIFT4)]; *(wwhere+5) = pal[((tile & PIXEL5)>>SHIFT5)]; *(wwhere+6) = pal[((tile & PIXEL6)>>SHIFT6)]; *(wwhere+7) = pal[((tile & PIXEL7)>>SHIFT7)]; } // Restore the original color *pal = temp; } // Blit tile, leaving color zero transparent, for 2 byte per pixel inline void md_vdp::draw_tile2(int which, int line, unsigned char *where) { unsigned tile, *pal; unsigned short *wwhere = (unsigned short*)where; pal = highpal + (which >> 9 & 0x30); // Determine which 16-color palette if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // If the tile is all 0's, why waste the time? if(!tile) return; // Blit the tile! if(which & 0x800) // x flipped { if(tile & PIXEL7) *(wwhere ) = pal[((tile & PIXEL7)>>SHIFT7)]; if(tile & PIXEL6) *(wwhere+1) = pal[((tile & PIXEL6)>>SHIFT6)]; if(tile & PIXEL5) *(wwhere+2) = pal[((tile & PIXEL5)>>SHIFT5)]; if(tile & PIXEL4) *(wwhere+3) = pal[((tile & PIXEL4)>>SHIFT4)]; if(tile & PIXEL3) *(wwhere+4) = pal[((tile & PIXEL3)>>SHIFT3)]; if(tile & PIXEL2) *(wwhere+5) = pal[((tile & PIXEL2)>>SHIFT2)]; if(tile & PIXEL1) *(wwhere+6) = pal[((tile & PIXEL1)>>SHIFT1)]; if(tile & PIXEL0) *(wwhere+7) = pal[((tile & PIXEL0)>>SHIFT0)]; } else { if(tile & PIXEL0) *(wwhere ) = pal[((tile & PIXEL0)>>SHIFT0)]; if(tile & PIXEL1) *(wwhere+1) = pal[((tile & PIXEL1)>>SHIFT1)]; if(tile & PIXEL2) *(wwhere+2) = pal[((tile & PIXEL2)>>SHIFT2)]; if(tile & PIXEL3) *(wwhere+3) = pal[((tile & PIXEL3)>>SHIFT3)]; if(tile & PIXEL4) *(wwhere+4) = pal[((tile & PIXEL4)>>SHIFT4)]; if(tile & PIXEL5) *(wwhere+5) = pal[((tile & PIXEL5)>>SHIFT5)]; if(tile & PIXEL6) *(wwhere+6) = pal[((tile & PIXEL6)>>SHIFT6)]; if(tile & PIXEL7) *(wwhere+7) = pal[((tile & PIXEL7)>>SHIFT7)]; } } inline void md_vdp::draw_tile3_solid(int which, int line, unsigned char *where) { unsigned tile; unsigned char *pal; pal = ((unsigned char*)highpal) + (which >> 7 & 0xc0); // Determine 16-color palette if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // Blit the tile (this is UGLY! Do you know of a better way? :P) if(which & 0x800) { *(where ) = pal[((tile & 0x0f000000)>>22)+1]; *(where+1 ) = pal[((tile & 0x0f000000)>>22)+2]; *(where+2 ) = pal[((tile & 0x0f000000)>>22) ]; *(where+3 ) = pal[((tile & 0xf0000000)>>26)+1]; *(where+4 ) = pal[((tile & 0xf0000000)>>26)+2]; *(where+5 ) = pal[((tile & 0xf0000000)>>26) ]; *(where+6 ) = pal[((tile & 0x000f0000)>>14)+1]; *(where+7 ) = pal[((tile & 0x000f0000)>>14)+2]; *(where+8 ) = pal[((tile & 0x000f0000)>>14) ]; *(where+9 ) = pal[((tile & 0x00f00000)>>18)+1]; *(where+10) = pal[((tile & 0x00f00000)>>18)+2]; *(where+11) = pal[((tile & 0x00f00000)>>18) ]; *(where+12) = pal[((tile & 0x00000f00)>> 6)+1]; *(where+13) = pal[((tile & 0x00000f00)>> 6)+2]; *(where+14) = pal[((tile & 0x00000f00)>> 6) ]; *(where+15) = pal[((tile & 0x0000f000)>>10)+1]; *(where+16) = pal[((tile & 0x0000f000)>>10)+2]; *(where+17) = pal[((tile & 0x0000f000)>>10) ]; *(where+18) = pal[((tile & 0x0000000f)<< 2)+1]; *(where+19) = pal[((tile & 0x0000000f)<< 2)+2]; *(where+20) = pal[((tile & 0x0000000f)<< 2) ]; *(where+21) = pal[((tile & 0x000000f0)>> 2)+1]; *(where+22) = pal[((tile & 0x000000f0)>> 2)+2]; *(where+23) = pal[((tile & 0x000000f0)>> 2) ]; } else { *(where ) = pal[((tile & 0x000000f0)>> 2)+1]; *(where+ 1) = pal[((tile & 0x000000f0)>> 2)+2]; *(where+ 2) = pal[((tile & 0x000000f0)>> 2) ]; *(where+ 3) = pal[((tile & 0x0000000f)<< 2)+1]; *(where+ 4) = pal[((tile & 0x0000000f)<< 2)+2]; *(where+ 5) = pal[((tile & 0x0000000f)<< 2) ]; *(where+ 6) = pal[((tile & 0x0000f000)>>10)+1]; *(where+ 7) = pal[((tile & 0x0000f000)>>10)+2]; *(where+ 8) = pal[((tile & 0x0000f000)>>10) ]; *(where+ 9) = pal[((tile & 0x00000f00)>> 6)+1]; *(where+10) = pal[((tile & 0x00000f00)>> 6)+2]; *(where+11) = pal[((tile & 0x00000f00)>> 6) ]; *(where+12) = pal[((tile & 0x00f00000)>>18)+1]; *(where+13) = pal[((tile & 0x00f00000)>>18)+2]; *(where+14) = pal[((tile & 0x00f00000)>>18) ]; *(where+15) = pal[((tile & 0x000f0000)>>14)+1]; *(where+16) = pal[((tile & 0x000f0000)>>14)+2]; *(where+17) = pal[((tile & 0x000f0000)>>14) ]; *(where+18) = pal[((tile & 0xf0000000)>>26)+1]; *(where+19) = pal[((tile & 0xf0000000)>>26)+2]; *(where+20) = pal[((tile & 0xf0000000)>>26) ]; *(where+21) = pal[((tile & 0x0f000000)>>22)+1]; *(where+22) = pal[((tile & 0x0f000000)>>22)+2]; *(where+23) = pal[((tile & 0x0f000000)>>22) ]; } } inline void md_vdp::draw_tile3(int which, int line, unsigned char *where) { unsigned tile; unsigned char *pal; pal = ((unsigned char*)highpal) + (which >> 7 & 0xc0); // Determine 16-color palette if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // If it's empty, why waste the time? if(!tile) return; // Blit the tile (this is UGLY! Do you know of a better way? :P) if(which & 0x800) { // The numbers are a little wierd, because of little endian. *gag* // Thanks Intel! if(tile & 0x0f000000) { *(where ) = pal[((tile & 0x0f000000)>>22)+1]; *(where+1 ) = pal[((tile & 0x0f000000)>>22)+2]; *(where+2 ) = pal[((tile & 0x0f000000)>>22) ]; } if(tile & 0xf0000000) { *(where+3 ) = pal[((tile & 0xf0000000)>>26)+1]; *(where+4 ) = pal[((tile & 0xf0000000)>>26)+2]; *(where+5 ) = pal[((tile & 0xf0000000)>>26) ]; } if(tile & 0x000f0000) { *(where+6 ) = pal[((tile & 0x000f0000)>>14)+1]; *(where+7 ) = pal[((tile & 0x000f0000)>>14)+2]; *(where+8 ) = pal[((tile & 0x000f0000)>>14) ]; } if(tile & 0x00f00000) { *(where+9 ) = pal[((tile & 0x00f00000)>>18)+1]; *(where+10) = pal[((tile & 0x00f00000)>>18)+2]; *(where+11) = pal[((tile & 0x00f00000)>>18) ]; } if(tile & 0x00000f00) { *(where+12) = pal[((tile & 0x00000f00)>> 6)+1]; *(where+13) = pal[((tile & 0x00000f00)>> 6)+2]; *(where+14) = pal[((tile & 0x00000f00)>> 6) ]; } if(tile & 0x0000f000) { *(where+15) = pal[((tile & 0x0000f000)>>10)+1]; *(where+16) = pal[((tile & 0x0000f000)>>10)+2]; *(where+17) = pal[((tile & 0x0000f000)>>10) ]; } if(tile & 0x0000000f) { *(where+18) = pal[((tile & 0x0000000f)<< 2)+1]; *(where+19) = pal[((tile & 0x0000000f)<< 2)+2]; *(where+20) = pal[((tile & 0x0000000f)<< 2) ]; } if(tile & 0x000000f0) { *(where+21) = pal[((tile & 0x000000f0)>> 2)+1]; *(where+22) = pal[((tile & 0x000000f0)>> 2)+2]; *(where+23) = pal[((tile & 0x000000f0)>> 2) ]; } } else { if(tile & 0x000000f0) { *(where ) = pal[((tile & 0x000000f0)>> 2)+1]; *(where+ 1) = pal[((tile & 0x000000f0)>> 2)+2]; *(where+ 2) = pal[((tile & 0x000000f0)>> 2) ]; } if(tile & 0x0000000f) { *(where+ 3) = pal[((tile & 0x0000000f)<< 2)+1]; *(where+ 4) = pal[((tile & 0x0000000f)<< 2)+2]; *(where+ 5) = pal[((tile & 0x0000000f)<< 2) ]; } if(tile & 0x0000f000) { *(where+ 6) = pal[((tile & 0x0000f000)>>10)+1]; *(where+ 7) = pal[((tile & 0x0000f000)>>10)+2]; *(where+ 8) = pal[((tile & 0x0000f000)>>10) ]; } if(tile & 0x00000f00) { *(where+ 9) = pal[((tile & 0x00000f00)>> 6)+1]; *(where+10) = pal[((tile & 0x00000f00)>> 6)+2]; *(where+11) = pal[((tile & 0x00000f00)>> 6) ]; } if(tile & 0x00f00000) { *(where+12) = pal[((tile & 0x00f00000)>>18)+1]; *(where+13) = pal[((tile & 0x00f00000)>>18)+2]; *(where+14) = pal[((tile & 0x00f00000)>>18) ]; } if(tile & 0x000f0000) { *(where+15) = pal[((tile & 0x000f0000)>>14)+1]; *(where+16) = pal[((tile & 0x000f0000)>>14)+2]; *(where+17) = pal[((tile & 0x000f0000)>>14) ]; } if(tile & 0xf0000000) { *(where+18) = pal[((tile & 0xf0000000)>>26)+1]; *(where+19) = pal[((tile & 0xf0000000)>>26)+2]; *(where+20) = pal[((tile & 0xf0000000)>>26) ]; } if(tile & 0x0f000000) { *(where+21) = pal[((tile & 0x0f000000)>>22)+1]; *(where+22) = pal[((tile & 0x0f000000)>>22)+2]; *(where+23) = pal[((tile & 0x0f000000)>>22) ]; } } } // Blit tile solidly, for 4 byte-per-pixel inline void md_vdp::draw_tile4_solid(int which, int line, unsigned char *where) { unsigned tile, temp, *pal; unsigned *wwhere = (unsigned*)where; pal = highpal + (which >> 9 & 0x30); // Determine which 16-color palette temp = *pal; *pal = highpal[reg[7]&0x3f]; // Get background color if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // Blit the tile! if(which & 0x800) // x flipped { *(wwhere ) = pal[((tile & PIXEL7)>>SHIFT7)]; *(wwhere+1) = pal[((tile & PIXEL6)>>SHIFT6)]; *(wwhere+2) = pal[((tile & PIXEL5)>>SHIFT5)]; *(wwhere+3) = pal[((tile & PIXEL4)>>SHIFT4)]; *(wwhere+4) = pal[((tile & PIXEL3)>>SHIFT3)]; *(wwhere+5) = pal[((tile & PIXEL2)>>SHIFT2)]; *(wwhere+6) = pal[((tile & PIXEL1)>>SHIFT1)]; *(wwhere+7) = pal[((tile & PIXEL0)>>SHIFT0)]; } else { *(wwhere ) = pal[((tile & PIXEL0)>>SHIFT0)]; *(wwhere+1) = pal[((tile & PIXEL1)>>SHIFT1)]; *(wwhere+2) = pal[((tile & PIXEL2)>>SHIFT2)]; *(wwhere+3) = pal[((tile & PIXEL3)>>SHIFT3)]; *(wwhere+4) = pal[((tile & PIXEL4)>>SHIFT4)]; *(wwhere+5) = pal[((tile & PIXEL5)>>SHIFT5)]; *(wwhere+6) = pal[((tile & PIXEL6)>>SHIFT6)]; *(wwhere+7) = pal[((tile & PIXEL7)>>SHIFT7)]; } // Restore the original color *pal = temp; } // Blit tile, leaving color zero transparent, for 4 byte per pixel inline void md_vdp::draw_tile4(int which, int line, unsigned char *where) { unsigned tile, *pal; unsigned *wwhere = (unsigned*)where; pal = highpal + (which >> 9 & 0x30); // Determine which 16-color palette if(which & 0x1000) // y flipped line ^= 7; // take from the bottom, instead of the top if(reg[12] & 2) // interlace tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3)); else tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2)); // If the tile is all 0's, why waste the time? if(!tile) return; // Blit the tile! if(which & 0x800) // x flipped { if(tile & PIXEL7) *(wwhere ) = pal[((tile & PIXEL7)>>SHIFT7)]; if(tile & PIXEL6) *(wwhere+1) = pal[((tile & PIXEL6)>>SHIFT6)]; if(tile & PIXEL5) *(wwhere+2) = pal[((tile & PIXEL5)>>SHIFT5)]; if(tile & PIXEL4) *(wwhere+3) = pal[((tile & PIXEL4)>>SHIFT4)]; if(tile & PIXEL3) *(wwhere+4) = pal[((tile & PIXEL3)>>SHIFT3)]; if(tile & PIXEL2) *(wwhere+5) = pal[((tile & PIXEL2)>>SHIFT2)]; if(tile & PIXEL1) *(wwhere+6) = pal[((tile & PIXEL1)>>SHIFT1)]; if(tile & PIXEL0) *(wwhere+7) = pal[((tile & PIXEL0)>>SHIFT0)]; } else { if(tile & PIXEL0) *(wwhere ) = pal[((tile & PIXEL0)>>SHIFT0)]; if(tile & PIXEL1) *(wwhere+1) = pal[((tile & PIXEL1)>>SHIFT1)]; if(tile & PIXEL2) *(wwhere+2) = pal[((tile & PIXEL2)>>SHIFT2)]; if(tile & PIXEL3) *(wwhere+3) = pal[((tile & PIXEL3)>>SHIFT3)]; if(tile & PIXEL4) *(wwhere+4) = pal[((tile & PIXEL4)>>SHIFT4)]; if(tile & PIXEL5) *(wwhere+5) = pal[((tile & PIXEL5)>>SHIFT5)]; if(tile & PIXEL6) *(wwhere+6) = pal[((tile & PIXEL6)>>SHIFT6)]; if(tile & PIXEL7) *(wwhere+7) = pal[((tile & PIXEL7)>>SHIFT7)]; } } #endif // ASM_TILES // Draw the window (front or back) void md_vdp::draw_window(int line, int front) { int size; int x, y, w, start; int pl, add; int total_window; unsigned char *where; int which; // Set everything up y = line >> 3; total_window = (y < (reg[18]&0x1f)) ^ (reg[18] >> 7); // Wide or narrow size = (reg[12] & 1)? 64 : 32; pl = (reg[3] << 10) + ((y&0x3f)*size*2); // Wide(320) or narrow(256)? if(reg[12] & 1) { w = 40; start = -8; } else { w = 32; start = 24; } add = -2; where = dest + (start * Bpp); for(x=-1; x= ((reg[17]&0x1f) << 1)) goto skip; } which = get_word(((unsigned char*)vram) + (pl+(add&((size-1)<<1)))); if((which>>15) == front) draw_tile(which, line&7, where); skip: add += 2; where += Bpp_times8; } } void md_vdp::draw_sprites(int line, int front) { unsigned which; int tx, ty, x, y, xend, ysize, yoff, i; unsigned char *where, *sprite; // Sprites have to be in reverse order :P for(i = sprite_count - 1; i >= 0; --i) { sprite = sprite_base + (sprite_order[i] << 3); // Get the first tile which = get_word(sprite + 4); // Only do it if it's on the right priority if((which >> 15) == front) { // Get the sprite's location y = get_word(sprite); x = get_word(sprite + 6) & 0x1ff; // Interlace? if(reg[12] & 2) y = (y & 0x3fe) >> 1; else y &= 0x1ff; x -= 0x80; y -= 0x80; yoff = (line - y); // Narrow mode? if(!(reg[12] & 1)) x += 32; xend = ((sprite[2] << 1) & 0x18) + x; ysize = sprite[2] & 0x3; // Render if this sprite's on this line if(xend > -8 && x < 320 && yoff >= 0 && yoff <= (ysize<<3)+7) { ty = yoff & 7; // y flipped? if(which & 0x1000) which += ysize - (yoff >> 3); else which += (yoff >> 3); ++ysize; // x flipped? if(which & 0x800) { where = dest + (xend * Bpp); for(tx = xend; tx >= x; tx -= 8) { if(tx > -8 && tx < 320) draw_tile(which, ty, where); which += ysize; where -= Bpp_times8; } } else { where = dest + (x * Bpp); for(tx = x; tx <= xend; tx += 8) { if(tx > -8 && tx < 320) draw_tile(which, ty, where); which += ysize; where += Bpp_times8; } } } } } } // The body for the next few functions is in an extraneous header file. // Phil, I hope I left enough in this file for GLOBAL to hack it right. ;) // Thanks to John Stiles for this trick :) void md_vdp::draw_plane_back0(int line) { #define FRONT 0 #define PLANE 0 #include "ras-drawplane.h" #undef PLANE #undef FRONT } void md_vdp::draw_plane_back1(int line) { #define FRONT 0 #define PLANE 1 #include "ras-drawplane.h" #undef PLANE #undef FRONT } void md_vdp::draw_plane_front0(int line) { #define FRONT 1 #define PLANE 0 #include "ras-drawplane.h" #undef PLANE #undef FRONT } void md_vdp::draw_plane_front1(int line) { #define FRONT 1 #define PLANE 1 #include "ras-drawplane.h" #undef PLANE #undef FRONT } // The main interface function, to generate a scanline void md_vdp::draw_scanline(struct bmap *bits, int line) { unsigned *ptr, i; // Set the destination in the bmap dest = bits->data + (bits->pitch * (line + 8) + 16); // If bytes per pixel hasn't yet been set, do it if(!Bpp) { if(bits->bpp <= 8) Bpp = 1; else if(bits->bpp <= 16) Bpp = 2; else if(bits->bpp <= 24) Bpp = 3; else Bpp = 4; Bpp_times8 = Bpp << 3; // used for tile blitting #ifdef ASM_TILES _asm_tiles_init(vram, reg, highpal); // pass these values to the asm tiles #endif } // If the palette's been changed, update it if(dirt[0x34] & 2) { ptr = highpal; // What color depth are we? switch(bits->bpp) { case 32: case 24: for(i = 0; i < 128; i += 2) *ptr++ = ((cram[i+1]&0x0e) << 20) | ((cram[i+1]&0xe0) << 8 ) | ((cram[i] &0x0e) << 4 ); break; case 16: for(i = 0; i < 128; i += 2) *ptr++ = ((cram[i+1]&0x0e) << 12) | ((cram[i+1]&0xe0) << 3 ) | ((cram[i] &0x0e) << 1 ); break; case 15: for(i = 0; i < 128; i += 2) *ptr++ = ((cram[i+1]&0x0e) << 11) | ((cram[i+1]&0xe0) << 2 ) | ((cram[i] &0x0e) << 1 ); break; case 8: default: // Let the hardware palette sort it out :P for(i = 0; i < 64; ++i) *ptr++ = i; } // Clean up the dirt dirt[0x34] &= ~2; pal_dirty = 1; } // Render the screen if it's turned on if(reg[1] & 0x40) { // Recalculate the sprite order, if it's dirty if((dirt[0x30] & 0x20) || (dirt[0x34] & 1)) { unsigned next = 0; // Find the sprite base in VRAM sprite_base = vram + (reg[5]<<9); // Order the sprites sprite_count = sprite_order[0] = 0; do { next = sprite_base[(next << 3) + 3]; sprite_order[++sprite_count] = next; // No more than 256 sprites/line, a reasonable limit ;) } while (next && sprite_count < 0x100); // Clean up the dirt dirt[0x30] &= ~0x20; dirt[0x34] &= ~1; } // Draw, from the bottom up // Low priority draw_plane_back1(line); draw_plane_back0(line); draw_window(line, 0); draw_sprites(line, 0); // High priority draw_plane_front1(line); draw_plane_front0(line); draw_window(line, 1); draw_sprites(line, 1); } else { // The display is off, paint it black // Do it a dword at a time unsigned *destl = (unsigned*)dest; for(i = 0; i < (80 * Bpp); ++i) destl[i] = 0; } // If we're in narrow (256) mode, cut off the messy edges if(!(reg[12] & 1)) { unsigned *destl = (unsigned*)dest; for(i = 0; i < Bpp_times8; ++i) destl[i] = destl[i + (72 * Bpp)] = 0; } } dgen-sdl-1.23/main.cpp 644 1750 1750 27731 7320414767 7751 // DGen/SDL 1.17 // by Joe Groff // Read LICENSE for copyright etc., but if you've seen one BSDish license, // you've seen them all ;) #include #include #include #include #include #include #include #include #include #include #include #define IS_MAIN_CPP #include "md.h" #include "pd.h" #include "pd-defs.h" #include "rc.h" #include "rc-vars.h" #ifdef __BEOS__ #include #endif // Ideal usec/frame for 60Hz #define USEC_FRAME_NTSC 16667 // 1000000/60 // Ideal usec/frame for 50Hz #define USEC_FRAME_PAL 20000 // 1000000/50 // Neat little macro to pick which one of the above :) #define USEC_FRAME (pal_mode? USEC_FRAME_PAL : USEC_FRAME_NTSC) // Defined in ras.cpp, and set to true if the Genesis palette's changed. extern int pal_dirty; int sound_is_okay = 0; FILE *debug_log = NULL; // Do a demo frame, if active #define DO_DEMO \ if(demo_record) { \ foo = htonl(megad.pad[0]); \ fwrite(&foo, sizeof(foo), 1, demo); \ foo = htonl(megad.pad[1]); \ fwrite(&foo, sizeof(foo), 1, demo); \ } if(demo_play) { \ fread(&foo, sizeof(foo), 1, demo); \ megad.pad[0] = ntohl(foo); \ fread(&foo, sizeof(foo), 1, demo); \ megad.pad[1] = ntohl(foo); \ if(feof(demo)) \ { \ pd_message("Demo finished."); \ demo_play = 0; \ } \ } // Convenience, so I don't have to type this constantly #define DO_FRAME(scr, pal) \ running = pd_handle_events(megad); \ DO_DEMO \ if (dgen_sound) { \ megad.one_frame((scr), (pal), &sndi); \ } else megad.one_frame((scr), (pal), NULL); // Directory to put savestates in static char saves[2048] = ""; // Directory to put battery RAM in static char ramdir[2048] = ""; // Temporary garbage can string :) static char temp[65536] = ""; // Get the basename from the ROM filename // An equivalent perl one-liner would be perl -pe 's@.*/([^.]*?)\..*@\1@' :) /* Modified: 20-11-1999 Dylan_G@bigfoot.com Made very much less evil. */ static char *gst_name(char *fn) { char buf[1024]; /* strtok modifies its arguments */ char *p = NULL, *p1 = NULL; memset(buf, 0, sizeof(buf)); strncpy(buf, fn, sizeof(buf)); if(strchr(buf, '.')) { /* Need to strip extension */ p = strtok(buf, "."); } if(strchr(buf, '/')) { /* Need to strip /path/name */ p = strtok(buf, "/"); /* We have to walk through until we hit NULL, then use N-1 pointer :-). */ while(p != NULL) { p1 = p; p = strtok(NULL, "/"); } } /* Fix in case there is no / in the filename */ if(p) p1 = p; return(p1); } // Show help and exit with code 2 static void help() { printf( "DGen/SDL v"VER"\n" "Usage: dgen [options] romname\n\n" "Where options are:\n" " -v Print version number and exit.\n" " -r RCFILE Read in the file RCFILE after parsing\n" " $HOME/.dgen/dgenrc.\n" " -n USEC Cuses dgen to sleep USEC microseconds per frame, to be\n" " nice to other processes.\n" " -p CODE,CODE... Takes a comma-delimited list of Game Genie (ABCD-EFGH)\n" " or Hex (123456:ABCD) codes to patch the ROM with.\n" " -R Set realtime priority -20, so no other processes may\n" " interrupt. dgen definitely needs root priviledges for\n" " this.\n" " -P Use PAL mode (50Hz) instead of normal NTSC (60Hz).\n" " -d DEMONAME Record a demo of the game you are playing.\n" " -D DEMONAME Play back a previously recorded demo.\n" " -s SLOT Load the saved state from the given slot at startup.\n" #ifdef JOYSTICK_SUPPORT " -j Use joystick if detected.\n" #endif ); // Display platform-specific options pd_help(); exit(2); } // Create the .dgen directory structure in the user's home directory static void mk_dgendir() { strcpy(temp, getenv("HOME")); strcat(temp, "/.dgen"); mkdir(temp, 0777); // Make save dir strcpy(saves, temp); strcat(saves, "/saves"); mkdir(saves, 0777); // Make ram dir strcpy(ramdir, temp); strcat(ramdir, "/ram"); mkdir(ramdir, 0777); } // Save/load states // It is externed from your implementation to change the current slot // (I know this is a hack :) int slot = 0; void md_save(md& megad) { FILE *save = NULL; sprintf(temp, "%s/%s.gs%d", saves, gst_name(megad.romfilename), slot); if((save = fopen(temp, "wb"))) { megad.export_gst(save); fclose(save); sprintf(temp, "Saved state to slot %d.", slot); pd_message(temp); } else { sprintf(temp, "Couldn't save state to slot %d!", slot); pd_message(temp); } } void md_load(md& megad) { FILE *load = NULL; sprintf(temp, "%s/%s.gs%d", saves, gst_name(megad.romfilename), slot); if((load = fopen(temp, "rb"))) { megad.import_gst(load); fclose(load); sprintf(temp, "Loaded state from slot %d.", slot); pd_message(temp); } else { sprintf(temp, "Couldn't load state from slot %d!", slot); pd_message(temp); } } // Load/save states from file static void ram_save(md& megad) { FILE *save = NULL; if(!megad.has_save_ram()) return; sprintf(temp, "%s/%s", ramdir, gst_name(megad.romfilename)); if((save = fopen(temp, "wb"))) { megad.put_save_ram(save); fclose(save); } else { fprintf(stderr, "Couldn't save battery RAM to %s!\n", temp); } } static void ram_load(md& megad) { FILE *load = NULL; if(!megad.has_save_ram()) return; sprintf(temp, "%s/%s", ramdir, gst_name(megad.romfilename)); if((load = fopen(temp, "rb"))) { megad.get_save_ram(load); fclose(load); } } int main(int argc, char *argv[]) { int c = 0, pal_mode = 0, running = 1, usec = 0, wp = 0, rp = 0, start_slot = -1; unsigned long long f = 0; char *patches = NULL, *rom = NULL; struct timeval oldclk, newclk, startclk, endclk; FILE *demo = NULL; int demo_record = 0, demo_play = 0, foo; // Parse the RC file parse_rc(NULL); // Check all our options strcpy(temp, "s:hvr:n:p:RPjd:D:"); strcat(temp, pd_options); while((c = getopt(argc, argv, temp)) != EOF) { switch(c) { case 'v': // Show version and exit printf("DGen/SDL version "VER"\n"); return 0; case 'r': // Parse another RC file parse_rc(optarg); break; case 'n': // Sleep for n microseconds dgen_nice = atoi(optarg); break; case 'p': // Game Genie patches patches = optarg; break; #ifndef __BEOS__ case 'R': // Try to set realtime priority if(geteuid()) { fprintf(stderr, "main: Only root can set lower priorities!\n"); break; } if(setpriority(PRIO_PROCESS, 0, -20) == -1) perror("main: setpriority"); break; #endif case 'P': // PAL mode pal_mode = 1; break; #ifdef JOYSTICK_SUPPORT case 'j': // Phil's joystick code dgen_joystick = 1; break; #endif case 'd': // Record demo if(demo) { fprintf(stderr,"main: Can't record and play at the same time!\n"); break; } if(!(demo = fopen(optarg, "wb"))) { fprintf(stderr, "main: Can't record demo file %s!\n", optarg); break; } demo_record = 1; break; case 'D': // Play demo if(demo) { fprintf(stderr,"main: Can't record and play at the same time!\n"); break; } if(!(demo = fopen(optarg, "rb"))) { fprintf(stderr, "main: Can't play demo file %s!\n", optarg); break; } demo_play = 1; break; case '?': // Bad option! case 'h': // A cry for help :) help(); case 's': // Pick a savestate to autoload start_slot = atoi(optarg); break; default: // Pass it on to platform-dependent stuff pd_option(c, optarg); break; } } #ifdef __BEOS__ // BeOS snooze() sleeps in milliseconds, not microseconds dgen_nice /= 1000; #endif // There should be a romname after all those options. If not, show help and // exit. if(optind >= argc) help(); // Initialize the platform-dependent stuff. if(!pd_graphics_init(dgen_sound, pal_mode)) { fprintf(stderr, "main: Couldn't initialize graphics!\n"); return 1; } if(dgen_sound) { dgen_16bit = dgen_16bit? PD_SND_16 : PD_SND_8; dgen_sound = pd_sound_init(dgen_16bit, dgen_soundrate, dgen_soundsegs); } // If sound fared OK, start up the sound chips if(dgen_sound) { if(YM2612Init(1, 7520000L, dgen_soundrate, NULL, NULL) || SN76496_init(0, 3478000L, dgen_soundrate, 16)) fprintf(stderr, "main: Couldn't start sound chipset emulators!\n"); else sound_is_okay = 1; } // Decrement the sound seg count. This makes it a nice AND mask :) --dgen_soundsegs; rom = argv[optind]; // Create the megadrive object md megad; if(!megad.okay()) { fprintf(stderr, "main: Megadrive init failed!\n"); return 1; } // Load the requested ROM if(megad.load(rom)) { fprintf(stderr, "main: Couldn't load ROM file %s!\n", rom); return 1; } // Set untouched pads megad.pad[0] = megad.pad[1] = 0xF303F; #ifdef JOYSTICK_SUPPORT if(dgen_joystick) megad.init_joysticks(); #endif // Load patches, if given if(patches) { printf("main: Using patch codes %s\n", patches); megad.patch(patches); } // Fix checksum megad.fix_rom_checksum(); // Reset megad.reset(); // Set PAL mode megad.pal = pal_mode; // Make sure the .dgen hierarchy is setup mk_dgendir(); // Load up save RAM ram_load(megad); // If autoload is on, load save state 0 if(dgen_autoload) { slot = 0; md_load(megad); } // If -s option was given, load the requested slot if(start_slot >= 0) { slot = start_slot; md_load(megad); } // Start the timing refs gettimeofday(&oldclk, NULL); gettimeofday(&startclk, NULL); // Start audio if(dgen_sound) pd_sound_start(); // Show cartridge header if(dgen_show_carthead) pd_show_carthead(megad); // Go around, and around, and around, and around... ;) while(running) { int frames_todo; frames_todo = 1; // Measure how many frames to do this round if(!dgen_sound && dgen_frameskip) { gettimeofday(&newclk, NULL); if(newclk.tv_usec < oldclk.tv_usec) usec += 1000000 + newclk.tv_usec - oldclk.tv_usec; else usec += newclk.tv_usec - oldclk.tv_usec; frames_todo = usec / USEC_FRAME; usec %= USEC_FRAME; oldclk = newclk; // We don't want to skip too many frames - this isn't Unreal ;) if(frames_todo > 8) frames_todo = 8; // Skip these frames for(;frames_todo > 1; --frames_todo) { DO_DEMO megad.one_frame(NULL, NULL, NULL); } } else if(dgen_sound) { // We can use the sound buffer for timing, instead of the above loop // If we are already caught up, wait for the read pointer to advance while((rp = pd_sound_rp()) == wp); while(wp != rp) { pd_sound_write(wp); ++wp; wp &= dgen_soundsegs; // Skip a frame to keep the sound going, until we hit the read // point. if(wp != rp) { DO_DEMO megad.one_frame(NULL, NULL, &sndi); } } } // If there are frames to do, do them! :) if(frames_todo) { DO_FRAME(&mdscr, mdpal); // Update palette if(mdpal && pal_dirty) { pd_graphics_palette_update(); pal_dirty = 0; } } // Update screen pd_graphics_update(); ++f; // Sleep a bit #ifdef __BEOS__ if(dgen_nice) snooze(dgen_nice); #else if(dgen_nice) usleep(dgen_nice); #endif } // Print fps gettimeofday(&endclk, NULL); printf("%d frames per second (optimal %d)\n", (unsigned)(f / (endclk.tv_sec - startclk.tv_sec)), (pal_mode? 50 : 60)); // Cleanup if(demo) fclose(demo); ram_save(megad); if(dgen_autosave) { slot = 0; md_save(megad); } megad.unplug(); pd_quit(); YM2612Shutdown(); // Come back anytime :) return 0; } dgen-sdl-1.23/rc.h 644 1750 1750 1177 7320141353 7036 // DGen/SDL v1.23+ #ifndef __SVGALIB_RC_H__ #define __SVGALIB_RC_H__ // Define the different craptv types #define NUM_CTV 4 // Include CTV_OFF #define CTV_OFF 0 #define CTV_BLUR 1 #define CTV_SCANLINE 2 #define CTV_INTERLACE 3 // Define OR masks for key modifiers #define KEYSYM_MOD_ALT 0x40000000 #define KEYSYM_MOD_SHIFT 0x20000000 #define KEYSYM_MOD_CTRL 0x10000000 #define KEYSYM_MOD_META 0x08000000 // All the CTV engine names, in string form for the RC and message bar extern char *ctv_names[]; // Provide a prototype to the parse_rc function in rc.cpp void parse_rc(const char *file); #endif // __SVGALIB_RC_H__ dgen-sdl-1.23/md-phil.h 644 1750 1750 1213 7027317555 7770 #ifndef _MD_PHIL_H_ #define _MD_PHIL_H_ #define MD_UNTOUCHED (0xF303F) #define MD_UP_MASK (1) // 0x00001 #define MD_DOWN_MASK (1 << 1) // 0x00002 #define MD_LEFT_MASK (1 << 2) // 0x00004 #define MD_RIGHT_MASK (1 << 3) // 0x00008 #define MD_B_MASK (1 << 4) // 0x00010 #define MD_C_MASK (1 << 5) // 0x00020 #define MD_A_MASK (1 << 12) // 0x01000 #define MD_START_MASK (1 << 13) // 0x02000 #define MD_Z_MASK (1 << 16) // 0x10000 #define MD_Y_MASK (1 << 17) // 0x20000 #define MD_X_MASK (1 << 18) // 0x40000 #define MD_MODE_MASK (1 << 19) // 0x80000 #endif // _MD_PHIL_H_ dgen-sdl-1.23/rc-vars.h 644 1750 1750 4146 7320144576 10020 #ifndef __RC_VARS_H__ #define __RC_VARS_H__ // DGen/SDL v1.17+ // RC-modified variables listed here #include "pd-defs.h" // Keysyms are defined in here // main.cpp defines IS_MAIN_CPP, which means we actually define the variables. // Otherwise, we just declare them as externs #ifdef IS_MAIN_CPP #define RCVAR(name, def) long name = def #else #define RCVAR(name, def) extern long name #endif RCVAR(pad1_up, PDK_UP); RCVAR(pad1_down, PDK_DOWN); RCVAR(pad1_left, PDK_LEFT); RCVAR(pad1_right, PDK_RIGHT); RCVAR(pad1_a, PDK_a); RCVAR(pad1_b, PDK_s); RCVAR(pad1_c, PDK_d); RCVAR(pad1_x, PDK_q); RCVAR(pad1_y, PDK_w); RCVAR(pad1_z, PDK_e); RCVAR(pad1_mode, PDK_BACKSPACE); RCVAR(pad1_start, PDK_RETURN); RCVAR(pad2_up, PDK_KP8); RCVAR(pad2_down, PDK_KP2); RCVAR(pad2_left, PDK_KP4); RCVAR(pad2_right, PDK_KP6); RCVAR(pad2_a, PDK_DELETE); RCVAR(pad2_b, PDK_END); RCVAR(pad2_c, PDK_PAGEDOWN); RCVAR(pad2_x, PDK_INSERT); RCVAR(pad2_y, PDK_HOME); RCVAR(pad2_z, PDK_PAGEUP); RCVAR(pad2_mode, PDK_KP_PLUS); RCVAR(pad2_start, PDK_KP_ENTER); RCVAR(dgen_fix_checksum, PDK_F1); RCVAR(dgen_quit, PDK_ESCAPE); RCVAR(dgen_splitscreen_toggle, PDK_F4); RCVAR(dgen_craptv_toggle, PDK_F5); RCVAR(dgen_screenshot, PDK_F12); RCVAR(dgen_reset, PDK_TAB); RCVAR(dgen_cpu_toggle, PDK_F11); RCVAR(dgen_stop, PDK_z); RCVAR(dgen_fullscreen_toggle, KEYSYM_MOD_ALT | PDK_RETURN); RCVAR(dgen_slot_0, PDK_0); RCVAR(dgen_slot_1, PDK_1); RCVAR(dgen_slot_2, PDK_2); RCVAR(dgen_slot_3, PDK_3); RCVAR(dgen_slot_4, PDK_4); RCVAR(dgen_slot_5, PDK_5); RCVAR(dgen_slot_6, PDK_6); RCVAR(dgen_slot_7, PDK_7); RCVAR(dgen_slot_8, PDK_8); RCVAR(dgen_slot_9, PDK_9); RCVAR(dgen_save, PDK_F2); RCVAR(dgen_load, PDK_F3); RCVAR(dgen_splitscreen_startup, 0); RCVAR(dgen_autoload, 0); RCVAR(dgen_autosave, 0); RCVAR(dgen_frameskip, 1); RCVAR(dgen_show_carthead, 0); RCVAR(dgen_sound, 1); RCVAR(dgen_soundrate, 22050); RCVAR(dgen_16bit, 1); RCVAR(dgen_soundsegs, 8); RCVAR(dgen_craptv, 0); RCVAR(dgen_nice, 0); RCVAR(dgen_joystick, 0); RCVAR(dgen_fullscreen, 0); RCVAR(dgen_scale, 1); RCVAR(dgen_opengl, 0); RCVAR(dgen_opengl_width, 640); RCVAR(dgen_opengl_height, 480); #endif // __RC_VARS_H__ dgen-sdl-1.23/md.h 644 1750 1750 22213 7027322615 7052 // DGen #ifndef __MD_H__ #define __MD_H__ #define VER VERSION // You needn't worry about changing the #defines at the beginning of this // header anymore, you can simply edit Makefile.config #ifdef COMPILE_WITH_STAR #ifndef __STARCPU_H__ #include "starcpu.h" #endif #endif #ifdef COMPILE_WITH_M68KEM #ifndef M68000__HEADER extern "C" { #include "m68000.h" } #endif #endif #ifdef COMPILE_WITH_MUSA #ifndef M68K__HEADER extern "C" { #include "m68k.h" } #endif #endif #ifndef _MZ80_H_ #include "mz80.h" #endif //#define BUILD_YM2612 extern "C" { #include "fm.h" } extern "C" { int SN76496_init(int chip,int clock,int sample_rate,int sample_bits); void SN76496Write(int chip,int data); void SN76496Update_16(int chip,void *buffer,int length); } extern "C" int test_ctv(unsigned char *dest, int len); extern "C" int blur_bitmap_16(unsigned char *dest, int len); extern "C" int blur_bitmap_15(unsigned char *dest, int len); struct bmap { unsigned char *data; int w,h; int pitch; int bpp; }; // Info passed to render the screen (possibly line by line) struct dgen_sinfo { unsigned char *vram,*cram,*vsram,*vdp_reg; }; // New struct, happily encapsulates all the sound info struct sndinfo { signed short *l, *r; int len; }; int draw_md_graphics (struct bmap *bm,unsigned char passpal[256],struct dgen_sinfo *si, int ymin, int ymax, int layer_sel); int get_md_palette(unsigned char pal[256],unsigned char *cram); class md; class md_vdp { public: // Next three lines are the state of the VDP // They have to be public so we can save and load states // and draw the screen. unsigned char *mem,*vram,*cram,*vsram; unsigned char reg[0x20]; int rw_mode,rw_addr,rw_dma; private: int poke_vram (int addr,unsigned char d); int poke_cram (int addr,unsigned char d); int poke_vsram(int addr,unsigned char d); int dma_len(); int dma_addr(); unsigned char dma_mem_read(int addr); int putword(unsigned short d); int putbyte(unsigned char d); int ok; // Used by draw_scanline to render the different display components void draw_tile1(int which, int line, unsigned char *where); void draw_tile1_solid(int which, int line, unsigned char *where); void draw_tile2(int which, int line, unsigned char *where); void draw_tile2_solid(int which, int line, unsigned char *where); /* FIXME: do 3 bytes/pixel */ void draw_tile3(int which, int line, unsigned char *where); void draw_tile3_solid(int which, int line, unsigned char *where); void draw_tile4(int which, int line, unsigned char *where); void draw_tile4_solid(int which, int line, unsigned char *where); void draw_window(int line, int front); void draw_sprites(int line, int front); void draw_plane_back0(int line); void draw_plane_back1(int line); void draw_plane_front0(int line); void draw_plane_front1(int line); // Working variables for the above unsigned char sprite_order[0x101], *sprite_base; unsigned sprite_count, Bpp, Bpp_times8; unsigned char *dest; public: md_vdp(); ~md_vdp(); md *belongs; // These are called by MEM.CPP int command(unsigned int cmd); unsigned short readword(); unsigned char readbyte(); int writeword(unsigned short d); int writebyte(unsigned char d); int okay() {return ok;} unsigned char *dirt; // Bitfield: what has changed VRAM/CRAM/VSRAM/Reg int get_screen_info(struct dgen_sinfo *si); // For Graph int reset(); unsigned int *highpal; // Draw a scanline void draw_scanline(struct bmap *bits, int line); }; #ifdef COMPILE_WITH_M68KEM // Make sure this gets C linkage extern "C" void cpu_setOPbase24(int pc); #endif class md { private: #ifdef COMPILE_WITH_M68KEM // Yuck - had to use friend function :( friend void cpu_setOPbase24(int pc); #endif int romlen; int ok; unsigned char *mem,*rom,*ram,*z80ram; // Saveram stuff: unsigned char *saveram; // The actual saveram buffer unsigned save_start, save_len; // Start address and length int save_prot, save_active; // Flags set from $A130F1 public: md_vdp vdp; private: struct mz80context z80; #ifdef COMPILE_WITH_STAR struct S68000CONTEXT cpu; STARSCREAM_PROGRAMREGION *fetch; STARSCREAM_DATAREGION *readbyte,*readword,*writebyte,*writeword; int memory_map(); #endif int star_mz80_on(); int star_mz80_off(); int z80_bank68k; // 9 bits int z80_online; int odo; //,odo_frame_max; // value of odo now/at end of frame int odo_line_start,odo_line_end,odo_line_len,ras,frame; int hint_countdown; int z80_extra_cycles; // Note order is (0) Vblank end -------- Vblank Start -- (HIGH) // So int6 happens in the middle of the count int coo_waiting; // after 04 write which is 0x4xxx or 0x8xxx unsigned int coo_cmd; // The complete command int aoo3_toggle,aoo5_toggle,aoo3_six,aoo5_six; int aoo3_six_timeout, aoo5_six_timeout; int calculate_hcoord(); unsigned char calculate_coo8(); unsigned char calculate_coo9(); int may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int mark); int may_want_to_get_sound(struct sndinfo *sndi); int z80_int_pending; void run_to_odo_star(int odo_to); void run_to_odo_musa(int odo_to); void run_to_odo_m68kem(int odo_to); void run_to_odo_z80(int odo_to); int fm_timer_callback(); int myfm_read(int a); int mysn_write(int v); int fm_sel[2],fm_tover[2],ras_fm_ticker[4]; signed short fm_reg[2][0x100]; // All of them (-1 = not def'd yet) int dac_data[0x138], dac_enabled, dac_last; // Since dac values are normally shifted << 6, 1 is used to mark unchanged // values. void dac_init() { dac_last = 1; dac_enabled = 0; dac_clear(); } void dac_clear() { dac_data[0] = dac_last; for(int i = 1; i < 0x138; ++i) dac_data[i] = 1; } void dac_submit(int d) { dac_last = (d - 0x80) << 6; if(dac_enabled) dac_data[ras] = dac_last; } void dac_enable(int d) { dac_enabled = d & 0x80; dac_data[ras] = (dac_enabled? dac_last : 1); } public: int myfm_write(int a,int v,int md); int flush_fm_to_mame(); int pause, layer_sel; // public struct, full with data from the cartridge header struct _carthead_ { char system_name[0x10]; // "SEGA GENESIS ", "SEGA MEGA DRIVE " char copyright[0x10]; // "(C)SEGA 1988.JUL" char domestic_name[0x30]; // Domestic game name char overseas_name[0x30]; // Overseas game name char product_no[0xe]; // "GM XXXXXXXX-XX" or "GM MK-XXXX -00" unsigned short checksum; // ROM checksum char control_data[0x10]; // I/O use data (usually only joystick) unsigned rom_start, rom_end; // ROM start & end addresses unsigned ram_start, ram_end; // RAM start & end addresses unsigned short save_magic; // 0x5241("RA") if saveram, else 0x2020 unsigned short save_flags; // Misc saveram info unsigned save_start, save_end; // Saveram start & end unsigned short modem_magic; // 0x4d4f("MO") if uses modem, else 0x2020 char modem_firm[4]; // Modem firm name (should be same as (c)) char modem_ver[4]; // yy.z, yy=ID number, z=version char memo[0x28]; // Extra data char countries[0x10]; // Country code } cart_head; int snd_mute; // &1=fm &2=psg &4=dac int country_ver; int pal; // 0 = NTSC 1 = PAL int one_frame_star(struct bmap *bm,unsigned char retpal[256],struct sndinfo *sndi); int one_frame_musa(struct bmap *bm,unsigned char retpal[256],struct sndinfo *sndi); int one_frame_m68kem(struct bmap *bm,unsigned char retpal[256],struct sndinfo *sndi); int one_frame(struct bmap *bm,unsigned char retpal[256],struct sndinfo *sndi); int pad[2]; // c000004 bit 1 write fifo empty, bit 0 write fifo full (???) // c000005 vint happened, (sprover, coll, oddinint) // invblank, inhblank, dma busy, pal unsigned char coo4,coo5; int okay() {return ok;} md(); ~md(); int plug_in(unsigned char *cart,int len); int unplug(); int load(char *name); int reset(); unsigned misc_readbyte(unsigned a); void misc_writebyte(unsigned a,unsigned d); unsigned misc_readword(unsigned a); void misc_writeword(unsigned a,unsigned d); int z80_init(); unsigned char z80_read(unsigned int a); void z80_write(unsigned int a,unsigned char v); unsigned short z80_port_read(unsigned short a); void z80_port_write(unsigned short a,unsigned char v); int cpu_emu;// OK to read it but call change_cpu_emu to change it int change_cpu_emu(int to); mz80context& z80_context() {return z80;} int load(FILE *hand,char *desc); int save(FILE *hand,char *desc); int import_gst(FILE *hand); int export_gst(FILE *hand); char romfilename[256]; // If known int get_screen_info(struct dgen_sinfo *si) { return vdp.get_screen_info(si); } int z80dump(); // Fix ROM checksum void fix_rom_checksum(); // Added by Joe Groff: // Patch the ROM code, using Game Genie/Hex codes void patch(const char *list); // Get/put the battery save RAM int has_save_ram(); void get_save_ram(FILE *from); void put_save_ram(FILE *into); // Added by Phillip K. Hornung // Linux joystick initialization and handling routines void init_joysticks(); void read_joysticks(); }; inline int md::has_save_ram() { return save_len; } #endif // __MD_H__ dgen-sdl-1.23/mz80.h 644 1750 1750 16732 7176135241 7263 /* Multi-Z80 32 Bit emulator */ /* Copyright 1996, Neil Bradley, All rights reserved * * License agreement: * * The mZ80 emulator may be distributed in unmodified form to any medium. * * mZ80 May not be sold, or sold as a part of a commercial package without * the express written permission of Neil Bradley (neil@synthcom.com). This * includes shareware. * * Modified versions of mZ80 may not be publicly redistributed without author * approval (neil@synthcom.com). This includes distributing via a publicly * accessible LAN. You may make your own source modifications and distribute * mZ80 in object only form. * * mZ80 Licensing for commercial applications is available. Please email * neil@synthcom.com for details. * * Synthcom Systems, Inc, and Neil Bradley will not be held responsible for * any damage done by the use of mZ80. It is purely "as-is". * * If you use mZ80 in a freeware application, credit in the following text: * * "Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)" * * must accompany the freeware application within the application itself or * in the documentation. * * Legal stuff aside: * * If you find problems with mZ80, please email the author so they can get * resolved. If you find a bug and fix it, please also email the author so * that those bug fixes can be propogated to the installed base of mZ80 * users. If you find performance improvements or problems with mZ80, please * email the author with your changes/suggestions and they will be rolled in * with subsequent releases of mZ80. * * The whole idea of this emulator is to have the fastest available 32 bit * Multi-z80 emulator for the PC, giving maximum performance. */ /* General z80 based defines */ #ifndef _MZ80_H_ #define _MZ80_H_ #ifndef UINT32 #define UINT32 unsigned long int #endif #ifndef UINT16 #define UINT16 unsigned short int #endif #ifndef UINT8 #define UINT8 unsigned char #endif #ifndef INT32 #define INT32 signed long int #endif #ifndef INT16 #define INT16 signed short int #endif #ifndef INT8 #define INT8 signed char #endif #ifdef __cplusplus extern "C" { #endif #ifndef _MEMORYREADWRITEBYTE_ #define _MEMORYREADWRITEBYTE_ struct MemoryWriteByte { UINT32 lowAddr; UINT32 highAddr; void (*memoryCall)(UINT32, UINT8, struct MemoryWriteByte *); void *pUserArea; }; struct MemoryReadByte { UINT32 lowAddr; UINT32 highAddr; UINT8 (*memoryCall)(UINT32, struct MemoryReadByte *); void *pUserArea; }; #endif // _MEMORYREADWRITEBYTE_ struct z80PortWrite { UINT16 lowIoAddr; UINT16 highIoAddr; void (*IOCall)(UINT16, UINT8, struct z80PortWrite *); void *pUserArea; }; struct z80PortRead { UINT16 lowIoAddr; UINT16 highIoAddr; UINT16 (*IOCall)(UINT16, struct z80PortRead *); void *pUserArea; }; struct z80TrapRec { UINT16 trapAddr; UINT8 skipCnt; UINT8 origIns; }; typedef union { UINT32 af; struct { #ifdef WORDS_BIGENDIAN UINT16 wFiller; UINT8 a; UINT8 f; #else UINT8 f; UINT8 a; UINT16 wFiller; #endif } half; } reg_af; #define z80AF z80af.af #define z80A z80af.half.a #define z80F z80af.half.f typedef union { UINT32 bc; struct { #ifdef WORDS_BIGENDIAN UINT16 wFiller; UINT8 b; UINT8 c; #else UINT8 c; UINT8 b; UINT16 wFiller; #endif } half; } reg_bc; #define z80BC z80bc.bc #define z80B z80bc.half.b #define z80C z80bc.half.c typedef union { UINT32 de; struct { #ifdef WORDS_BIGENDIAN UINT16 wFiller; UINT8 d; UINT8 e; #else UINT8 e; UINT8 d; UINT16 wFiller; #endif } half; } reg_de; #define z80DE z80de.de #define z80D z80de.half.d #define z80E z80de.half.e typedef union { UINT32 hl; struct { #ifdef WORDS_BIGENDIAN UINT16 wFiller; UINT8 h; UINT8 l; #else UINT8 l; UINT8 h; UINT16 wFiller; #endif } half; } reg_hl; #define z80HL z80hl.hl #define z80H z80hl.half.h #define z80L z80hl.half.l #define z80SP z80sp.sp typedef union { UINT32 ix; struct { #ifdef WORDS_BIGENDIAN UINT16 wFiller; UINT8 xh; UINT8 xl; #else UINT8 xl; UINT8 xh; UINT16 wFiller; #endif } half; } reg_ix; #define z80IX z80ix.ix #define z80XH z80ix.half.xh #define z80XL z80ix.half.xl typedef union { UINT32 iy; struct { #ifdef WORDS_BIGENDIAN UINT16 wFiller; UINT8 yh; UINT8 yl; #else UINT8 yl; UINT8 yh; UINT16 wFiller; #endif } half; } reg_iy; #define z80IY z80iy.iy #define z80YH z80iy.half.yh #define z80YL z80iy.half.yl struct mz80context { UINT8 *z80Base; struct MemoryReadByte *z80MemRead; struct MemoryWriteByte *z80MemWrite; struct z80PortRead *z80IoRead; struct z80PortWrite *z80IoWrite; UINT32 z80clockticks; UINT32 z80iff; UINT32 z80interruptMode; UINT32 z80halted; reg_af z80af; reg_bc z80bc; reg_de z80de; reg_hl z80hl; UINT32 z80afprime; UINT32 z80bcprime; UINT32 z80deprime; UINT32 z80hlprime; reg_ix z80ix; reg_iy z80iy; UINT32 z80sp; UINT32 z80pc; UINT32 z80nmiAddr; UINT32 z80intAddr; UINT32 z80rCounter; UINT8 z80i; UINT8 z80r; UINT8 z80intPending; }; // These are the enumerations used for register access. DO NOT ALTER THEIR // ORDER! It must match the same order as in the mz80.c/mz80.asm files! enum { #ifndef CPUREG_PC CPUREG_PC = 0, #endif CPUREG_Z80_AF = 1, CPUREG_Z80_BC, CPUREG_Z80_DE, CPUREG_Z80_HL, CPUREG_Z80_AFPRIME, CPUREG_Z80_BCPRIME, CPUREG_Z80_DEPRIME, CPUREG_Z80_HLPRIME, CPUREG_Z80_IX, CPUREG_Z80_IY, CPUREG_Z80_SP, CPUREG_Z80_I, CPUREG_Z80_R, CPUREG_Z80_A, CPUREG_Z80_B, CPUREG_Z80_C, CPUREG_Z80_D, CPUREG_Z80_E, CPUREG_Z80_H, CPUREG_Z80_L, CPUREG_Z80_F, CPUREG_Z80_CARRY, CPUREG_Z80_NEGATIVE, CPUREG_Z80_PARITY, CPUREG_Z80_OVERFLOW, CPUREG_Z80_HALFCARRY, CPUREG_Z80_ZERO, CPUREG_Z80_SIGN, CPUREG_Z80_IFF1, CPUREG_Z80_IFF2, // Leave this here! CPUREG_Z80_MAX_INDEX }; extern UINT32 mz80exec(UINT32); extern UINT32 mz80GetContextSize(void); extern UINT32 mz80GetElapsedTicks(UINT32); extern void mz80ReleaseTimeslice(void); extern void mz80GetContext(void *); extern void mz80SetContext(void *); extern void mz80reset(void); extern void mz80ClearPendingInterrupt(void); extern UINT32 mz80int(UINT32); extern UINT32 mz80nmi(void); extern void mz80init(void); extern UINT32 z80intAddr; extern UINT32 z80nmiAddr; // Debugger useful routines extern UINT8 mz80SetRegisterValue(void *, UINT32, UINT32); extern UINT32 mz80GetRegisterValue(void *, UINT32); extern UINT32 mz80GetRegisterTextValue(void *, UINT32, UINT8 *); extern UINT8 *mz80GetRegisterName(UINT32); // Memory/IO read/write commands #ifndef VALUE_BYTE #define VALUE_BYTE 0 #endif #ifndef VALUE_WORD #define VALUE_WORD 1 #endif #ifndef VALUE_DWORD #define VALUE_DWORD 2 #endif #ifndef VALUE_IO #define VALUE_IO 3 #endif extern void mz80WriteValue(UINT8 bWhat, UINT32 dwAddr, UINT32 dwData); extern UINT32 mz80ReadValue(UINT8 bWhat, UINT32 dwAddr); // Flag definitions #define Z80_FLAG_CARRY 0x01 #define Z80_FLAG_NEGATIVE 0x02 #define Z80_FLAG_OVERFLOW_PARITY 0x04 #define Z80_FLAG_UNDEFINED1 0x08 #define Z80_FLAG_HALF_CARRY 0x10 #define Z80_FLAG_UNDEFINED2 0x20 #define Z80_FLAG_ZERO 0x40 #define Z80_FLAG_SIGN 0x80 #define IFF1 0x01 #define IFF2 0x02 typedef struct mz80context CONTEXTMZ80; #ifdef __cplusplus }; #endif #endif // _MZ80_H_ dgen-sdl-1.23/fm.h 644 1750 1750 6725 7027317554 7054 /* File: fm.h -- header file for software emuration for FM sound genelator */ #ifndef _H_FM_FM_ #define _H_FM_FM_ ////// starshine - one chip 4 me! #define HAS_YM2612 1 #define BUILD_YM2612 (HAS_YM2612) // build YM2612 emulator #define BUILD_YM2203 (HAS_YM2203) /* build YM2203(OPN) emulator */ #define BUILD_YM2608 (HAS_YM2608) /* build YM2608(OPNA) emulator */ #define BUILD_YM2610 (HAS_YM2610) /* build YM2610(OPNB) emulator */ #define BUILD_YM2610B (HAS_YM2610B) /* build YM2610B(OPNB?)emulator */ #define BUILD_YM2151 (HAS_YM2151) /* build YM2151(OPM) emulator */ /* stereo mixing / separate */ //#define FM_STEREO_MIX /* output bit size 8 or 16 */ #define FM_OUTPUT_BIT 16 #define YM2203_NUMBUF 1 #ifdef FM_STEREO_MIX #define YM2151_NUMBUF 1 #define YM2608_NUMBUF 1 #define YM2612_NUMBUF 1 #define YM2610_NUMBUF 1 #else #define YM2151_NUMBUF 2 /* FM L+R */ #define YM2608_NUMBUF 2 /* FM L+R+ADPCM+RYTHM */ #define YM2612_NUMBUF 2 /* FM L+R */ #define YM2610_NUMBUF 2 #endif #if (FM_OUTPUT_BIT==16) typedef unsigned short FMSAMPLE; typedef unsigned long FMSAMPLE_MIX; #endif #if (FM_OUTPUT_BIT==8) typedef unsigned char FMSAMPLE; typedef unsigned short FMSAMPLE_MIX; #endif /* For YM2151/YM2608/YM2612 option */ typedef void (*FM_TIMERHANDLER)(int n,int c,int cnt,double stepTime); typedef void (*FM_IRQHANDLER)(int n,int irq); /* FM_TIMERHANDLER : Stop or Start timer */ /* int n = chip number */ /* int c = Channel 0=TimerA,1=TimerB */ /* int count = timer count (0=stop) */ /* doube stepTime = step time of one count (sec.)*/ /* FM_IRQHHANDLER : IRQ level changing sense */ /* int n = chip number */ /* int irq = IRQ level 0=OFF,1=ON */ #ifdef BUILD_OPN /* -------------------- YM2203/YM2608 Interface -------------------- */ /* ** 'n' : YM2203 chip number 'n' ** 'r' : register ** 'v' : value */ //void OPNWriteReg(int n, int r, int v); /* ** read status YM2203 chip number 'n' */ unsigned char OPNReadStatus(int n); #endif /* BUILD_OPN */ #if BUILD_YM2203 /* -------------------- YM2203(OPN) Interface -------------------- */ /* ** Initialize YM2203 emulator(s). ** ** 'num' is the number of virtual YM2203's to allocate ** 'rate' is sampling rate ** return 0 = success */ int YM2203Init(int num, int baseclock, int rate, FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); /* ** shutdown the YM2203 emulators .. make sure that no sound system stuff ** is touching our audio buffers ... */ void YM2203Shutdown(void); /* ** reset all chip registers for YM2203 number 'num' */ void YM2203ResetChip(int num); void YM2203UpdateOne(int num, void *buffer, int length); /* ** return : InterruptLevel */ int YM2203Write(int n,int a,int v); unsigned char YM2203Read(int n,int a); /* ** Timer OverFlow */ int YM2203TimerOver(int n, int c); /*int YM2203SetBuffer(int n, FMSAMPLE *buf );*/ #endif /* BUILD_YM2203 */ #if BUILD_YM2612 int YM2612Init(int num, int baseclock, int rate, FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler); void YM2612Shutdown(void); void YM2612ResetChip(int num); void YM2612UpdateOne(int num, void **buffer, int length); int YM2612Write(int n, int a,int v); unsigned char YM2612Read(int n,int a); int YM2612TimerOver(int n, int c ); FMSAMPLE *YM2612Buffer(int n); /*int YM2612SetBuffer(int n, FMSAMPLE **buf );*/ #endif /* BUILD_YM2612 */ #endif /* _H_FM_FM_ */ dgen-sdl-1.23/decode.h 644 1750 1750 460 7027317553 7642 /* Header file for decode functions */ #ifndef __GENIE_DECODE_H__ #define __GENIE_DECODE_H__ struct patch { unsigned int addr, data; }; #ifdef __cplusplus extern "C" { #endif void decode(const char* code, struct patch *result); #ifdef __cplusplus } // extern "C" #endif #endif // __GENIE_DECODE_H__ dgen-sdl-1.23/mem.cpp 644 1750 1750 17474 7232431200 7565 // DGen/SDL v1.15+ // Megadrive C++ module - misc memory #include #include "md.h" // md.h also has include fm.h // This is to handle memory accesses outside of ROM and RAM // e.g. c00000 and a00000 addresses // REMEMBER NOT TO USE ANY STATIC variables, because they // will exist thoughout ALL megadrives! unsigned char md::z80_read(unsigned int a) { if (a<0x2000) return z80ram[a&0xffff]; if ((a&0xfffc)==0x4000) // 00 01 02 03 - not sure about reads { return myfm_read(a&3); } if (a>=0x8000) { int addr68k; addr68k=z80_bank68k<<15; addr68k+=a&0x7fff; return misc_readbyte(addr68k); } return 0; } unsigned short md::z80_port_read(unsigned short a) { int ret=0; // dprintf("z80 port read %.2x return %.4x\n",a,ret); return ret; } void md::z80_port_write(unsigned short a,unsigned char v) { // dprintf("z80 port write %.2x %.2x\n",a,v); } void md::z80_write(unsigned int a,unsigned char v) { if ((a&0xfffc)==0x4000) // 00 01 02 03 { myfm_write(a&3,v,1); return ; } if (a==0x7f11) { mysn_write(v); return; } if (a==0x6000) { z80_bank68k>>=1; z80_bank68k+=(v&1)<<8; z80_bank68k&=0x1ff; // 9 bits and filled in the new top one return ; } if (a<0x2000) { z80ram[a&0xffff]=v; return; } if (a>=0x8000) { int addr68k; addr68k=z80_bank68k<<15; addr68k+=a&0x7fff; misc_writebyte(addr68k,v); return; } // dprintf("z80 write %.4x %.2x\n",a,v); return; } unsigned md::misc_readbyte(unsigned a) { unsigned char ret=0; a&=0x00ffffff; // in case stars didn't clip to 24-bit bus // In case it's a rom read after all if (a<0xa00000) { // Saveram if((save_active) && (save_len) && (a >= save_start) && ((a - save_start) < save_len)) { return saveram[(a^1) - save_start]; } else if ((signed)(a^1)=0xe00000) if (a<=0xffffff) { ret=ram[(a^1)&0xffff]; goto end; } // GFX data read (byte) if ((a&0xfffffffe)==0x00c00000) // 00 or 01 { ret=vdp.readbyte(); goto end; } if ((a&0xfffffffc)==0xa04000) { ret=myfm_read(a&3); goto end; } if ((a>=0xa00000)&&(a<0xa08000)) { // Read from z80's memory ret=z80_read(a&0x7fff); goto end; } // I/O port access if ((a&0xfffffe)==0xa10002) { if (aoo3_six==3) { // Extended pad info if (aoo3_toggle==0) ret=((pad[0]>>8)&0x30)+0x00; else ret=((pad[0])&0x30)+0x40+((pad[0]>>16)&0xf); } else { if (aoo3_toggle==0) { if (aoo3_six==4) ret=((pad[0]>>8)&0x30)+0x00+0x0f; else ret=((pad[0]>>8)&0x30)+0x00+(pad[0]&3); } else ret=((pad[0])&0x30)+0x40+(pad[0]&15); } goto end; } if ((a&0xfffffe)==0xa10004) { if (aoo5_six==3) { // Extended pad info if (aoo5_toggle==0x00) ret=((pad[1]>>8)&0x30)+0x00; else ret=((pad[1])&0x30)+0x40+((pad[1]>>16)&0xf); } else { if (aoo5_toggle==0x00) { if (aoo5_six==4) ret=((pad[1]>>8)&0x30)+0x00+0x0f; else ret=((pad[1]>>8)&0x30)+0x00+(pad[1]&3); } else ret=((pad[1])&0x30)+0x40+(pad[1]&15); } goto end; } if (a==0xa10001) { // overseas/pal/disk/0/ md version (0-f) - may make games act different! if ((country_ver&0xff0)==0xff0) { // autodetect country int headcode=0x80,avail=0; int i; for (i=0;i<3;i++) { int ch=misc_readbyte(0x1f0+i); if (ch=='U') avail|=1; else if (ch=='E') avail|=2; else if (ch=='J') avail|=4; } if (avail&1) headcode=0x80; else if (avail&2) headcode=0x80; else if (avail&4) headcode=0x00; ret=headcode+(country_ver&0x0f) | (pal? 0x40 : 0); } else ret=country_ver; goto end; } if (a==0xa11000) {ret=0xff; goto end; } if (a==0xa11001) {ret=0xff; goto end; } if (a==0xa11100) { ret=z80_online; goto end; } if (a==0xa11101) {ret=0x00; goto end; } if (a==0xa11200) {ret=0xff; goto end; } if (a==0xa11201) {ret=0xff; goto end; } // Genecyst style - toggles fifo full/empty if (a==0xc00004) { // This is the genecyst fudge for FIFO full/empty coo4^=0x03; ret=coo4; goto end; } if (a==0xc00005) { // This is the genecyst fudge for in h-blank //coo5^=0x04; ret=coo5 | (pal? 1 : 0); goto end; } if (a==0xc00008) { ret=calculate_coo8(); goto end; } if (a==0xc00009) { ret=calculate_coo9(); goto end; } end: return ret; } void md::misc_writebyte(unsigned a,unsigned d) { a&=0x00ffffff; // in case stars didn't clip to 24-bit bus // Saveram write if(save_len && !save_prot) if(a >= save_start) if ((a - save_start) < save_len) { saveram[(a^1) - save_start] = d; return; } // In case it's a ram write after all if (a>=0xe00000) if (a<=0xffffff) { ram[(a^1)&0xffff]=d; return; } // GFX data write (byte) if ((a&0xfffffffe)==0x00c00000) // 00 or 01 { vdp.writebyte(d); return; } if ((a&0xfffffffc)==0xa04000) { myfm_write(a&3,d,1); return; } if (a==0xc00011) { mysn_write(d); return; } if (a==0xa11100) { //d8 (W) 0: BUSREQ CANCEL // 1: BUSREQ REQUEST if (d==1) z80_online=0; else z80_online=1; return; } if (a==0xa11101) return; if (a==0xa11200) { if (d==0) mz80reset(); return; } if (a==0xa11201) return; if ((a>=0xa00000)&&(a<0xa08000)) { // Write into z80's memory z80_write(a&0x7fff,d); return; } // I/O port access if (a==0xa10003) { if (aoo3_six>=0 && (d&0x40)==0 && aoo3_toggle ) aoo3_six++; if (aoo3_six>0xc00000) aoo3_six&=~0x400000; // keep it circling around a high value if (d&0x40) aoo3_toggle=1; else aoo3_toggle=0; aoo3_six_timeout=0; return; } if (a==0xa10005) { if (aoo5_six>=0 && (d&0x40)==0 && aoo5_toggle ) aoo5_six++; if (aoo5_six>0xc00000) aoo5_six&=~0x400000; // keep it circling around a high value if (d&0x40) aoo5_toggle=1; else aoo5_toggle=0; aoo5_six_timeout=0; return; } // Saveram status (thanks Steve :) if(a==0xa130f1) { // Bit 0: 0=rom active, 1=sram active // Bit 1: 0=writeable, 1=write protect save_active = d & 1; save_prot = d & 2; } } unsigned md::misc_readword(unsigned a) { unsigned int ret=0; a&=0x00ffffff; // in case stars didn't clip to 24-bit bus if ((a&0xfffffffc)==0x00c00000) // 00 or 02 { ret=vdp.readword(); goto end; } // else pass onto readbyte ret =misc_readbyte(a)<<8; ret|=misc_readbyte(a+1); goto end; end: return ret; } void md::misc_writeword(unsigned a,unsigned d) { a&=0x00ffffff; // in case stars didn't clip to 24-bit bus // GFX data write (word) if ((a&0xfffffffc)==0x00c00000) // 00 or 02 { vdp.writeword(d); return; } if ((a&0xfffffffc)==0x00c00004) // 04 or 06 { if (coo_waiting) { // Okay completed the vdp command coo_cmd|=d; coo_waiting=0; vdp.command(coo_cmd); return; } if ((d&0xc000)==0x8000) { int addr; addr=d>>8; addr&=0x1f; if (vdp.reg[addr]!=(d&0xff)) { // Store dirty information down to 1byte level in bits int byt,bit; byt=addr; bit=byt&7; byt>>=3; byt&=0x03; vdp.dirt[0x30+byt]|=(1<>8); misc_writebyte(a+1,d&255); } dgen-sdl-1.23/ras-drawplane.h 644 1750 1750 4405 7027317555 11204 int xsize, ysize; int x, scan, w, xstart; static int sizes[4] = {32, 64, 64, 128}; unsigned which; unsigned char *where, *scrolls, *tiles, *tile_line; int xoff, yoff, xoff_mask; int xscroll, yscroll; #if PLANE == 0 // Plane 0 is only where the window isn't // This should make Herzog Zwei split screen work perfectly, and clean // up those little glitches on Sonic 3's level select. if(reg[18] & 0x80) // Window goes down, plane 0 goes up! :) { if((line>>3) >= (reg[18]&0x1f)) return; } else { // Window goes up, plane 0 goes down if((line>>3) < (reg[18]&0x1f)) return; } #endif xsize = sizes[ reg[16] & 3] << 1; ysize = sizes[(reg[16] >> 4) & 3]; #if PLANE == 0 yscroll = get_word(vsram); scrolls = vram + ((reg[13]<<10) & 0xfc00); tiles = vram + (reg[ 2]<<10); #else // PLANE == 1 yscroll = get_word(vsram+2); scrolls = vram + ((reg[13]<<10) & 0xfc00) + 2; tiles = vram + (reg[ 4]<<13); #endif // Interlace? if(reg[12] & 2) yscroll >>= 1; // Offset for the line yscroll += line; // Wide or narrow? if(reg[12] & 1) { w = 40; xstart = -8; } else { w = 32; xstart = 24; } // How do we horizontal offset? switch(reg[11] & 3) { case 2: // per tile scrolls += (line & ~7) << 2; break; case 3: // per line scrolls += line << 2; break; default: break; } xscroll = get_word(scrolls); xoff_mask = xsize - 1; yoff = (yscroll>>3) & (ysize - 1); xoff = ((-(xscroll>>3) - 1)<<1) & xoff_mask; tile_line = tiles + xsize * yoff; scan = yscroll & 7; where = dest + (xstart + (xscroll & 7)) * Bpp; for(x = -1; x < w; ++x) { #if PLANE == 0 if(reg[17] & 0x80) // Don't draw where the window will be { if(x >= ((reg[17]&0x1f) << 1)) goto skip; } else { // + 1 so scroll layers in Sonic look right if((x + 1) < ((reg[17]&0x1f) << 1)) goto skip; } #endif which = get_word(tile_line + xoff); #if (FRONT == 0) && (PLANE == 1) draw_tile_solid(which, scan, where); #elif FRONT == 1 if(which >> 15) draw_tile(which, scan, where); #else if(!(which >> 15)) draw_tile(which, scan, where); #endif #if PLANE == 0 skip: #endif where += Bpp_times8; xoff = (xoff + 2) & xoff_mask; } dgen-sdl-1.23/pd.h 644 1750 1750 6047 7320151432 7035 #ifndef __PD_H__ #define __PD_H__ #include #include #include "md.h" // DGen/SDL v1.17+ // Platform-dependent interface // Your platform implementation needs to define all these functions and // variables! // This is the struct bmap setup by your implementation. // It should be 336x240 (or 336x256 in PAL mode), in 8, 12, 15, 16, 24 or 32 // bits-per-pixel. extern struct bmap mdscr; // Also, you should allocate a 256-char palette array, if need be. Otherwise // this can be NULL if you don't have a paletted display. extern unsigned char *mdpal; // Initialize graphics, in NTSC (320x224) or PAL (320x240) mode. // Since many interfaces require that DGen be setuid-root, this should also // discard root priviledges, if at all necessary. // It should return 1 on successful setup, or 0 if something wrong happened. int pd_graphics_init(int want_sound, int want_pal); // This updats the palette, if necessary. void pd_graphics_palette_update(); // This updates the screen, with the mdscr bitmap. void pd_graphics_update(); // This is the struct sndinfo, also setup by your implementation. // Note that the buffers pointed to in this struct should ALWAYS be 16-bit // signed format, regardless of the actual audio format. extern struct sndinfo sndi; // Initialize sound, with the given format, frequency, and number of segments. // It should keep segs frames' worth of sound buffered. // The parameters should all be modified to reflect the actual characteristics. // This is always called after pd_graphics_init, so you can count on graphics // stuff being initialized. :) // It should return 1 on successful setup, or 0 if something wrong happened. int pd_sound_init(long &format, long &freq, long &segs); // Sound, if any, should be paused at first. Sound should start when this // function is called. void pd_sound_start(); // Likewise, sound should pause if this function is called. void pd_sound_pause(); // This should return which sound segment is currently being played from int pd_sound_rp(); // And this function is called to commit the sound buffers to be played, into // one of the playback buffer segments. void pd_sound_write(int seg); // This should be a list of all the command-line options specific to this // platform, in the form given to getopt(3), i.e "a:b::c". extern char *pd_options; // And, this is called to handle platform-specific stuff. void pd_option(char c, const char *optarg); // This is called after displaying the base options for help, so that you may // document your platform-specific command-line options etc. void pd_help(); // This is called before each frame to handle events, and update the MegaDrive // accordingly. It returns 1 to continue playing the game, or 0 to quit. int pd_handle_events(md &megad); // These are called to display and clear game messages. void pd_message(const char *msg); void pd_clear_message(); // This should display cartridge header info. You can do this any way you like, // I don't care. :) void pd_show_carthead(md &megad); // This should clean up the mess you made. ;) void pd_quit(); #endif // __PD_H__ dgen-sdl-1.23/driver.h 644 1750 1750 501 7027317554 7707 // Dave's driver.h 'filler' file #define INLINE /**/ //#define __inline__ /**/ //#define BUILD_OPN //#define BUILD_YM2612 //#define SEG_SUPPORT //#define INTERNAL_TIMER // use internal timer // Dave : I don't know what's going on here... //#ifdef INTERNAL_TIMER //void YM2612UpdateReq(int chip) //{ //} //#endif dgen-sdl-1.23/sn76496.h 644 1750 1750 653 7027317555 7465 #ifndef SN76496_H #define SN76496_H #define MAX_76496 4 struct SN76496interface { int num; /* total number of 76496 in the machine */ int baseclock; int volume[MAX_76496]; }; int SN76496_sh_start(); void SN76496_0_w(int offset,int data); void SN76496_1_w(int offset,int data); void SN76496_2_w(int offset,int data); void SN76496_3_w(int offset,int data); void SN76496_set_clock(int chip,int _clock); #endif dgen-sdl-1.23/starcpu.h 644 1750 1750 13304 7027317556 10144 /* ** Starscream 680x0 emulation library ** Copyright 1997, 1998, 1999 Neill Corlett ** ** Refer to STARDOC.TXT for terms of use, API reference, and directions on ** how to compile. */ #ifndef __STARCPU_H__ #define __STARCPU_H__ #ifdef __cplusplus extern "C" { #endif /* Remember to byte-swap these regions. (read STARDOC.TXT for details) */ struct STARSCREAM_PROGRAMREGION { unsigned lowaddr; unsigned highaddr; unsigned offset; }; struct STARSCREAM_DATAREGION { unsigned lowaddr; unsigned highaddr; void *memorycall; void *userdata; }; /* Memory structures for 16-bit data path */ #define STARSCREAM_CONTEXTINFO_MEM16 \ struct STARSCREAM_PROGRAMREGION *fetch; \ struct STARSCREAM_DATAREGION *readbyte; \ struct STARSCREAM_DATAREGION *readword; \ struct STARSCREAM_DATAREGION *writebyte; \ struct STARSCREAM_DATAREGION *writeword; \ struct STARSCREAM_PROGRAMREGION *s_fetch; \ struct STARSCREAM_DATAREGION *s_readbyte; \ struct STARSCREAM_DATAREGION *s_readword; \ struct STARSCREAM_DATAREGION *s_writebyte; \ struct STARSCREAM_DATAREGION *s_writeword; \ struct STARSCREAM_PROGRAMREGION *u_fetch; \ struct STARSCREAM_DATAREGION *u_readbyte; \ struct STARSCREAM_DATAREGION *u_readword; \ struct STARSCREAM_DATAREGION *u_writebyte; \ struct STARSCREAM_DATAREGION *u_writeword; \ /* Memory structures for 16-bit data path with function code support */ #define STARSCREAM_CONTEXTINFO_MEM16FC \ unsigned (*f_readbyte) (unsigned f, unsigned a); \ unsigned (*f_readword) (unsigned f, unsigned a); \ unsigned (*f_writebyte)(unsigned f, unsigned a); \ unsigned (*f_writeword)(unsigned f, unsigned a); \ /* Memory structures for 32-bit sizable data path */ #define STARSCREAM_CONTEXTINFO_MEM32 \ struct STARSCREAM_PROGRAMREGION *fetch; \ struct STARSCREAM_DATAREGION *readbus; \ struct STARSCREAM_DATAREGION *writebus; \ struct STARSCREAM_PROGRAMREGION *s_fetch; \ struct STARSCREAM_DATAREGION *s_readbus; \ struct STARSCREAM_DATAREGION *s_writebus; \ struct STARSCREAM_PROGRAMREGION *u_fetch; \ struct STARSCREAM_DATAREGION *u_readbus; \ struct STARSCREAM_DATAREGION *u_writebus; \ unsigned (*f_readbus) (unsigned f, unsigned a); \ unsigned (*f_writebus)(unsigned f, unsigned a); \ /* Common context info for all 680x0 types */ #define STARSCREAM_CONTEXTINFO_COMMON \ void (*resethandler)(void); \ unsigned dreg[8]; \ unsigned areg[8]; \ unsigned asp; \ unsigned pc; \ unsigned odometer; \ unsigned char interrupts[8]; \ unsigned short sr; \ /* 68000-specific context info */ #define STARSCREAM_CONTEXTINFO_68000SPECIFIC \ unsigned short contextfiller00; \ /* Context info for 68010 and higher */ #define STARSCREAM_CONTEXTINFO_68010 \ unsigned char sfc; \ unsigned char dfc; \ unsigned vbr; \ void (*bkpthandler)(void); \ /* 68010-specific context info */ #define STARSCREAM_CONTEXTINFO_68010SPECIFIC \ unsigned char loopmode; \ unsigned char contextfiller10[3]; \ /* Context info for 68020 and higher */ #define STARSCREAM_CONTEXTINFO_68020 \ unsigned asp2; \ struct S68000CONTEXT { STARSCREAM_CONTEXTINFO_MEM16 STARSCREAM_CONTEXTINFO_COMMON STARSCREAM_CONTEXTINFO_68000SPECIFIC }; struct S68010CONTEXT { STARSCREAM_CONTEXTINFO_MEM16 STARSCREAM_CONTEXTINFO_MEM16FC STARSCREAM_CONTEXTINFO_COMMON STARSCREAM_CONTEXTINFO_68010 STARSCREAM_CONTEXTINFO_68010SPECIFIC }; struct S68020CONTEXT { STARSCREAM_CONTEXTINFO_MEM32 STARSCREAM_CONTEXTINFO_COMMON STARSCREAM_CONTEXTINFO_68010 STARSCREAM_CONTEXTINFO_68020 }; #define STARSCREAM_IDENTIFIERS(SNC,SN) \ \ extern struct SNC##CONTEXT SN##context; \ \ int SN##init (void); \ unsigned SN##reset (void); \ unsigned SN##exec (int n); \ int SN##interrupt (int level, int vector); \ void SN##flushInterrupts (void); \ int SN##GetContextSize (void); \ void SN##GetContext (void *context); \ void SN##SetContext (void *context); \ int SN##fetch (unsigned address); \ unsigned SN##readOdometer (void); \ unsigned SN##tripOdometer (void); \ unsigned SN##controlOdometer (int n); \ void SN##releaseTimeslice (void); \ unsigned SN##readPC (void); \ STARSCREAM_IDENTIFIERS(S68000,s68000) STARSCREAM_IDENTIFIERS(S68010,s68010) STARSCREAM_IDENTIFIERS(S68020,s68020) #ifdef __cplusplus } #endif #endif dgen-sdl-1.23/m68k.h 644 1750 1750 31101 7027317554 7241 #ifndef M68K__HEADER #define M68K__HEADER /* ======================================================================== */ /* ========================= LICENSING & COPYRIGHT ======================== */ /* ======================================================================== */ /* * MUSASHI * Version 2.0a * * A portable Motorola M680x0 processor emulation engine. * Copyright 1999 Karl Stenerud. All rights reserved. * * This code may be freely used for non-commercial purpooses as long as this * copyright notice remains unaltered in the source code and any binary files * containing this code in compiled form. * * Any commercial ventures wishing to use this code must contact the author * (Karl Stenerud) to negotiate commercial licensing terms. * * The latest version of this code can be obtained at: * http://milliways.scas.bcit.bc.ca/~karl/musashi */ /* ======================================================================== */ /* ============================= INSTRUCTIONS ============================= */ /* ======================================================================== */ /* 1. edit m68kconf.h and modify according to your needs. * 2. Implement in your host program the functions defined in * "FUNCTIONS CALLED BY THE CPU" located later in this file. * 3. You must call m68k_pulse_reset() first to initialize the emulation. * 4. If you don't call m68k_set_cpu_mode(), it will default to 68000 behavior. * * Requirements: * - All operations in this core are done using a default size which must be * at least 32 bits wide. * - Because of signed/unsigned operations required for CPU emulation, this * core will only work on a 2's complement machine. I'm not about to add * 2's complement emulation =). If you don't know what 2's complement is, * you most likely have it. * * Notes: * * You must at least implement the m68k_read_memory_xx() and * m68k_write_memory_xx() functions in order to use the emulation core. * Unless you plan to implement more direct access to memory for immediate * reads and instruction fetches, you can just #define the * m68k_read_immediate_xx() and m68k_read_instruction() functions to * the m68k_read_memory_xx() functions. * * In order to use the emulation, you will need to call m68k_input_reset() * and m68k_execute(). All the other functions are just to let you poke * about with the internals of the CPU. */ /* ======================================================================== */ /* ============================ GENERAL DEFINES =========================== */ /* ======================================================================== */ /* There are 7 levels of interrupt to the 68000. Level 7 cannot me masked */ #define M68K_IRQ_1 1 #define M68K_IRQ_2 2 #define M68K_IRQ_3 3 #define M68K_IRQ_4 4 #define M68K_IRQ_5 5 #define M68K_IRQ_6 6 #define M68K_IRQ_7 7 /* Special interrupt acknowledge values. * Use these as special returns from the interrupt acknowledge callback * (specified later in this header). */ /* Causes an interrupt autovector (0x18 + interrupt level) to be taken. * This happens in a real 68000 if VPA or AVEC is asserted during an interrupt * acknowledge cycle instead of DTACK. */ #define M68K_INT_ACK_AUTOVECTOR -1 /* Causes the spurious interrupt vector (0x18) to be taken * This happens in a real 68000 if BERR is asserted during the interrupt * acknowledge cycle (i.e. no devices responded to the acknowledge). */ #define M68K_INT_ACK_SPURIOUS -2 /* CPU types for use in m68k_set_cpu_type() */ #define M68K_CPU_MODE_68000 1 #define M68K_CPU_MODE_68010 2 #define M68K_CPU_MODE_68020 4 /* ======================================================================== */ /* ============================== STRUCTURES ============================== */ /* ======================================================================== */ typedef struct /* CPU Context */ { unsigned int mode; /* CPU Operation Mode (68000, 68010, or 68020) */ unsigned int sr; /* Status Register */ unsigned int ppc; /* Previous program counter */ unsigned int pc; /* Program Counter */ unsigned int d[8]; /* Data Registers */ unsigned int a[8]; /* Address Registers */ unsigned int usp; /* User Stack Pointer */ unsigned int isp; /* Interrupt Stack Pointer */ unsigned int msp; /* Master Stack Pointer */ unsigned int vbr; /* Vector Base Register. Used in 68010+ */ unsigned int sfc; /* Source Function Code. Used in 68010+ */ unsigned int dfc; /* Destination Function Code. Used in 68010+ */ unsigned int stopped; /* Stopped state: only interrupt can restart */ unsigned int halted; /* Halted state: only reset can restart */ unsigned int int_state; /* Current interrupt line states -- ASG: changed from ints_pending */ unsigned int int_cycles; /* Extra cycles taken due to interrupts -- ASG: added */ int (*int_ack_callback)(int int_level); /* Interrupt Acknowledge */ void (*bkpt_ack_callback)(int data); /* Breakpoint Acknowledge */ void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ void (*pc_changed_callback)(int new_pc); /* Called when the PC changes by a large amount */ void (*set_fc_callback)(int new_fc); /* Called when the CPU function code changes */ void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */ } m68k_cpu_context; /* ======================================================================== */ /* ====================== FUNCTIONS CALLED BY THE CPU ===================== */ /* ======================================================================== */ /* You will have to implement these functions */ /* read/write functions called by the CPU to access memory. * while values used are 32 bits, only the appropriate number * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits * of value should be written to memory). * address will be a 24-bit value. */ /* Read from anywhere */ int m68k_read_memory_8(int address); int m68k_read_memory_16(int address); int m68k_read_memory_32(int address); /* Read data immediately following the PC */ int m68k_read_immediate_8(int address); int m68k_read_immediate_16(int address); int m68k_read_immediate_32(int address); /* Read an instruction (16-bit word immeditately after PC) */ int m68k_read_instruction(int address); /* Write to anywhere */ void m68k_write_memory_8(int address, int value); void m68k_write_memory_16(int address, int value); void m68k_write_memory_32(int address, int value); /* ======================================================================== */ /* ============================== CALLBACKS =============================== */ /* ======================================================================== */ /* These functions allow you to set callbacks to the host when specific events * occur. Note that you must enable the corresponding value in m68kconf.h * in order for these to do anything useful. * Note: I have defined default callbacks which are used if you have enabled * the corresponding #define in m68kconf.h but either haven't assigned a * callback or have assigned a callback of NULL. */ /* Set the callback for an interrupt acknowledge. * You must enable M68K_INT_ACK in m68kconf.h. * The CPU will call the callback with the interrupt level being acknowledged. * The host program must return either a vector from 0x02-0xff, or one of the * special interrupt acknowledge values specified earlier in this header. * If this is not implemented, the CPU will always assume an autovectored * interrupt. * Default behavior: return M68K_INT_ACK_AUTOVECTOR. */ void m68k_set_int_ack_callback(int (*callback)(int int_level)); /* Set the callback for a breakpoint acknowledge (68010+). * You must enable M68K_BKPT_ACK in m68kconf.h. * The CPU will call the callback with whatever was in the data field of the * BKPT instruction for 68020+, or 0 for 68010. * Default behavior: do nothing. */ void m68k_set_bkpt_ack_callback(void (*callback)(int data)); /* Set the callback for the RESET instruction. * You must enable M68K_OUTPUT_RESET in m68kconf.h. * The CPU calls this callback every time it encounters a RESET instruction. * Default behavior: do nothing. */ void m68k_set_reset_instr_callback(void (*callback)(void)); /* Set the callback for informing of a large PC change. * You must enable M68K_PC_CHANGED in m68kconf.h. * The CPU calls this callback with the new PC value every time the PC changes * by a large value (currently set for changes by longwords). * Default behavior: do nothing. */ void m68k_set_pc_changed_callback(void (*callback)(int new_pc)); /* Set the callback for CPU function code changes. * You must enable M68K_SET_FC in m68kconf.h. * The CPU calls this callback with the function code before every memory * access to set the CPU's function code according to what kind of memory * access it is (supervisor/user, program/data and such). * Default behavior: do nothing. */ void m68k_set_fc_callback(void (*callback)(int new_fc)); /* Set a callback for the instruction cycle of the CPU. * You must enable M68K_INSTR_HOOK in m68kconf.h. * The CPU calls this callback just before fetching the opcode in the * instruction cycle. * Default behavior: do nothing. */ void m68k_set_instr_hook_callback(void (*callback)(void)); /* ======================================================================== */ /* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ /* =======================================================<================ */ /* Use this function to set the CPU type ypu want to emulate. * Currently supported types are: M68K_CPU_MODE_68000, M68K_CPU_MODE_68010, * and M68K_CPU_MODE_68020. */ void m68k_set_cpu_mode(int cpu_mode); /* Reset the CPU as if you asserted RESET */ /* You *MUST* call this at least once to initialize the emulation */ void m68k_pulse_reset(void *param); /* execute num_clks worth of instructions. returns number of clks used */ int m68k_execute(int num_clks); /* The following 2 functions simulate an interrupt controller attached to the * CPU since the 68000 needs an interrupt controller attached to work * properly. Valid interrupt lines are 1, 2, 3, 4, 5, 6, and 7 (7 is a non- * maskable interrupt) */ void m68k_assert_irq(int int_line); void m68k_clear_irq(int int_line); /* Halt the CPU as if you asserted the HALT pin */ void m68k_pulse_halt(void); /* look at the internals of the CPU */ int m68k_peek_dr(int reg_num); int m68k_peek_ar(int reg_num); unsigned int m68k_peek_pc(void); unsigned int m68k_peek_ppc(void); int m68k_peek_sr(void); int m68k_peek_ir(void); int m68k_peek_t1_flag(void); int m68k_peek_t0_flag(void); int m68k_peek_s_flag(void); int m68k_peek_m_flag(void); int m68k_peek_int_mask(void); int m68k_peek_x_flag(void); int m68k_peek_n_flag(void); int m68k_peek_z_flag(void); int m68k_peek_v_flag(void); int m68k_peek_c_flag(void); int m68k_peek_usp(void); int m68k_peek_isp(void); int m68k_peek_msp(void); /* poke values into the internals of the CPU */ void m68k_poke_dr(int reg_num, int value); void m68k_poke_ar(int reg_num, int value); void m68k_poke_pc(unsigned int value); void m68k_poke_sr(int value); void m68k_poke_ir(int value); void m68k_poke_t1_flag(int value); void m68k_poke_t0_flag(int value); void m68k_poke_s_flag(int value); void m68k_poke_m_flag(int value); void m68k_poke_int_mask(int value); void m68k_poke_x_flag(int value); void m68k_poke_n_flag(int value); void m68k_poke_z_flag(int value); void m68k_poke_v_flag(int value); void m68k_poke_c_flag(int value); void m68k_poke_usp(int value); void m68k_poke_isp(int value); void m68k_poke_msp(int value); /* context switching to allow multiple CPUs */ unsigned m68k_get_context(void* dst); void m68k_set_context(void* dst); /* check if an instruction is valid for the specified CPU mode */ int m68k_is_valid_instruction(int instruction, int cpu_mode); /* ======================================================================== */ /* ============================= CONFIGURATION ============================ */ /* ======================================================================== */ /* Import the configuration for this build */ #include "m68kconf.h" /* ======================================================================== */ /* ============================== END OF FILE ============================= */ /* ======================================================================== */ #endif /* M68K__HEADER */ dgen-sdl-1.23/m68kconf.h 644 1750 1750 6260 7027317554 10077 #ifndef M68KCONF__HEADER #define M68KCONF__HEADER //#include "osd_cpu.h" //#include "mamedbg.h" /* ======================================================================== */ /* ============================= CONFIGURATION ============================ */ /* ======================================================================== */ /* Configuration switches. 1 = ON, 0 = OFF */ /* If on, CPU will call the interrupt_acknowledge callback when it services an * interrupt. * If off, all interrupts will be autovectored. */ #define M68K_INT_ACK 0 /* If on, CPU will call the breakpoint acknowledge callback when it encounters * a breakpoint instruction and it is running in 68010+ mode. */ #define M68K_BKPT_ACK 0 /* If on, the CPU will monitor the trace flags and take trace exceptions */ #define M68K_TRACE 0 /* If on, CPU will actually halt when m68k_input_halt is called by the host. * I allow it to be disabled for a very slight speed increase. */ #define M68K_HALT 0 /* If on, CPU will call the output reset callback when it encounters a reset * instruction. */ #define M68K_OUTPUT_RESET 0 /* If on, CPU will call the pc changed callback when it changes the PC by a * large value. This allows host programs to be nicer when it comes to * fetching immediate data and instructions on a banked memory system. */ #define M68K_PC_CHANGED 0 /* If on, CPU will call the set fc callback on every memory access to * differentiate between user/supervisor, program/data access like a real * 68000 would. This should be enabled and the callback should be set if you * are going to emulate the m68010. (moves uses function codes to read/write * data from different address spaces) */ #define M68K_SET_FC 0 /* If on, CPU will call the instruction hook callback before every * instruction. */ #define M68K_INSTR_HOOK 0 /* Define the default mode the CPU runs in if none has been specified */ #define M68K_DEFAULT_CPU_MODE M68K_CPU_MODE_68000 /* Uncomment this to enable logging of illegal instruction calls. * M68K_LOG must be #defined to a stdio file stream. Logging will only * occur if the file stream is not NULL. * Turn on M68K_LOG_EMULATED_INSTRUCTIONS to log all 1010 and 1111 calls. #include extern FILE* some_file_handle #define M68K_LOG some_file_handle #define M68K_LOG_EMULATED_INSTRUCTIONS 1 */ /* Set to your compiler's static inline keyword. If your compiler doesn't * have inline, just set this to static. * If you define INLINE in the makefile, it will override this value. */ #ifndef INLINE //#define INLINE static __inline__ #define INLINE static #endif /* ======================================================================== */ /* ============================== MAME STUFF ============================== */ /* ======================================================================== */ /* Uncomment this to enable mame stuff */ /* */ //#include "m68kmame.h" /* ======================================================================== */ /* ============================== END OF FILE ============================= */ /* ======================================================================== */ #endif /* M68KCONF__HEADER */ dgen-sdl-1.23/asm_tiles.asmu 644 1750 1750 40201 7030027670 11142 bits 32 section .text %define which [ebp+36] ; int which %define line [ebp+40] ; int line %define where [ebp+44] ; unsigned char *where %define vram [ebp+24] ; unsigned char *vram %define reg [ebp+28] ; unsigned char reg[0x20] %define highpal [ebp+32] ; unsigned int *highpal ;%define cache_align times ($$-$) & 3 nop ; Align to 4-byte boundary ;%define cache_align times ($$-$) & 7 nop ; Align to 8-byte boundary %define cache_align times ($$-$) & 31 nop ; Align to 32-byte boundary global __asm_tiles_init global __drawtile1_solid global __drawtile1 global __drawtile2_solid global __drawtile2 global __drawtile3_solid global __drawtile3 global __drawtile4_solid global __drawtile4 ; Neat utility macro %macro triple_xor 2 xor %1, %2 ; Triple XOR for a neat register exchange ;) xor %2, %1 xor %1, %2 %endmacro %macro blit_pixel1 1-* ; 8bpp blitting, solid mov eax, ebx and eax, %1 %if %0 > 1 shr eax, byte %2 %endif or eax, [esi] mov byte [edi], al inc edi %endmacro %macro blit_pixel1_trans 1-* ; 8bpp blitting, transparent mov eax, ebx and eax, %1 jz %%trans %if %0 > 1 shr eax, byte %2 %endif or eax, [esi] mov byte [edi], al %%trans: inc edi %endmacro %macro blit_pixel2 1-* ; 16bpp blitting, solid mov eax, ebx and eax, %1 %if %0 > 1 shr eax, byte %2 %endif lea edx, [esi+eax*4] mov eax, [edx] mov word [edi], ax add edi, byte 2 %endmacro %macro blit_pixel2_trans 1-* ; 16bpp blitting, transparent mov eax, ebx and eax, %1 jz %%trans %if %0 > 1 shr eax, byte %2 %endif lea edx, [esi+eax*4] mov eax, [edx] mov word [edi], ax %%trans: add edi, byte 2 %endmacro %macro blit_pixel3 1-* ; 24bpp blitting, solid mov eax, ebx and eax, %1 %if %0 > 1 shr eax, byte %2 %endif lea edx, [esi+eax*4+1] mov ax, word [edx] mov word [edi], ax add edi, 2 dec edx mov al, byte [edx] mov byte [edi], al inc edi %endmacro %macro blit_pixel3_trans 1-* ; 24bpp blitting, transparent mov eax, ebx and eax, %1 jz %%trans %if %0 > 1 shr eax, byte %2 %endif lea edx, [esi+eax*4+1] mov ax, word [edx] mov word [edi], ax add edi, 2 dec edx mov al, byte [edx] mov byte [edi], al inc edi jmp %%next %%trans: add edi, byte 3 %%next: %endmacro %macro blit_pixel4 1-* ; 32bpp blitting, solid mov eax, ebx and eax, %1 %if %0 > 1 shr eax, byte %2 %endif lea edx, [esi+eax*4] mov eax, [edx] mov [edi], eax add edi, byte 4 %endmacro %macro blit_pixel4_trans 1-* ; 32bpp blitting, transparent mov eax, ebx and eax, %1 jz %%trans %if %0 > 1 shr eax, byte %2 %endif lea edx, [esi+eax*4] mov eax, [edx] mov [edi], eax %%trans: add edi, byte 4 %endmacro ; ---------------------------------------- ; int _asm_tiles_init ; (unsigned char *vram, unsigned char *reg, unsigned char *highpal) ; ---------------------------------------- cache_align __asm_tiles_init: push eax push ebx push edx push esp push ebp mov ebp, esp mov eax, vram mov ebx, reg mov edx, highpal mov [__vram], eax mov [__reg], ebx mov [__highpal], edx pop ebp pop esp pop edx pop ebx pop eax ret cache_align ; ---------------------------------------- ; int _drawtile1_solid ; (int which, int line, unsigned char *where) ; ---------------------------------------- cache_align __drawtile1_solid: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax mov edi, [__reg] push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel1 0x0f000000, 24 ; pixel 8 blit_pixel1 0xf0000000, 28 ; ..... 7 blit_pixel1 0x000f0000, 16 ; ..... 6 blit_pixel1 0x00f00000, 20 ; ..... 5 blit_pixel1 0x00000f00, 8 ; ..... 4 blit_pixel1 0x0000f000, 12 ; ..... 3 blit_pixel1 0x0000000f ; ..... 2 blit_pixel1 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel1 0x000000f0, 4 ; pixel 1 blit_pixel1 0x0000000f ; ..... 2 blit_pixel1 0x0000f000, 12 ; ..... 3 blit_pixel1 0x00000f00, 8 ; ..... 4 blit_pixel1 0x00f00000, 20 ; ..... 5 blit_pixel1 0x000f0000, 16 ; ..... 6 blit_pixel1 0xf0000000, 28 ; ..... 7 blit_pixel1 0x0f000000, 24 ; ..... 8 cache_align .cleanup: popad ret cache_align ; ---------------------------------------- __drawtile1: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi test ebx, ebx jz near .cleanup ; Don't waste time if the tile is blank! mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel1_trans 0x0f000000, 24 ; pixel 8 blit_pixel1_trans 0xf0000000, 28 ; ..... 7 blit_pixel1_trans 0x000f0000, 16 ; ..... 6 blit_pixel1_trans 0x00f00000, 20 ; ..... 5 blit_pixel1_trans 0x00000f00, 8 ; ..... 4 blit_pixel1_trans 0x0000f000, 12 ; ..... 3 blit_pixel1_trans 0x0000000f ; ..... 2 blit_pixel1_trans 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel1_trans 0x000000f0, 4 ; pixel 1 blit_pixel1_trans 0x0000000f ; ..... 2 blit_pixel1_trans 0x0000f000, 12 ; ..... 3 blit_pixel1_trans 0x00000f00, 8 ; ..... 4 blit_pixel1_trans 0x00f00000, 20 ; ..... 5 blit_pixel1_trans 0x000f0000, 16 ; ..... 6 blit_pixel1_trans 0xf0000000, 28 ; ..... 7 blit_pixel1_trans 0x0f000000, 24 ; ..... 8 cache_align .cleanup: popad ret cache_align ; ---------------------------------------- cache_align __drawtile2_solid: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov ecx, esi mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax ; - mov edi, [__reg] mov edx, [edi + 7] push dword [esi] and edx, 0x3f mov eax, [ecx + edx*4] mov [esi], eax ; - push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel2 0x0f000000, 24 ; pixel 8 blit_pixel2 0xf0000000, 28 ; ..... 7 blit_pixel2 0x000f0000, 16 ; ..... 6 blit_pixel2 0x00f00000, 20 ; ..... 5 blit_pixel2 0x00000f00, 8 ; ..... 4 blit_pixel2 0x0000f000, 12 ; ..... 3 blit_pixel2 0x0000000f ; ..... 2 blit_pixel2 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel2 0x000000f0, 4 ; pixel 1 blit_pixel2 0x0000000f ; ..... 2 blit_pixel2 0x0000f000, 12 ; ..... 3 blit_pixel2 0x00000f00, 8 ; ..... 4 blit_pixel2 0x00f00000, 20 ; ..... 5 blit_pixel2 0x000f0000, 16 ; ..... 6 blit_pixel2 0xf0000000, 28 ; ..... 7 blit_pixel2 0x0f000000, 24 ; ..... 8 cache_align .cleanup: pop dword [esi] popad ret cache_align ; ---------------------------------------- cache_align __drawtile2: pushad mov ebp, esp .get_pal: mov ebx, which mov esi, [__highpal] mov eax, ebx shr eax, 7 and eax, 0xc0 add esi, eax push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi test ebx, ebx jz near .cleanup ; Don't waste time if the tile is blank! mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel2_trans 0x0f000000, 24 ; pixel 8 blit_pixel2_trans 0xf0000000, 28 ; ..... 7 blit_pixel2_trans 0x000f0000, 16 ; ..... 6 blit_pixel2_trans 0x00f00000, 20 ; ..... 5 blit_pixel2_trans 0x00000f00, 8 ; ..... 4 blit_pixel2_trans 0x0000f000, 12 ; ..... 3 blit_pixel2_trans 0x0000000f ; ..... 2 blit_pixel2_trans 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel2_trans 0x000000f0, 4 ; pixel 1 blit_pixel2_trans 0x0000000f ; ..... 2 blit_pixel2_trans 0x0000f000, 12 ; ..... 3 blit_pixel2_trans 0x00000f00, 8 ; ..... 4 blit_pixel2_trans 0x00f00000, 20 ; ..... 5 blit_pixel2_trans 0x000f0000, 16 ; ..... 6 blit_pixel2_trans 0xf0000000, 28 ; ..... 7 blit_pixel2_trans 0x0f000000, 24 ; ..... 8 cache_align .cleanup: popad ret cache_align ; ---------------------------------------- __drawtile3_solid: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov ecx, esi mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax ; - mov edi, [__reg] mov edx, [edi + 7] push dword [esi] and edx, 0x3f mov eax, [ecx + edx*4] mov [esi], eax ; - push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel3 0x0f000000, 24 ; pixel 8 blit_pixel3 0xf0000000, 28 ; ..... 7 blit_pixel3 0x000f0000, 16 ; ..... 6 blit_pixel3 0x00f00000, 20 ; ..... 5 blit_pixel3 0x00000f00, 8 ; ..... 4 blit_pixel3 0x0000f000, 12 ; ..... 3 blit_pixel3 0x0000000f ; ..... 2 blit_pixel3 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel3 0x000000f0, 4 ; pixel 1 blit_pixel3 0x0000000f ; ..... 2 blit_pixel3 0x0000f000, 12 ; ..... 3 blit_pixel3 0x00000f00, 8 ; ..... 4 blit_pixel3 0x00f00000, 20 ; ..... 5 blit_pixel3 0x000f0000, 16 ; ..... 6 blit_pixel3 0xf0000000, 28 ; ..... 7 blit_pixel3 0x0f000000, 24 ; ..... 8 cache_align .cleanup: pop dword [esi] popad ret cache_align ; ---------------------------------------- __drawtile3: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi test ebx, ebx jz near .cleanup ; Don't waste time if the tile is blank! mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel3_trans 0x0f000000, 24 ; pixel 8 blit_pixel3_trans 0xf0000000, 28 ; ..... 7 blit_pixel3_trans 0x000f0000, 16 ; ..... 6 blit_pixel3_trans 0x00f00000, 20 ; ..... 5 blit_pixel3_trans 0x00000f00, 8 ; ..... 4 blit_pixel3_trans 0x0000f000, 12 ; ..... 3 blit_pixel3_trans 0x0000000f ; ..... 2 blit_pixel3_trans 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel3_trans 0x000000f0, 4 ; pixel 1 blit_pixel3_trans 0x0000000f ; ..... 2 blit_pixel3_trans 0x0000f000, 12 ; ..... 3 blit_pixel3_trans 0x00000f00, 8 ; ..... 4 blit_pixel3_trans 0x00f00000, 20 ; ..... 5 blit_pixel3_trans 0x000f0000, 16 ; ..... 6 blit_pixel3_trans 0xf0000000, 28 ; ..... 7 blit_pixel3_trans 0x0f000000, 24 ; ..... 8 cache_align .cleanup: popad ret cache_align ; ---------------------------------------- __drawtile4_solid: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov ecx, esi mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax ; - mov edi, [__reg] mov edx, [edi + 7] push dword [esi] and edx, 0x3f mov eax, [ecx + edx*4] mov [esi], eax ; - push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel4 0x0f000000, 24 ; pixel 8 blit_pixel4 0xf0000000, 28 ; ..... 7 blit_pixel4 0x000f0000, 16 ; ..... 6 blit_pixel4 0x00f00000, 20 ; ..... 5 blit_pixel4 0x00000f00, 8 ; ..... 4 blit_pixel4 0x0000f000, 12 ; ..... 3 blit_pixel4 0x0000000f ; ..... 2 blit_pixel4 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel4 0x000000f0, 4 ; pixel 1 blit_pixel4 0x0000000f ; ..... 2 blit_pixel4 0x0000f000, 12 ; ..... 3 blit_pixel4 0x00000f00, 8 ; ..... 4 blit_pixel4 0x00f00000, 20 ; ..... 5 blit_pixel4 0x000f0000, 16 ; ..... 6 blit_pixel4 0xf0000000, 28 ; ..... 7 blit_pixel4 0x0f000000, 24 ; ..... 8 cache_align .cleanup: pop dword [esi] popad ret cache_align ; ---------------------------------------- __drawtile4: pushad mov ebp, esp .setup .get_pal: mov ebx, which mov esi, [__highpal] mov eax, ebx shr eax, byte 7 and eax, 0xc0 add esi, eax push esi .check_y_flip: mov eax, ebx xor ecx, ecx mov edx, line test eax, 0x1000 jz .check_interlace .y_flipped: xor edx, byte 7 cache_align .check_interlace: mov esi, [__reg] mov cl, [esi+12] mov esi, [__vram] and eax, 0x7ff test cl, byte 0x2 jz .no_interlace .interlace: lea edx, [edx*8] shl eax, 6 jmp .check_x_flip cache_align .no_interlace: lea edx, [edx*4] shl eax, 5 cache_align .check_x_flip: add eax, edx mov edi, where lea esi, [esi+eax] mov ebx, [esi] pop esi test ebx, ebx jz near .cleanup ; Don't waste time if the tile is blank! mov eax, which test eax, 0x800 jz near .x_not_flipped .x_flipped: blit_pixel4_trans 0x0f000000, 24 ; pixel 8 blit_pixel4_trans 0xf0000000, 28 ; ..... 7 blit_pixel4_trans 0x000f0000, 16 ; ..... 6 blit_pixel4_trans 0x00f00000, 20 ; ..... 5 blit_pixel4_trans 0x00000f00, 8 ; ..... 4 blit_pixel4_trans 0x0000f000, 12 ; ..... 3 blit_pixel4_trans 0x0000000f ; ..... 2 blit_pixel4_trans 0x000000f0, 4 ; ..... 1 jmp .cleanup cache_align .x_not_flipped: blit_pixel4_trans 0x000000f0, 4 ; pixel 1 blit_pixel4_trans 0x0000000f ; ..... 2 blit_pixel4_trans 0x0000f000, 12 ; ..... 3 blit_pixel4_trans 0x00000f00, 8 ; ..... 4 blit_pixel4_trans 0x00f00000, 20 ; ..... 5 blit_pixel4_trans 0x000f0000, 16 ; ..... 6 blit_pixel4_trans 0xf0000000, 28 ; ..... 7 blit_pixel4_trans 0x0f000000, 24 ; ..... 8 cache_align .cleanup: popad ret cache_align section .data __vram dd 0 __reg dd 0 __highpal dd 0 ; ---------------------------------------- dgen-sdl-1.23/ctv.asmu 644 1750 1750 5121 7027317553 7750 ; CTV! bits 32 section .text ;extern "C" int blur_bitmap_16 ; (unsigned char *dest,int len); global _blur_bitmap_16 global _test_ctv times ($$-$) & 3 db 0 _blur_bitmap_16: push edi ; point to screen push edx ; temporary for unwrapping push ecx ; count push ebx ; last pixel ; ax = current pixel xor ebx,ebx ; Last pixel mov edi,[esp+20] ; edi is a pointer to the bitmap mov ecx,[esp+24] ; ecx is the amount of pixels to blur blur16_loop: mov ax,word[edi] mov dx,ax and ax,0x07e0 and dx,0xf81f rol eax,16 mov ax,dx ; Now we have unwrapped the green middle out of eax mov edx,eax ; ebx=this pixel (unwrapped) before we changed it add eax,ebx ; add last pixel to this one mov ebx,edx ; ebx=this pixel for next time sar eax,1 ; wrap up again mov edx,eax ror edx,16 and dx,0x07e0 and ax,0xf81f or ax,dx ;finished pixel in ax ;mov word[edi],ax ;add edi,2 stosw loop blur16_loop pop ebx pop ecx pop edx pop edi xor eax,eax ret ; -------------------------------------- bits 32 section .text ;extern "C" int blur_bitmap_15 ; (unsigned char *dest,int len); global _blur_bitmap_15 times ($$-$) & 3 db 0 _blur_bitmap_15: push edi ; point to screen push edx ; temporary for unwrapping push ecx ; count push ebx ; last pixel ; ax = current pixel xor ebx,ebx ; Last pixel mov edi,[esp+20] ; edi is a pointer to the bitmap mov ecx,[esp+24] ; ecx is the amount of pixels to blur blur15_loop: mov ax,word[edi] mov dx,ax and ax,0x03e0 and dx,0x7c1f rol eax,16 mov ax,dx ; Now we have unwrapped the green middle out of eax mov edx,eax ; ebx=this pixel (unwrapped) before we changed it add eax,ebx ; add last pixel to this one mov ebx,edx ; ebx=this pixel for next time sar eax,1 ; wrap up again mov edx,eax ror edx,16 and dx,0x03e0 and ax,0x7c1f or ax,dx ;finished pixel in ax ;mov word[edi],ax ;add edi,2 stosw loop blur15_loop pop ebx pop ecx pop edx pop edi xor eax,eax ret ; ---------------------------- bits 32 section .text ;extern "C" int test_ctv ; (unsigned char *dest,int len); global _test_ctv times ($$-$) & 3 db 0 _test_ctv: push edi ; point to screen push edx ; temporary for unwrapping push ecx ; count push ebx ; last pixel ; ax = current pixel xor ebx,ebx ; Last pixel mov edi,[esp+20] ; edi is a pointer to the bitmap mov ecx,[esp+24] ; ecx is the amount of pixels to blur test_loop: mov ax,word[edi] mov dx,ax rol eax,16 mov ax,dx mov edx,eax ; ebx=this pixel (unwrapped) before we changed it mov ebx,edx ; ebx=this pixel for next time sar eax,1 mov edx,eax ror edx,16 ;finished pixel in ax ;mov word[edi],ax ;add edi,2 stosw loop test_loop pop ebx pop ecx pop edx pop edi xor eax,eax ret dgen-sdl-1.23/asm_memcpy.asmu 644 1750 1750 1166 7027317553 11313 bits 32 section .text ;extern "C" int asm_memcpy ; (unsigned char *dest, unsigned char *src, int len); global _asm_memcpy times ($$-$) & 3 db 0 _asm_memcpy: pushad ; save registers mov edi,[esp+36] ; get 1st argument mov esi,[esp+40] ; ...2nd mov eax,[esp+44] ; ...3rd mov edx, eax shr eax, 2 ; figure out how many 4 byte chunks we have and edx, 3 ; also figure out slack test eax, eax ; Do we have any big chunks? push edx jz .slack ; If not, just do slack mov ecx,eax rep movsd ; move 4 byte chunks .slack: pop ecx rep movsb ; move 1 byte slack popad ; clean up ret ; -------------------------------------- dgen-sdl-1.23/mmx_memcpy.asmu 644 1750 1750 1472 7027317555 11336 bits 32 section .text ;extern "C" int mmx_memcpy ; (unsigned char *dest, unsigned char *src, int len); global _mmx_memcpy times ($$-$) & 3 db 0 _mmx_memcpy: pushad ; save registers mov edi,[esp+36] ; get 1st argument mov esi,[esp+40] ; ...2nd mov eax,[esp+44] ; ...3rd mov edx, eax shr eax, byte 3 ; figure out how many 8 byte chunks we have and edx, byte 7 ; also figure out slack test eax, eax ; Do we have any big chunks? push edx jz .slack ; If not, let's just do slack mov ecx,eax .mmx_move: movq mm0,qword[esi] ; move 8 byte blocks using MMX movq qword[edi],mm0 add esi, byte 8 ; increment pointers add edi, byte 8 loopnz .mmx_move ; continue until CX=0 .slack: pop ecx rep movsb ; move 1 byte slack emms ; Free up for the FPU popad ; clean up ret ; -------------------------------------- dgen-sdl-1.23/sn76496u.c 644 1750 1750 4510 7027317556 7662 { int i; DATATYPE *buf = (DATATYPE *)buffer; struct SN76496 *R = &sn[chip]; /* If the volume is 0, increase the counter */ for (i = 0;i < 4;i++) { if (R->Volume[i] == 0) { /* note that I do count += length, NOT count = length + 1. You might think */ /* it's the same since the volume is 0, but doing the latter could cause */ /* interferencies when the program is rapidly modulating the volume. */ if (R->Count[i] <= length*STEP) R->Count[i] += length*STEP; } } while (length > 0) { int vol[4]; unsigned int out; int left; /* vol[] keeps track of how long each square wave stays */ /* in the 1 position during the sample period. */ vol[0] = vol[1] = vol[2] = vol[3] = 0; for (i = 0;i < 3;i++) { if (R->Output[i]) vol[i] += R->Count[i]; R->Count[i] -= STEP; /* Period[i] is the half period of the square wave. Here, in each */ /* loop I add Period[i] twice, so that at the end of the loop the */ /* square wave is in the same status (0 or 1) it was at the start. */ /* vol[i] is also incremented by Period[i], since the wave has been 1 */ /* exactly half of the time, regardless of the initial position. */ /* If we exit the loop in the middle, Output[i] has to be inverted */ /* and vol[i] incremented only if the exit status of the square */ /* wave is 1. */ while (R->Count[i] <= 0) { R->Count[i] += R->Period[i]; if (R->Count[i] > 0) { R->Output[i] ^= 1; if (R->Output[i]) vol[i] += R->Period[i]; break; } R->Count[i] += R->Period[i]; vol[i] += R->Period[i]; } if (R->Output[i]) vol[i] -= R->Count[i]; } left = STEP; do { int nextevent; if (R->Count[3] < left) nextevent = R->Count[3]; else nextevent = left; if (R->Output[3]) vol[3] += R->Count[3]; R->Count[3] -= nextevent; if (R->Count[3] <= 0) { if (R->RNG & 1) R->RNG ^= R->NoiseFB; R->RNG >>= 1; R->Output[3] = R->RNG & 1; R->Count[3] += R->Period[3]; if (R->Output[3]) vol[3] += R->Period[3]; } if (R->Output[3]) vol[3] -= R->Count[3]; left -= nextevent; } while (left > 0); out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + vol[2] * R->Volume[2] + vol[3] * R->Volume[3]; if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; *(buf++) = ((DATACONV(out)*3)>>3); // Dave: a bit quieter length--; } } dgen-sdl-1.23/zz80.c 644 1750 1750 1411105 7176132472 7330 /* Multi-Z80 32 Bit emulator */ /* Copyright 1996-2000 Neil Bradley, All rights reserved * * License agreement: * * (MZ80 Refers to both the assembly code emitted by makeZ80.c and makeZ80.c * itself) * * MZ80 May be distributed in unmodified form to any medium. * * MZ80 May not be sold, or sold as a part of a commercial package without * the express written permission of Neil Bradley (neil@synthcom.com). This * includes shareware. * * Modified versions of MZ80 may not be publicly redistributed without author * approval (neil@synthcom.com). This includes distributing via a publicly * accessible LAN. You may make your own source modifications and distribute * MZ80 in source or object form, but if you make modifications to MZ80 * then it should be noted in the top as a comment in makeZ80.c. * * MZ80 Licensing for commercial applications is available. Please email * neil@synthcom.com for details. * * Synthcom Systems, Inc, and Neil Bradley will not be held responsible for * any damage done by the use of MZ80. It is purely "as-is". * * If you use MZ80 in a freeware application, credit in the following text: * * "Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)" * * must accompany the freeware application within the application itself or * in the documentation. * * Legal stuff aside: * * If you find problems with MZ80, please email the author so they can get * resolved. If you find a bug and fix it, please also email the author so * that those bug fixes can be propogated to the installed base of MZ80 * users. If you find performance improvements or problems with MZ80, please * email the author with your changes/suggestions and they will be rolled in * with subsequent releases of MZ80. * * The whole idea of this emulator is to have the fastest available 32 bit * Multi-Z80 emulator for the PC, giving maximum performance. */ #include #include #include #include "mz80.h" UINT32 z80intAddr; UINT32 z80pc; /* Modular global variables go here*/ static CONTEXTMZ80 cpu; /* CPU Context */ static UINT8 *pbPC; /* Program counter normalized */ static UINT8 *pbSP; /* Stack pointer normalized */ static struct MemoryReadByte *psMemRead; /* Read memory structure */ static struct MemoryWriteByte *psMemWrite; /* Write memory structure */ static struct z80PortRead *psIoRead; /* Read I/O structure */ static struct z80PortWrite *psIoWrite; /* Write memory structure */ static INT32 sdwCyclesRemaining; /* Used as a countdown */ static UINT32 dwReturnCode; /* Return code from exec() */ static UINT32 dwOriginalCycles; /* How many cycles did we start with? */ static UINT32 dwElapsedTicks; /* How many ticks did we elapse? */ static INT32 sdwAddr; /* Temporary address storage */ static UINT32 dwAddr; /* Temporary stack address */ static UINT8 *pbAddAdcTable; /* Pointer to add/adc flag table */ static UINT8 *pbSubSbcTable; /* Pointer to sub/sbc flag table */ static UINT32 dwTemp; /* Temporary value */ static UINT8 bTemp; /* Temporary value */ static UINT8 bTemp2; /* Temporary value */ /* Precomputed flag tables */ static UINT8 bPostIncFlags[0x100] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x50 }; static UINT8 bPostDecFlags[0x100] = { 0x92,0x42,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, 0x16,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82 }; static UINT8 bPostORFlags[0x100] = { 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84, 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84, 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84, 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84 }; static UINT8 bPostANDFlags[0x100] = { 0x54,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14, 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10, 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10, 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14, 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10, 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14, 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14, 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10, 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90, 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94, 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94, 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90, 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94, 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90, 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90, 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94 }; static UINT16 wDAATable[0x800] = { 0x5400,0x1001,0x1002,0x1403,0x1004,0x1405,0x1406,0x1007, 0x1008,0x1409,0x1010,0x1411,0x1412,0x1013,0x1414,0x1015, 0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,0x1016,0x1417, 0x1418,0x1019,0x1020,0x1421,0x1422,0x1023,0x1424,0x1025, 0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,0x1026,0x1427, 0x1428,0x1029,0x1430,0x1031,0x1032,0x1433,0x1034,0x1435, 0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,0x1436,0x1037, 0x1038,0x1439,0x1040,0x1441,0x1442,0x1043,0x1444,0x1045, 0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,0x1046,0x1447, 0x1448,0x1049,0x1450,0x1051,0x1052,0x1453,0x1054,0x1455, 0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,0x1456,0x1057, 0x1058,0x1459,0x1460,0x1061,0x1062,0x1463,0x1064,0x1465, 0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,0x1466,0x1067, 0x1068,0x1469,0x1070,0x1471,0x1472,0x1073,0x1474,0x1075, 0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,0x1076,0x1477, 0x1478,0x1079,0x9080,0x9481,0x9482,0x9083,0x9484,0x9085, 0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,0x9086,0x9487, 0x9488,0x9089,0x9490,0x9091,0x9092,0x9493,0x9094,0x9495, 0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,0x9496,0x9097, 0x9098,0x9499,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505, 0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,0x1506,0x1107, 0x1108,0x1509,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115, 0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,0x1116,0x1517, 0x1518,0x1119,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125, 0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,0x1126,0x1527, 0x1528,0x1129,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535, 0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,0x1536,0x1137, 0x1138,0x1539,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145, 0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,0x1146,0x1547, 0x1548,0x1149,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555, 0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,0x1556,0x1157, 0x1158,0x1559,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565, 0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,0x1566,0x1167, 0x1168,0x1569,0x1170,0x1571,0x1572,0x1173,0x1574,0x1175, 0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,0x1176,0x1577, 0x1578,0x1179,0x9180,0x9581,0x9582,0x9183,0x9584,0x9185, 0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,0x9186,0x9587, 0x9588,0x9189,0x9590,0x9191,0x9192,0x9593,0x9194,0x9595, 0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,0x9596,0x9197, 0x9198,0x9599,0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5, 0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,0x95a6,0x91a7, 0x91a8,0x95a9,0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5, 0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,0x91b6,0x95b7, 0x95b8,0x91b9,0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5, 0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,0x95c6,0x91c7, 0x91c8,0x95c9,0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5, 0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,0x91d6,0x95d7, 0x95d8,0x91d9,0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5, 0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,0x91e6,0x95e7, 0x95e8,0x91e9,0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5, 0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,0x95f6,0x91f7, 0x91f8,0x95f9,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505, 0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,0x1506,0x1107, 0x1108,0x1509,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115, 0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,0x1116,0x1517, 0x1518,0x1119,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125, 0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,0x1126,0x1527, 0x1528,0x1129,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535, 0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,0x1536,0x1137, 0x1138,0x1539,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145, 0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,0x1146,0x1547, 0x1548,0x1149,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555, 0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,0x1556,0x1157, 0x1158,0x1559,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565, 0x1406,0x1007,0x1008,0x1409,0x140a,0x100b,0x140c,0x100d, 0x100e,0x140f,0x1010,0x1411,0x1412,0x1013,0x1414,0x1015, 0x1016,0x1417,0x1418,0x1019,0x101a,0x141b,0x101c,0x141d, 0x141e,0x101f,0x1020,0x1421,0x1422,0x1023,0x1424,0x1025, 0x1026,0x1427,0x1428,0x1029,0x102a,0x142b,0x102c,0x142d, 0x142e,0x102f,0x1430,0x1031,0x1032,0x1433,0x1034,0x1435, 0x1436,0x1037,0x1038,0x1439,0x143a,0x103b,0x143c,0x103d, 0x103e,0x143f,0x1040,0x1441,0x1442,0x1043,0x1444,0x1045, 0x1046,0x1447,0x1448,0x1049,0x104a,0x144b,0x104c,0x144d, 0x144e,0x104f,0x1450,0x1051,0x1052,0x1453,0x1054,0x1455, 0x1456,0x1057,0x1058,0x1459,0x145a,0x105b,0x145c,0x105d, 0x105e,0x145f,0x1460,0x1061,0x1062,0x1463,0x1064,0x1465, 0x1466,0x1067,0x1068,0x1469,0x146a,0x106b,0x146c,0x106d, 0x106e,0x146f,0x1070,0x1471,0x1472,0x1073,0x1474,0x1075, 0x1076,0x1477,0x1478,0x1079,0x107a,0x147b,0x107c,0x147d, 0x147e,0x107f,0x9080,0x9481,0x9482,0x9083,0x9484,0x9085, 0x9086,0x9487,0x9488,0x9089,0x908a,0x948b,0x908c,0x948d, 0x948e,0x908f,0x9490,0x9091,0x9092,0x9493,0x9094,0x9495, 0x9496,0x9097,0x9098,0x9499,0x949a,0x909b,0x949c,0x909d, 0x909e,0x949f,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505, 0x1506,0x1107,0x1108,0x1509,0x150a,0x110b,0x150c,0x110d, 0x110e,0x150f,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115, 0x1116,0x1517,0x1518,0x1119,0x111a,0x151b,0x111c,0x151d, 0x151e,0x111f,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125, 0x1126,0x1527,0x1528,0x1129,0x112a,0x152b,0x112c,0x152d, 0x152e,0x112f,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535, 0x1536,0x1137,0x1138,0x1539,0x153a,0x113b,0x153c,0x113d, 0x113e,0x153f,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145, 0x1146,0x1547,0x1548,0x1149,0x114a,0x154b,0x114c,0x154d, 0x154e,0x114f,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555, 0x1556,0x1157,0x1158,0x1559,0x155a,0x115b,0x155c,0x115d, 0x115e,0x155f,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565, 0x1566,0x1167,0x1168,0x1569,0x156a,0x116b,0x156c,0x116d, 0x116e,0x156f,0x1170,0x1571,0x1572,0x1173,0x1574,0x1175, 0x1176,0x1577,0x1578,0x1179,0x117a,0x157b,0x117c,0x157d, 0x157e,0x117f,0x9180,0x9581,0x9582,0x9183,0x9584,0x9185, 0x9186,0x9587,0x9588,0x9189,0x918a,0x958b,0x918c,0x958d, 0x958e,0x918f,0x9590,0x9191,0x9192,0x9593,0x9194,0x9595, 0x9596,0x9197,0x9198,0x9599,0x959a,0x919b,0x959c,0x919d, 0x919e,0x959f,0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5, 0x95a6,0x91a7,0x91a8,0x95a9,0x95aa,0x91ab,0x95ac,0x91ad, 0x91ae,0x95af,0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5, 0x91b6,0x95b7,0x95b8,0x91b9,0x91ba,0x95bb,0x91bc,0x95bd, 0x95be,0x91bf,0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5, 0x95c6,0x91c7,0x91c8,0x95c9,0x95ca,0x91cb,0x95cc,0x91cd, 0x91ce,0x95cf,0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5, 0x91d6,0x95d7,0x95d8,0x91d9,0x91da,0x95db,0x91dc,0x95dd, 0x95de,0x91df,0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5, 0x91e6,0x95e7,0x95e8,0x91e9,0x91ea,0x95eb,0x91ec,0x95ed, 0x95ee,0x91ef,0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5, 0x95f6,0x91f7,0x91f8,0x95f9,0x95fa,0x91fb,0x95fc,0x91fd, 0x91fe,0x95ff,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505, 0x1506,0x1107,0x1108,0x1509,0x150a,0x110b,0x150c,0x110d, 0x110e,0x150f,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115, 0x1116,0x1517,0x1518,0x1119,0x111a,0x151b,0x111c,0x151d, 0x151e,0x111f,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125, 0x1126,0x1527,0x1528,0x1129,0x112a,0x152b,0x112c,0x152d, 0x152e,0x112f,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535, 0x1536,0x1137,0x1138,0x1539,0x153a,0x113b,0x153c,0x113d, 0x113e,0x153f,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145, 0x1146,0x1547,0x1548,0x1149,0x114a,0x154b,0x114c,0x154d, 0x154e,0x114f,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555, 0x1556,0x1157,0x1158,0x1559,0x155a,0x115b,0x155c,0x115d, 0x115e,0x155f,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565, 0x5600,0x1201,0x1202,0x1603,0x1204,0x1605,0x1606,0x1207, 0x1208,0x1609,0x1204,0x1605,0x1606,0x1207,0x1208,0x1609, 0x1210,0x1611,0x1612,0x1213,0x1614,0x1215,0x1216,0x1617, 0x1618,0x1219,0x1614,0x1215,0x1216,0x1617,0x1618,0x1219, 0x1220,0x1621,0x1622,0x1223,0x1624,0x1225,0x1226,0x1627, 0x1628,0x1229,0x1624,0x1225,0x1226,0x1627,0x1628,0x1229, 0x1630,0x1231,0x1232,0x1633,0x1234,0x1635,0x1636,0x1237, 0x1238,0x1639,0x1234,0x1635,0x1636,0x1237,0x1238,0x1639, 0x1240,0x1641,0x1642,0x1243,0x1644,0x1245,0x1246,0x1647, 0x1648,0x1249,0x1644,0x1245,0x1246,0x1647,0x1648,0x1249, 0x1650,0x1251,0x1252,0x1653,0x1254,0x1655,0x1656,0x1257, 0x1258,0x1659,0x1254,0x1655,0x1656,0x1257,0x1258,0x1659, 0x1660,0x1261,0x1262,0x1663,0x1264,0x1665,0x1666,0x1267, 0x1268,0x1669,0x1264,0x1665,0x1666,0x1267,0x1268,0x1669, 0x1270,0x1671,0x1672,0x1273,0x1674,0x1275,0x1276,0x1677, 0x1678,0x1279,0x1674,0x1275,0x1276,0x1677,0x1678,0x1279, 0x9280,0x9681,0x9682,0x9283,0x9684,0x9285,0x9286,0x9687, 0x9688,0x9289,0x9684,0x9285,0x9286,0x9687,0x9688,0x9289, 0x9690,0x9291,0x9292,0x9693,0x9294,0x9695,0x9696,0x9297, 0x9298,0x9699,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739, 0x1340,0x1741,0x1742,0x1343,0x1744,0x1345,0x1346,0x1747, 0x1748,0x1349,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349, 0x1750,0x1351,0x1352,0x1753,0x1354,0x1755,0x1756,0x1357, 0x1358,0x1759,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759, 0x1760,0x1361,0x1362,0x1763,0x1364,0x1765,0x1766,0x1367, 0x1368,0x1769,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769, 0x1370,0x1771,0x1772,0x1373,0x1774,0x1375,0x1376,0x1777, 0x1778,0x1379,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379, 0x9380,0x9781,0x9782,0x9383,0x9784,0x9385,0x9386,0x9787, 0x9788,0x9389,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389, 0x9790,0x9391,0x9392,0x9793,0x9394,0x9795,0x9796,0x9397, 0x9398,0x9799,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799, 0x97a0,0x93a1,0x93a2,0x97a3,0x93a4,0x97a5,0x97a6,0x93a7, 0x93a8,0x97a9,0x93a4,0x97a5,0x97a6,0x93a7,0x93a8,0x97a9, 0x93b0,0x97b1,0x97b2,0x93b3,0x97b4,0x93b5,0x93b6,0x97b7, 0x97b8,0x93b9,0x97b4,0x93b5,0x93b6,0x97b7,0x97b8,0x93b9, 0x97c0,0x93c1,0x93c2,0x97c3,0x93c4,0x97c5,0x97c6,0x93c7, 0x93c8,0x97c9,0x93c4,0x97c5,0x97c6,0x93c7,0x93c8,0x97c9, 0x93d0,0x97d1,0x97d2,0x93d3,0x97d4,0x93d5,0x93d6,0x97d7, 0x97d8,0x93d9,0x97d4,0x93d5,0x93d6,0x97d7,0x97d8,0x93d9, 0x93e0,0x97e1,0x97e2,0x93e3,0x97e4,0x93e5,0x93e6,0x97e7, 0x97e8,0x93e9,0x97e4,0x93e5,0x93e6,0x97e7,0x97e8,0x93e9, 0x97f0,0x93f1,0x93f2,0x97f3,0x93f4,0x97f5,0x97f6,0x93f7, 0x93f8,0x97f9,0x93f4,0x97f5,0x97f6,0x93f7,0x93f8,0x97f9, 0x5700,0x1301,0x1302,0x1703,0x1304,0x1705,0x1706,0x1307, 0x1308,0x1709,0x1304,0x1705,0x1706,0x1307,0x1308,0x1709, 0x1310,0x1711,0x1712,0x1313,0x1714,0x1315,0x1316,0x1717, 0x1718,0x1319,0x1714,0x1315,0x1316,0x1717,0x1718,0x1319, 0x1320,0x1721,0x1722,0x1323,0x1724,0x1325,0x1326,0x1727, 0x1728,0x1329,0x1724,0x1325,0x1326,0x1727,0x1728,0x1329, 0x1730,0x1331,0x1332,0x1733,0x1334,0x1735,0x1736,0x1337, 0x1338,0x1739,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739, 0x1340,0x1741,0x1742,0x1343,0x1744,0x1345,0x1346,0x1747, 0x1748,0x1349,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349, 0x1750,0x1351,0x1352,0x1753,0x1354,0x1755,0x1756,0x1357, 0x1358,0x1759,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759, 0x1760,0x1361,0x1362,0x1763,0x1364,0x1765,0x1766,0x1367, 0x1368,0x1769,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769, 0x1370,0x1771,0x1772,0x1373,0x1774,0x1375,0x1376,0x1777, 0x1778,0x1379,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379, 0x9380,0x9781,0x9782,0x9383,0x9784,0x9385,0x9386,0x9787, 0x9788,0x9389,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389, 0x9790,0x9391,0x9392,0x9793,0x9394,0x9795,0x9796,0x9397, 0x9398,0x9799,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799, 0x97fa,0x93fb,0x97fc,0x93fd,0x93fe,0x97ff,0x5600,0x1201, 0x1202,0x1603,0x1204,0x1605,0x1606,0x1207,0x1208,0x1609, 0x160a,0x120b,0x160c,0x120d,0x120e,0x160f,0x1210,0x1611, 0x1612,0x1213,0x1614,0x1215,0x1216,0x1617,0x1618,0x1219, 0x121a,0x161b,0x121c,0x161d,0x161e,0x121f,0x1220,0x1621, 0x1622,0x1223,0x1624,0x1225,0x1226,0x1627,0x1628,0x1229, 0x122a,0x162b,0x122c,0x162d,0x162e,0x122f,0x1630,0x1231, 0x1232,0x1633,0x1234,0x1635,0x1636,0x1237,0x1238,0x1639, 0x163a,0x123b,0x163c,0x123d,0x123e,0x163f,0x1240,0x1641, 0x1642,0x1243,0x1644,0x1245,0x1246,0x1647,0x1648,0x1249, 0x124a,0x164b,0x124c,0x164d,0x164e,0x124f,0x1650,0x1251, 0x1252,0x1653,0x1254,0x1655,0x1656,0x1257,0x1258,0x1659, 0x165a,0x125b,0x165c,0x125d,0x125e,0x165f,0x1660,0x1261, 0x1262,0x1663,0x1264,0x1665,0x1666,0x1267,0x1268,0x1669, 0x166a,0x126b,0x166c,0x126d,0x126e,0x166f,0x1270,0x1671, 0x1672,0x1273,0x1674,0x1275,0x1276,0x1677,0x1678,0x1279, 0x127a,0x167b,0x127c,0x167d,0x167e,0x127f,0x9280,0x9681, 0x9682,0x9283,0x9684,0x9285,0x9286,0x9687,0x9688,0x9289, 0x928a,0x968b,0x928c,0x968d,0x968e,0x928f,0x9690,0x9291, 0x9292,0x9693,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739, 0x173a,0x133b,0x173c,0x133d,0x133e,0x173f,0x1340,0x1741, 0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349, 0x134a,0x174b,0x134c,0x174d,0x174e,0x134f,0x1750,0x1351, 0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759, 0x175a,0x135b,0x175c,0x135d,0x135e,0x175f,0x1760,0x1361, 0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769, 0x176a,0x136b,0x176c,0x136d,0x136e,0x176f,0x1370,0x1771, 0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379, 0x137a,0x177b,0x137c,0x177d,0x177e,0x137f,0x9380,0x9781, 0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389, 0x938a,0x978b,0x938c,0x978d,0x978e,0x938f,0x9790,0x9391, 0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799, 0x979a,0x939b,0x979c,0x939d,0x939e,0x979f,0x97a0,0x93a1, 0x93a2,0x97a3,0x93a4,0x97a5,0x97a6,0x93a7,0x93a8,0x97a9, 0x97aa,0x93ab,0x97ac,0x93ad,0x93ae,0x97af,0x93b0,0x97b1, 0x97b2,0x93b3,0x97b4,0x93b5,0x93b6,0x97b7,0x97b8,0x93b9, 0x93ba,0x97bb,0x93bc,0x97bd,0x97be,0x93bf,0x97c0,0x93c1, 0x93c2,0x97c3,0x93c4,0x97c5,0x97c6,0x93c7,0x93c8,0x97c9, 0x97ca,0x93cb,0x97cc,0x93cd,0x93ce,0x97cf,0x93d0,0x97d1, 0x97d2,0x93d3,0x97d4,0x93d5,0x93d6,0x97d7,0x97d8,0x93d9, 0x93da,0x97db,0x93dc,0x97dd,0x97de,0x93df,0x93e0,0x97e1, 0x97e2,0x93e3,0x97e4,0x93e5,0x93e6,0x97e7,0x97e8,0x93e9, 0x93ea,0x97eb,0x93ec,0x97ed,0x97ee,0x93ef,0x97f0,0x93f1, 0x93f2,0x97f3,0x93f4,0x97f5,0x97f6,0x93f7,0x93f8,0x97f9, 0x97fa,0x93fb,0x97fc,0x93fd,0x93fe,0x97ff,0x5700,0x1301, 0x1302,0x1703,0x1304,0x1705,0x1706,0x1307,0x1308,0x1709, 0x170a,0x130b,0x170c,0x130d,0x130e,0x170f,0x1310,0x1711, 0x1712,0x1313,0x1714,0x1315,0x1316,0x1717,0x1718,0x1319, 0x131a,0x171b,0x131c,0x171d,0x171e,0x131f,0x1320,0x1721, 0x1722,0x1323,0x1724,0x1325,0x1326,0x1727,0x1728,0x1329, 0x132a,0x172b,0x132c,0x172d,0x172e,0x132f,0x1730,0x1331, 0x1332,0x1733,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739, 0x173a,0x133b,0x173c,0x133d,0x133e,0x173f,0x1340,0x1741, 0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349, 0x134a,0x174b,0x134c,0x174d,0x174e,0x134f,0x1750,0x1351, 0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759, 0x175a,0x135b,0x175c,0x135d,0x135e,0x175f,0x1760,0x1361, 0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769, 0x176a,0x136b,0x176c,0x136d,0x136e,0x176f,0x1370,0x1771, 0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379, 0x137a,0x177b,0x137c,0x177d,0x177e,0x137f,0x9380,0x9781, 0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389, 0x938a,0x978b,0x938c,0x978d,0x978e,0x938f,0x9790,0x9391, 0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799 }; void DDFDCBHandler(UINT32 dwWhich); static void InvalidInstruction(UINT32 dwCount) { pbPC -= dwCount; /* Invalid instruction - back up */ dwReturnCode = (UINT32) pbPC - (UINT32) cpu.z80Base; dwOriginalCycles -= sdwCyclesRemaining; sdwCyclesRemaining = 0; } void CBHandler(void) { switch (*pbPC++) { case 0x00: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80B >> 7); cpu.z80B = (cpu.z80B << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80B]; break; } case 0x01: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80C >> 7); cpu.z80C = (cpu.z80C << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80C]; break; } case 0x02: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80D >> 7); cpu.z80D = (cpu.z80D << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80D]; break; } case 0x03: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80E >> 7); cpu.z80E = (cpu.z80E << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80E]; break; } case 0x04: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80H >> 7); cpu.z80H = (cpu.z80H << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80H]; break; } case 0x05: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80L >> 7); cpu.z80L = (cpu.z80L << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80L]; break; } case 0x06: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (bTemp >> 7); bTemp = (bTemp << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x07: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (cpu.z80A >> 7); cpu.z80A = (cpu.z80A << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[cpu.z80A]; break; } case 0x08: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B & Z80_FLAG_CARRY); cpu.z80B = (cpu.z80B >> 1) | (cpu.z80B << 7); cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x09: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C & Z80_FLAG_CARRY); cpu.z80C = (cpu.z80C >> 1) | (cpu.z80C << 7); cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x0a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D & Z80_FLAG_CARRY); cpu.z80D = (cpu.z80D >> 1) | (cpu.z80D << 7); cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x0b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E & Z80_FLAG_CARRY); cpu.z80E = (cpu.z80E >> 1) | (cpu.z80E << 7); cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x0c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H & Z80_FLAG_CARRY); cpu.z80H = (cpu.z80H >> 1) | (cpu.z80H << 7); cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x0d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L & Z80_FLAG_CARRY); cpu.z80L = (cpu.z80L >> 1) | (cpu.z80L << 7); cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x0e: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1) | (bTemp << 7); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x0f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY); cpu.z80A = (cpu.z80A >> 1) | (cpu.z80A << 7); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x10: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B >> 7); cpu.z80B = (cpu.z80B << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x11: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C >> 7); cpu.z80C = (cpu.z80C << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x12: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D >> 7); cpu.z80D = (cpu.z80D << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x13: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E >> 7); cpu.z80E = (cpu.z80E << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x14: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H >> 7); cpu.z80H = (cpu.z80H << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x15: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L >> 7); cpu.z80L = (cpu.z80L << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x16: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp >> 7); bTemp = (bTemp << 1) | bTemp2; cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x17: { sdwCyclesRemaining -= 8; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A >> 7); cpu.z80A = (cpu.z80A << 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x18: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B & Z80_FLAG_CARRY); cpu.z80B = (cpu.z80B >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x19: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C & Z80_FLAG_CARRY); cpu.z80C = (cpu.z80C >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x1a: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D & Z80_FLAG_CARRY); cpu.z80D = (cpu.z80D >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x1b: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E & Z80_FLAG_CARRY); cpu.z80E = (cpu.z80E >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x1c: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H & Z80_FLAG_CARRY); cpu.z80H = (cpu.z80H >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x1d: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L & Z80_FLAG_CARRY); cpu.z80L = (cpu.z80L >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x1e: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1) | bTemp2; cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x1f: { sdwCyclesRemaining -= 8; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY); cpu.z80A = (cpu.z80A >> 1) | bTemp2; cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x20: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B >> 7); cpu.z80B = (cpu.z80B << 1); cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x21: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C >> 7); cpu.z80C = (cpu.z80C << 1); cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x22: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D >> 7); cpu.z80D = (cpu.z80D << 1); cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x23: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E >> 7); cpu.z80E = (cpu.z80E << 1); cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x24: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H >> 7); cpu.z80H = (cpu.z80H << 1); cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x25: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L >> 7); cpu.z80L = (cpu.z80L << 1); cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x26: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp >> 7); bTemp = (bTemp << 1); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x27: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A >> 7); cpu.z80A = (cpu.z80A << 1); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x28: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B & Z80_FLAG_CARRY); cpu.z80B = (cpu.z80B >> 1) | (cpu.z80B & 0x80); cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x29: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C & Z80_FLAG_CARRY); cpu.z80C = (cpu.z80C >> 1) | (cpu.z80C & 0x80); cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x2a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D & Z80_FLAG_CARRY); cpu.z80D = (cpu.z80D >> 1) | (cpu.z80D & 0x80); cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x2b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E & Z80_FLAG_CARRY); cpu.z80E = (cpu.z80E >> 1) | (cpu.z80E & 0x80); cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x2c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H & Z80_FLAG_CARRY); cpu.z80H = (cpu.z80H >> 1) | (cpu.z80H & 0x80); cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x2d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L & Z80_FLAG_CARRY); cpu.z80L = (cpu.z80L >> 1) | (cpu.z80L & 0x80); cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x2e: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1) | (bTemp & 0x80); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x2f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY); cpu.z80A = (cpu.z80A >> 1) | (cpu.z80A & 0x80); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x30: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B >> 7); cpu.z80B = (cpu.z80B << 1); cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x31: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C >> 7); cpu.z80C = (cpu.z80C << 1); cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x32: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D >> 7); cpu.z80D = (cpu.z80D << 1); cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x33: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E >> 7); cpu.z80E = (cpu.z80E << 1); cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x34: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H >> 7); cpu.z80H = (cpu.z80H << 1); cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x35: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L >> 7); cpu.z80L = (cpu.z80L << 1); cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x36: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp >> 7); bTemp = (bTemp << 1); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x37: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A >> 7); cpu.z80A = (cpu.z80A << 1); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x38: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80B & Z80_FLAG_CARRY); cpu.z80B = (cpu.z80B >> 1); cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x39: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80C & Z80_FLAG_CARRY); cpu.z80C = (cpu.z80C >> 1); cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x3a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80D & Z80_FLAG_CARRY); cpu.z80D = (cpu.z80D >> 1); cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x3b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80E & Z80_FLAG_CARRY); cpu.z80E = (cpu.z80E >> 1); cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x3c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80H & Z80_FLAG_CARRY); cpu.z80H = (cpu.z80H >> 1); cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x3d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80L & Z80_FLAG_CARRY); cpu.z80L = (cpu.z80L >> 1); cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x3e: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x3f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY); cpu.z80A = (cpu.z80A >> 1); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x40: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x41: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x42: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x43: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x44: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x45: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x46: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x47: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x48: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x49: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4e: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x50: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x51: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x52: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x53: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x54: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x55: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x56: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x57: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x58: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x59: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5e: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x60: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x61: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x62: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x63: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x64: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x65: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x66: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x67: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x68: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x69: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6e: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x70: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x71: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x72: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x73: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x74: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x75: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x76: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x77: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x78: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80B & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x79: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80C & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7a: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80D & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7b: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80E & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7c: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80H & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7d: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80L & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7e: { sdwCyclesRemaining -= 12; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(bTemp & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7f: { sdwCyclesRemaining -= 8; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO); cpu.z80F |= (Z80_FLAG_HALF_CARRY); if (!(cpu.z80A & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x80: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xfe; break; } case 0x81: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xfe; break; } case 0x82: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xfe; break; } case 0x83: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xfe; break; } case 0x84: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xfe; break; } case 0x85: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xfe; break; } case 0x86: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xfe; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x87: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xfe; break; } case 0x88: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xfd; break; } case 0x89: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xfd; break; } case 0x8a: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xfd; break; } case 0x8b: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xfd; break; } case 0x8c: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xfd; break; } case 0x8d: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xfd; break; } case 0x8e: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xfd; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x8f: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xfd; break; } case 0x90: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xfb; break; } case 0x91: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xfb; break; } case 0x92: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xfb; break; } case 0x93: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xfb; break; } case 0x94: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xfb; break; } case 0x95: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xfb; break; } case 0x96: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xfb; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x97: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xfb; break; } case 0x98: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xf7; break; } case 0x99: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xf7; break; } case 0x9a: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xf7; break; } case 0x9b: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xf7; break; } case 0x9c: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xf7; break; } case 0x9d: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xf7; break; } case 0x9e: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xf7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x9f: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xf7; break; } case 0xa0: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xef; break; } case 0xa1: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xef; break; } case 0xa2: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xef; break; } case 0xa3: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xef; break; } case 0xa4: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xef; break; } case 0xa5: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xef; break; } case 0xa6: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xef; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xa7: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xef; break; } case 0xa8: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xdf; break; } case 0xa9: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xdf; break; } case 0xaa: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xdf; break; } case 0xab: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xdf; break; } case 0xac: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xdf; break; } case 0xad: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xdf; break; } case 0xae: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xdf; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xaf: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xdf; break; } case 0xb0: { sdwCyclesRemaining -= 8; cpu.z80B &= 0xbf; break; } case 0xb1: { sdwCyclesRemaining -= 8; cpu.z80C &= 0xbf; break; } case 0xb2: { sdwCyclesRemaining -= 8; cpu.z80D &= 0xbf; break; } case 0xb3: { sdwCyclesRemaining -= 8; cpu.z80E &= 0xbf; break; } case 0xb4: { sdwCyclesRemaining -= 8; cpu.z80H &= 0xbf; break; } case 0xb5: { sdwCyclesRemaining -= 8; cpu.z80L &= 0xbf; break; } case 0xb6: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0xbf; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xb7: { sdwCyclesRemaining -= 8; cpu.z80A &= 0xbf; break; } case 0xb8: { sdwCyclesRemaining -= 8; cpu.z80B &= 0x7f; break; } case 0xb9: { sdwCyclesRemaining -= 8; cpu.z80C &= 0x7f; break; } case 0xba: { sdwCyclesRemaining -= 8; cpu.z80D &= 0x7f; break; } case 0xbb: { sdwCyclesRemaining -= 8; cpu.z80E &= 0x7f; break; } case 0xbc: { sdwCyclesRemaining -= 8; cpu.z80H &= 0x7f; break; } case 0xbd: { sdwCyclesRemaining -= 8; cpu.z80L &= 0x7f; break; } case 0xbe: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp &= 0x7f; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xbf: { sdwCyclesRemaining -= 8; cpu.z80A &= 0x7f; break; } case 0xc0: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x01; break; } case 0xc1: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x01; break; } case 0xc2: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x01; break; } case 0xc3: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x01; break; } case 0xc4: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x01; break; } case 0xc5: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x01; break; } case 0xc6: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x01; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xc7: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x01; break; } case 0xc8: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x02; break; } case 0xc9: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x02; break; } case 0xca: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x02; break; } case 0xcb: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x02; break; } case 0xcc: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x02; break; } case 0xcd: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x02; break; } case 0xce: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x02; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xcf: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x02; break; } case 0xd0: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x04; break; } case 0xd1: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x04; break; } case 0xd2: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x04; break; } case 0xd3: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x04; break; } case 0xd4: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x04; break; } case 0xd5: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x04; break; } case 0xd6: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x04; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xd7: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x04; break; } case 0xd8: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x08; break; } case 0xd9: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x08; break; } case 0xda: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x08; break; } case 0xdb: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x08; break; } case 0xdc: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x08; break; } case 0xdd: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x08; break; } case 0xde: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x08; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xdf: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x08; break; } case 0xe0: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x10; break; } case 0xe1: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x10; break; } case 0xe2: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x10; break; } case 0xe3: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x10; break; } case 0xe4: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x10; break; } case 0xe5: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x10; break; } case 0xe6: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x10; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xe7: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x10; break; } case 0xe8: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x20; break; } case 0xe9: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x20; break; } case 0xea: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x20; break; } case 0xeb: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x20; break; } case 0xec: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x20; break; } case 0xed: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x20; break; } case 0xee: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x20; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xef: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x20; break; } case 0xf0: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x40; break; } case 0xf1: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x40; break; } case 0xf2: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x40; break; } case 0xf3: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x40; break; } case 0xf4: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x40; break; } case 0xf5: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x40; break; } case 0xf6: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x40; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xf7: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x40; break; } case 0xf8: { sdwCyclesRemaining -= 8; cpu.z80B |= 0x80; break; } case 0xf9: { sdwCyclesRemaining -= 8; cpu.z80C |= 0x80; break; } case 0xfa: { sdwCyclesRemaining -= 8; cpu.z80D |= 0x80; break; } case 0xfb: { sdwCyclesRemaining -= 8; cpu.z80E |= 0x80; break; } case 0xfc: { sdwCyclesRemaining -= 8; cpu.z80H |= 0x80; break; } case 0xfd: { sdwCyclesRemaining -= 8; cpu.z80L |= 0x80; break; } case 0xfe: { sdwCyclesRemaining -= 15; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp |= 0x80; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0xff: { sdwCyclesRemaining -= 8; cpu.z80A |= 0x80; break; } } } void EDHandler(void) { switch (*pbPC++) { case 0x00: { InvalidInstruction(2); break; } case 0x01: { InvalidInstruction(2); break; } case 0x02: { InvalidInstruction(2); break; } case 0x03: { InvalidInstruction(2); break; } case 0x04: { InvalidInstruction(2); break; } case 0x05: { InvalidInstruction(2); break; } case 0x06: { InvalidInstruction(2); break; } case 0x07: { InvalidInstruction(2); break; } case 0x08: { InvalidInstruction(2); break; } case 0x09: { InvalidInstruction(2); break; } case 0x0a: { InvalidInstruction(2); break; } case 0x0b: { InvalidInstruction(2); break; } case 0x0c: { InvalidInstruction(2); break; } case 0x0d: { InvalidInstruction(2); break; } case 0x0e: { InvalidInstruction(2); break; } case 0x0f: { InvalidInstruction(2); break; } case 0x10: { InvalidInstruction(2); break; } case 0x11: { InvalidInstruction(2); break; } case 0x12: { InvalidInstruction(2); break; } case 0x13: { InvalidInstruction(2); break; } case 0x14: { InvalidInstruction(2); break; } case 0x15: { InvalidInstruction(2); break; } case 0x16: { InvalidInstruction(2); break; } case 0x17: { InvalidInstruction(2); break; } case 0x18: { InvalidInstruction(2); break; } case 0x19: { InvalidInstruction(2); break; } case 0x1a: { InvalidInstruction(2); break; } case 0x1b: { InvalidInstruction(2); break; } case 0x1c: { InvalidInstruction(2); break; } case 0x1d: { InvalidInstruction(2); break; } case 0x1e: { InvalidInstruction(2); break; } case 0x1f: { InvalidInstruction(2); break; } case 0x20: { InvalidInstruction(2); break; } case 0x21: { InvalidInstruction(2); break; } case 0x22: { InvalidInstruction(2); break; } case 0x23: { InvalidInstruction(2); break; } case 0x24: { InvalidInstruction(2); break; } case 0x25: { InvalidInstruction(2); break; } case 0x26: { InvalidInstruction(2); break; } case 0x27: { InvalidInstruction(2); break; } case 0x28: { InvalidInstruction(2); break; } case 0x29: { InvalidInstruction(2); break; } case 0x2a: { InvalidInstruction(2); break; } case 0x2b: { InvalidInstruction(2); break; } case 0x2c: { InvalidInstruction(2); break; } case 0x2d: { InvalidInstruction(2); break; } case 0x2e: { InvalidInstruction(2); break; } case 0x2f: { InvalidInstruction(2); break; } case 0x30: { InvalidInstruction(2); break; } case 0x31: { InvalidInstruction(2); break; } case 0x32: { InvalidInstruction(2); break; } case 0x33: { InvalidInstruction(2); break; } case 0x34: { InvalidInstruction(2); break; } case 0x35: { InvalidInstruction(2); break; } case 0x36: { InvalidInstruction(2); break; } case 0x37: { InvalidInstruction(2); break; } case 0x38: { InvalidInstruction(2); break; } case 0x39: { InvalidInstruction(2); break; } case 0x3a: { InvalidInstruction(2); break; } case 0x3b: { InvalidInstruction(2); break; } case 0x3c: { InvalidInstruction(2); break; } case 0x3d: { InvalidInstruction(2); break; } case 0x3e: { InvalidInstruction(2); break; } case 0x3f: { InvalidInstruction(2); break; } case 0x40: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80B = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80B = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80B]; break; } case 0x41: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80B, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x42: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL - cpu.z80BC - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80BC) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80BC ^ cpu.z80HL) & (cpu.z80BC ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x43: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwTemp >= psMemWrite->lowAddr) && (dwTemp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwTemp, (cpu.z80BC & 0xff), psMemWrite); psMemWrite->memoryCall(dwTemp + 1, (cpu.z80BC >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr)) = cpu.z80BC; *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr) + 1) = cpu.z80BC >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwTemp] = (UINT8) cpu.z80BC; cpu.z80Base[dwTemp + 1] = (UINT8) ((UINT32) cpu.z80BC >> 8); } break; } case 0x44: { sdwCyclesRemaining -= 8; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) 0 << 8) | cpu.z80A]; cpu.z80A = 0 - cpu.z80A; break; } case 0x45: { sdwCyclesRemaining -= 14; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ cpu.z80iff &= ~(IFF1); /* Keep IFF2 around */ cpu.z80iff |= ((cpu.z80iff >> 1) & IFF1); /* IFF2->IFF1 */ break; } case 0x46: { sdwCyclesRemaining -= 8; cpu.z80interruptMode = 0; break; } case 0x47: { sdwCyclesRemaining -= 9; cpu.z80i = cpu.z80A; break; } case 0x48: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80C = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80C = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80C]; break; } case 0x49: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80C, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x4a: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL + cpu.z80BC + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80BC) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80BC ^ cpu.z80HL ^ 0x8000) & (cpu.z80BC ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x4b: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwTemp >= psMemRead->lowAddr) && (dwTemp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80BC = psMemRead->memoryCall(dwTemp, psMemRead); cpu.z80BC |= (UINT32) ((UINT32) psMemRead->memoryCall(dwTemp + 1, psMemRead) << 8); } else { cpu.z80BC = *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr)); cpu.z80BC |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80BC = cpu.z80Base[dwTemp]; cpu.z80BC |= (UINT32) ((UINT32) cpu.z80Base[dwTemp + 1] << 8); } break; } case 0x4c: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x4d: { sdwCyclesRemaining -= 14; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ break; } case 0x4e: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x4f: { sdwCyclesRemaining -= 9; cpu.z80r = cpu.z80A; break; } case 0x50: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80D = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80D = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80D]; break; } case 0x51: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80D, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x52: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL - cpu.z80DE - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80DE) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80DE ^ cpu.z80HL) & (cpu.z80DE ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x53: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwTemp >= psMemWrite->lowAddr) && (dwTemp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwTemp, (cpu.z80DE & 0xff), psMemWrite); psMemWrite->memoryCall(dwTemp + 1, (cpu.z80DE >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr)) = cpu.z80DE; *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr) + 1) = cpu.z80DE >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwTemp] = (UINT8) cpu.z80DE; cpu.z80Base[dwTemp + 1] = (UINT8) ((UINT32) cpu.z80DE >> 8); } break; } case 0x54: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x55: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x56: { sdwCyclesRemaining -= 8; cpu.z80interruptMode = 1; cpu.z80intAddr = 0x38; break; } case 0x57: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((cpu.z80iff & IFF2) << 1); cpu.z80A = cpu.z80i; cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x58: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80E = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80E = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80E]; break; } case 0x59: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80E, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x5a: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL + cpu.z80DE + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80DE) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80DE ^ cpu.z80HL ^ 0x8000) & (cpu.z80DE ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x5b: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwTemp >= psMemRead->lowAddr) && (dwTemp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80DE = psMemRead->memoryCall(dwTemp, psMemRead); cpu.z80DE |= (UINT32) ((UINT32) psMemRead->memoryCall(dwTemp + 1, psMemRead) << 8); } else { cpu.z80DE = *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr)); cpu.z80DE |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80DE = cpu.z80Base[dwTemp]; cpu.z80DE |= (UINT32) ((UINT32) cpu.z80Base[dwTemp + 1] << 8); } break; } case 0x5c: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x5d: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x5e: { sdwCyclesRemaining -= 8; cpu.z80interruptMode = 2; break; } case 0x5f: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80r]; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_OVERFLOW_PARITY)) | ((cpu.z80iff & IFF2) << 1); cpu.z80A = cpu.z80r; bTemp = (cpu.z80r + (cpu.z80B + sdwCyclesRemaining + 1 + cpu.z80H)) ^ cpu.z80A; cpu.z80r = (cpu.z80r & 0x80) | (bTemp & 0x7f); break; } case 0x60: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80H = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80H = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80H]; break; } case 0x61: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80H, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x62: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL - cpu.z80HL - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80HL) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80HL ^ cpu.z80HL) & (cpu.z80HL ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x63: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwTemp >= psMemWrite->lowAddr) && (dwTemp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwTemp, (cpu.z80HL & 0xff), psMemWrite); psMemWrite->memoryCall(dwTemp + 1, (cpu.z80HL >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr)) = cpu.z80HL; *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr) + 1) = cpu.z80HL >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwTemp] = (UINT8) cpu.z80HL; cpu.z80Base[dwTemp + 1] = (UINT8) ((UINT32) cpu.z80HL >> 8); } break; } case 0x64: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x65: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x66: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x67: { sdwCyclesRemaining -= 18; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = (cpu.z80A & 0x0f) << 4; cpu.z80A = (cpu.z80A & 0xf0) | (bTemp & 0x0f); bTemp = (bTemp >> 4) | bTemp2; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x68: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80L = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80L = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80L]; break; } case 0x69: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80L, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x6a: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL + cpu.z80HL + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80HL) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80HL ^ cpu.z80HL ^ 0x8000) & (cpu.z80HL ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x6b: { sdwCyclesRemaining -= 20; InvalidInstruction(2); break; } case 0x6c: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x6d: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x6e: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x6f: { sdwCyclesRemaining -= 18; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = (cpu.z80A & 0x0f); cpu.z80A = (cpu.z80A & 0xf0) | (bTemp >> 4); bTemp = (bTemp << 4) | bTemp2; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x70: { sdwCyclesRemaining -= 12; InvalidInstruction(2); break; } case 0x71: { sdwCyclesRemaining -= 12; InvalidInstruction(2); break; } case 0x72: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL - cpu.z80sp - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80sp) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80sp ^ cpu.z80HL) & (cpu.z80sp ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x73: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwTemp >= psMemWrite->lowAddr) && (dwTemp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwTemp, (cpu.z80sp & 0xff), psMemWrite); psMemWrite->memoryCall(dwTemp + 1, (cpu.z80sp >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr)) = cpu.z80sp; *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr) + 1) = cpu.z80sp >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwTemp] = (UINT8) cpu.z80sp; cpu.z80Base[dwTemp + 1] = (UINT8) ((UINT32) cpu.z80sp >> 8); } break; } case 0x74: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x75: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x76: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x77: { InvalidInstruction(2); break; } case 0x78: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwAddr >= psIoRead->lowIoAddr) && (dwAddr <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80A = psIoRead->IOCall(dwAddr, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80A = 0xff; /* Unclaimed I/O read */ } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0x79: { sdwCyclesRemaining -= 12; dwAddr = cpu.z80C; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwAddr >= psIoWrite->lowIoAddr) && (dwAddr <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwAddr, cpu.z80A, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0x7a: { sdwCyclesRemaining -= 15; dwTemp = cpu.z80HL + cpu.z80sp + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN); if (0 == (dwTemp & 0xffff)) { cpu.z80F |= Z80_FLAG_ZERO; } cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ cpu.z80sp) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80F |= ((((cpu.z80sp ^ cpu.z80HL ^ 0x8000) & (cpu.z80sp ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x7b: { sdwCyclesRemaining -= 20; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwTemp >= psMemRead->lowAddr) && (dwTemp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80sp = psMemRead->memoryCall(dwTemp, psMemRead); cpu.z80sp |= (UINT32) ((UINT32) psMemRead->memoryCall(dwTemp + 1, psMemRead) << 8); } else { cpu.z80sp = *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr)); cpu.z80sp |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80sp = cpu.z80Base[dwTemp]; cpu.z80sp |= (UINT32) ((UINT32) cpu.z80Base[dwTemp + 1] << 8); } break; } case 0x7c: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x7d: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x7e: { sdwCyclesRemaining -= 8; InvalidInstruction(2); break; } case 0x7f: { InvalidInstruction(2); break; } case 0x80: { InvalidInstruction(2); break; } case 0x81: { InvalidInstruction(2); break; } case 0x82: { InvalidInstruction(2); break; } case 0x83: { InvalidInstruction(2); break; } case 0x84: { InvalidInstruction(2); break; } case 0x85: { InvalidInstruction(2); break; } case 0x86: { InvalidInstruction(2); break; } case 0x87: { InvalidInstruction(2); break; } case 0x88: { InvalidInstruction(2); break; } case 0x89: { InvalidInstruction(2); break; } case 0x8a: { InvalidInstruction(2); break; } case 0x8b: { InvalidInstruction(2); break; } case 0x8c: { InvalidInstruction(2); break; } case 0x8d: { InvalidInstruction(2); break; } case 0x8e: { InvalidInstruction(2); break; } case 0x8f: { InvalidInstruction(2); break; } case 0x90: { InvalidInstruction(2); break; } case 0x91: { InvalidInstruction(2); break; } case 0x92: { InvalidInstruction(2); break; } case 0x93: { InvalidInstruction(2); break; } case 0x94: { InvalidInstruction(2); break; } case 0x95: { InvalidInstruction(2); break; } case 0x96: { InvalidInstruction(2); break; } case 0x97: { InvalidInstruction(2); break; } case 0x98: { InvalidInstruction(2); break; } case 0x99: { InvalidInstruction(2); break; } case 0x9a: { InvalidInstruction(2); break; } case 0x9b: { InvalidInstruction(2); break; } case 0x9c: { InvalidInstruction(2); break; } case 0x9d: { InvalidInstruction(2); break; } case 0x9e: { InvalidInstruction(2); break; } case 0x9f: { InvalidInstruction(2); break; } case 0xa0: { sdwCyclesRemaining -= 16; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80DE >= psMemWrite->lowAddr) && (cpu.z80DE <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80DE, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80DE - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80DE] = (UINT8) bTemp; } ++cpu.z80HL; ++cpu.z80DE; --cpu.z80BC; cpu.z80HL &= 0xffff; cpu.z80DE &= 0xffff; cpu.z80BC &= 0xffff; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY); if (cpu.z80BC) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xa1: { sdwCyclesRemaining -= 16; { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80HL++; cpu.z80HL &= 0xffff; cpu.z80BC--; cpu.z80BC &= 0xffff; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO)); if (cpu.z80BC) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xa2: { sdwCyclesRemaining -= 16; { psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((cpu.z80B >= psIoRead->lowIoAddr) && (cpu.z80B <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; bTemp = psIoRead->IOCall(cpu.z80B, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { bTemp = 0xff; /* Unclaimed I/O read */ } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } cpu.z80HL++; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; pbPC -= 2; } break; } case 0xa3: { sdwCyclesRemaining -= 16; { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((cpu.z80BC >= psIoWrite->lowIoAddr) && (cpu.z80BC <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(cpu.z80BC, bTemp, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } cpu.z80HL++; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xa4: { InvalidInstruction(2); break; } case 0xa5: { InvalidInstruction(2); break; } case 0xa6: { InvalidInstruction(2); break; } case 0xa7: { InvalidInstruction(2); break; } case 0xa8: { sdwCyclesRemaining -= 16; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80DE >= psMemWrite->lowAddr) && (cpu.z80DE <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80DE, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80DE - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80DE] = (UINT8) bTemp; } --cpu.z80HL; --cpu.z80DE; --cpu.z80BC; cpu.z80HL &= 0xffff; cpu.z80DE &= 0xffff; cpu.z80BC &= 0xffff; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY); if (cpu.z80BC) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xa9: { sdwCyclesRemaining -= 16; { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80HL--; cpu.z80HL &= 0xffff; cpu.z80BC--; cpu.z80BC &= 0xffff; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO)); if (cpu.z80BC) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xaa: { sdwCyclesRemaining -= 16; { psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((cpu.z80B >= psIoRead->lowIoAddr) && (cpu.z80B <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; bTemp = psIoRead->IOCall(cpu.z80B, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { bTemp = 0xff; /* Unclaimed I/O read */ } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } cpu.z80HL--; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; pbPC -= 2; } break; } case 0xab: { sdwCyclesRemaining -= 16; { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((cpu.z80BC >= psIoWrite->lowIoAddr) && (cpu.z80BC <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(cpu.z80BC, bTemp, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } cpu.z80HL--; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xac: { InvalidInstruction(2); break; } case 0xad: { InvalidInstruction(2); break; } case 0xae: { InvalidInstruction(2); break; } case 0xaf: { InvalidInstruction(2); break; } case 0xb0: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining > 0) && (cpu.z80BC)) { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80DE >= psMemWrite->lowAddr) && (cpu.z80DE <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80DE, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80DE - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80DE] = (UINT8) bTemp; } ++cpu.z80HL; ++cpu.z80DE; --cpu.z80BC; cpu.z80HL &= 0xffff; cpu.z80DE &= 0xffff; cpu.z80BC &= 0xffff; sdwCyclesRemaining -= 21; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY); if (cpu.z80BC) { pbPC -= 2; /* Back up so we hit this instruction again */ cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } sdwCyclesRemaining -= 16; break; } case 0xb1: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining >= 0) && (cpu.z80BC)) { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80HL++; cpu.z80HL &= 0xffff; cpu.z80BC--; cpu.z80BC &= 0xffff; sdwCyclesRemaining -= 16; if (cpu.z80A == bTemp) { break; } } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO)); if (cpu.z80BC) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xb2: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining > 0) && (cpu.z80B)) { psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((cpu.z80B >= psIoRead->lowIoAddr) && (cpu.z80B <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; bTemp = psIoRead->IOCall(cpu.z80B, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { bTemp = 0xff; /* Unclaimed I/O read */ } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } cpu.z80HL++; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; pbPC -= 2; } break; } case 0xb3: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining > 0) && (cpu.z80B)) { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((cpu.z80BC >= psIoWrite->lowIoAddr) && (cpu.z80BC <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(cpu.z80BC, bTemp, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } cpu.z80HL++; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xb4: { InvalidInstruction(2); break; } case 0xb5: { InvalidInstruction(2); break; } case 0xb6: { InvalidInstruction(2); break; } case 0xb7: { InvalidInstruction(2); break; } case 0xb8: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining > 0) && (cpu.z80BC)) { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80DE >= psMemWrite->lowAddr) && (cpu.z80DE <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80DE, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80DE - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80DE] = (UINT8) bTemp; } --cpu.z80HL; --cpu.z80DE; --cpu.z80BC; cpu.z80HL &= 0xffff; cpu.z80DE &= 0xffff; cpu.z80BC &= 0xffff; sdwCyclesRemaining -= 21; } cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY); if (cpu.z80BC) { pbPC -= 2; /* Back up so we hit this instruction again */ cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } sdwCyclesRemaining -= 16; break; } case 0xb9: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining >= 0) && (cpu.z80BC)) { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80HL--; cpu.z80HL &= 0xffff; cpu.z80BC--; cpu.z80BC &= 0xffff; sdwCyclesRemaining -= 16; if (cpu.z80A == bTemp) { break; } } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO)); if (cpu.z80BC) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xba: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining > 0) && (cpu.z80B)) { psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((cpu.z80B >= psIoRead->lowIoAddr) && (cpu.z80B <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; bTemp = psIoRead->IOCall(cpu.z80B, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { bTemp = 0xff; /* Unclaimed I/O read */ } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } cpu.z80HL--; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; pbPC -= 2; } break; } case 0xbb: { sdwCyclesRemaining -= 16; while ((sdwCyclesRemaining > 0) && (cpu.z80B)) { psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((cpu.z80BC >= psIoWrite->lowIoAddr) && (cpu.z80BC <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(cpu.z80BC, bTemp, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } cpu.z80HL--; cpu.z80HL &= 0xffff; sdwCyclesRemaining -= 16; cpu.z80B--; } cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY)); if (cpu.z80B) { cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY; } break; } case 0xbc: { InvalidInstruction(2); break; } case 0xbd: { InvalidInstruction(2); break; } case 0xbe: { InvalidInstruction(2); break; } case 0xbf: { InvalidInstruction(2); break; } case 0xc0: { InvalidInstruction(2); break; } case 0xc1: { InvalidInstruction(2); break; } case 0xc2: { InvalidInstruction(2); break; } case 0xc3: { InvalidInstruction(2); break; } case 0xc4: { InvalidInstruction(2); break; } case 0xc5: { InvalidInstruction(2); break; } case 0xc6: { InvalidInstruction(2); break; } case 0xc7: { InvalidInstruction(2); break; } case 0xc8: { InvalidInstruction(2); break; } case 0xc9: { InvalidInstruction(2); break; } case 0xca: { InvalidInstruction(2); break; } case 0xcb: { InvalidInstruction(2); break; } case 0xcc: { InvalidInstruction(2); break; } case 0xcd: { InvalidInstruction(2); break; } case 0xce: { InvalidInstruction(2); break; } case 0xcf: { InvalidInstruction(2); break; } case 0xd0: { InvalidInstruction(2); break; } case 0xd1: { InvalidInstruction(2); break; } case 0xd2: { InvalidInstruction(2); break; } case 0xd3: { InvalidInstruction(2); break; } case 0xd4: { InvalidInstruction(2); break; } case 0xd5: { InvalidInstruction(2); break; } case 0xd6: { InvalidInstruction(2); break; } case 0xd7: { InvalidInstruction(2); break; } case 0xd8: { InvalidInstruction(2); break; } case 0xd9: { InvalidInstruction(2); break; } case 0xda: { InvalidInstruction(2); break; } case 0xdb: { InvalidInstruction(2); break; } case 0xdc: { InvalidInstruction(2); break; } case 0xdd: { InvalidInstruction(2); break; } case 0xde: { InvalidInstruction(2); break; } case 0xdf: { InvalidInstruction(2); break; } case 0xe0: { InvalidInstruction(2); break; } case 0xe1: { InvalidInstruction(2); break; } case 0xe2: { InvalidInstruction(2); break; } case 0xe3: { InvalidInstruction(2); break; } case 0xe4: { InvalidInstruction(2); break; } case 0xe5: { InvalidInstruction(2); break; } case 0xe6: { InvalidInstruction(2); break; } case 0xe7: { InvalidInstruction(2); break; } case 0xe8: { InvalidInstruction(2); break; } case 0xe9: { InvalidInstruction(2); break; } case 0xea: { InvalidInstruction(2); break; } case 0xeb: { InvalidInstruction(2); break; } case 0xec: { InvalidInstruction(2); break; } case 0xed: { InvalidInstruction(2); break; } case 0xee: { InvalidInstruction(2); break; } case 0xef: { InvalidInstruction(2); break; } case 0xf0: { InvalidInstruction(2); break; } case 0xf1: { InvalidInstruction(2); break; } case 0xf2: { InvalidInstruction(2); break; } case 0xf3: { InvalidInstruction(2); break; } case 0xf4: { InvalidInstruction(2); break; } case 0xf5: { InvalidInstruction(2); break; } case 0xf6: { InvalidInstruction(2); break; } case 0xf7: { InvalidInstruction(2); break; } case 0xf8: { InvalidInstruction(2); break; } case 0xf9: { InvalidInstruction(2); break; } case 0xfa: { InvalidInstruction(2); break; } case 0xfb: { InvalidInstruction(2); break; } case 0xfc: { InvalidInstruction(2); break; } case 0xfd: { InvalidInstruction(2); break; } case 0xfe: { InvalidInstruction(2); break; } case 0xff: { InvalidInstruction(2); break; } } } void DDHandler(void) { switch (*pbPC++) { case 0x00: { InvalidInstruction(2); break; } case 0x01: { InvalidInstruction(2); break; } case 0x02: { InvalidInstruction(2); break; } case 0x03: { InvalidInstruction(2); break; } case 0x04: { InvalidInstruction(2); break; } case 0x05: { InvalidInstruction(2); break; } case 0x06: { InvalidInstruction(2); break; } case 0x07: { InvalidInstruction(2); break; } case 0x08: { InvalidInstruction(2); break; } case 0x09: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IX + cpu.z80BC; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IX ^ dwTemp ^ cpu.z80BC) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IX = dwTemp & 0xffff; break; } case 0x0a: { InvalidInstruction(2); break; } case 0x0b: { InvalidInstruction(2); break; } case 0x0c: { InvalidInstruction(2); break; } case 0x0d: { InvalidInstruction(2); break; } case 0x0e: { InvalidInstruction(2); break; } case 0x0f: { InvalidInstruction(2); break; } case 0x10: { InvalidInstruction(2); break; } case 0x11: { InvalidInstruction(2); break; } case 0x12: { InvalidInstruction(2); break; } case 0x13: { InvalidInstruction(2); break; } case 0x14: { InvalidInstruction(2); break; } case 0x15: { InvalidInstruction(2); break; } case 0x16: { InvalidInstruction(2); break; } case 0x17: { InvalidInstruction(2); break; } case 0x18: { InvalidInstruction(2); break; } case 0x19: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IX + cpu.z80DE; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IX ^ dwTemp ^ cpu.z80DE) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IX = dwTemp & 0xffff; break; } case 0x1a: { InvalidInstruction(2); break; } case 0x1b: { InvalidInstruction(2); break; } case 0x1c: { InvalidInstruction(2); break; } case 0x1d: { InvalidInstruction(2); break; } case 0x1e: { InvalidInstruction(2); break; } case 0x1f: { InvalidInstruction(2); break; } case 0x20: { InvalidInstruction(2); break; } case 0x21: { sdwCyclesRemaining -= 14; cpu.z80IX = *pbPC++; cpu.z80IX |= ((UINT32) *pbPC++ << 8); break; } case 0x22: { sdwCyclesRemaining -= 20; dwAddr = *pbPC++; dwAddr |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, (cpu.z80IX & 0xff), psMemWrite); psMemWrite->memoryCall(dwAddr + 1, (cpu.z80IX >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = cpu.z80IX; *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr) + 1) = cpu.z80IX >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) cpu.z80IX; cpu.z80Base[dwAddr + 1] = (UINT8) ((UINT32) cpu.z80IX >> 8); } break; } case 0x23: { sdwCyclesRemaining -= 10; cpu.z80IX++; cpu.z80IX &= 0xffff; break; } case 0x24: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80XH++]; break; } case 0x25: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[cpu.z80XH--]; break; } case 0x26: { sdwCyclesRemaining -= 9; cpu.z80XH = *pbPC++; break; } case 0x27: { InvalidInstruction(2); break; } case 0x28: { InvalidInstruction(2); break; } case 0x29: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IX + cpu.z80IX; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IX ^ dwTemp ^ cpu.z80HL) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IX = dwTemp & 0xffff; break; } case 0x2a: { sdwCyclesRemaining -= 20; dwAddr = *pbPC++; dwAddr |= ((UINT32) *pbPC++ << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80IX = psMemRead->memoryCall(dwAddr, psMemRead); cpu.z80IX |= (UINT32) ((UINT32) psMemRead->memoryCall(dwAddr + 1, psMemRead) << 8); } else { cpu.z80IX = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); cpu.z80IX |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80IX = cpu.z80Base[dwAddr]; cpu.z80IX |= (UINT32) ((UINT32) cpu.z80Base[dwAddr + 1] << 8); } break; } case 0x2b: { sdwCyclesRemaining -= 10; cpu.z80IX--; cpu.z80IX &= 0xffff; break; } case 0x2c: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80XL++]; break; } case 0x2d: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[cpu.z80XL--]; break; } case 0x2e: { sdwCyclesRemaining -= 9; cpu.z80XL = *pbPC++; break; } case 0x2f: { InvalidInstruction(2); break; } case 0x30: { InvalidInstruction(2); break; } case 0x31: { InvalidInstruction(2); break; } case 0x32: { InvalidInstruction(2); break; } case 0x33: { InvalidInstruction(2); break; } case 0x34: { sdwCyclesRemaining -= 23; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[bTemp++]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x35: { sdwCyclesRemaining -= 23; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[bTemp--]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x36: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, *pbPC++, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = *pbPC++; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) *pbPC++; } break; } case 0x37: { InvalidInstruction(2); break; } case 0x38: { InvalidInstruction(2); break; } case 0x39: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IX + cpu.z80sp; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IX ^ dwTemp ^ cpu.z80sp) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IX = dwTemp & 0xffff; break; } case 0x3a: { InvalidInstruction(2); break; } case 0x3b: { InvalidInstruction(2); break; } case 0x3c: { InvalidInstruction(2); break; } case 0x3d: { InvalidInstruction(2); break; } case 0x3e: { InvalidInstruction(2); break; } case 0x3f: { InvalidInstruction(2); break; } case 0x40: { InvalidInstruction(2); break; } case 0x41: { InvalidInstruction(2); break; } case 0x42: { InvalidInstruction(2); break; } case 0x43: { InvalidInstruction(2); break; } case 0x44: { sdwCyclesRemaining -= 9; cpu.z80B = cpu.z80XH; break; } case 0x45: { sdwCyclesRemaining -= 9; cpu.z80B = cpu.z80XL; break; } case 0x46: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80B = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80B = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80B = cpu.z80Base[sdwAddr]; } break; } case 0x47: { InvalidInstruction(2); break; } case 0x48: { InvalidInstruction(2); break; } case 0x49: { InvalidInstruction(2); break; } case 0x4a: { InvalidInstruction(2); break; } case 0x4b: { InvalidInstruction(2); break; } case 0x4c: { sdwCyclesRemaining -= 9; cpu.z80C = cpu.z80XH; break; } case 0x4d: { sdwCyclesRemaining -= 9; cpu.z80C = cpu.z80XL; break; } case 0x4e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80C = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80C = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80C = cpu.z80Base[sdwAddr]; } break; } case 0x4f: { InvalidInstruction(2); break; } case 0x50: { InvalidInstruction(2); break; } case 0x51: { InvalidInstruction(2); break; } case 0x52: { InvalidInstruction(2); break; } case 0x53: { InvalidInstruction(2); break; } case 0x54: { sdwCyclesRemaining -= 9; cpu.z80D = cpu.z80XH; break; } case 0x55: { sdwCyclesRemaining -= 9; cpu.z80D = cpu.z80XL; break; } case 0x56: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80D = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80D = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80D = cpu.z80Base[sdwAddr]; } break; } case 0x57: { InvalidInstruction(2); break; } case 0x58: { InvalidInstruction(2); break; } case 0x59: { InvalidInstruction(2); break; } case 0x5a: { InvalidInstruction(2); break; } case 0x5b: { InvalidInstruction(2); break; } case 0x5c: { sdwCyclesRemaining -= 9; cpu.z80E = cpu.z80XH; break; } case 0x5d: { sdwCyclesRemaining -= 9; cpu.z80E = cpu.z80XL; break; } case 0x5e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80E = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80E = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80E = cpu.z80Base[sdwAddr]; } break; } case 0x5f: { InvalidInstruction(2); break; } case 0x60: { sdwCyclesRemaining -= 9; cpu.z80XH = cpu.z80B; break; } case 0x61: { sdwCyclesRemaining -= 9; cpu.z80XH = cpu.z80C; break; } case 0x62: { sdwCyclesRemaining -= 9; cpu.z80XH = cpu.z80D; break; } case 0x63: { sdwCyclesRemaining -= 9; cpu.z80XH = cpu.z80E; break; } case 0x64: { sdwCyclesRemaining -= 9; break; } case 0x65: { sdwCyclesRemaining -= 9; cpu.z80XH = cpu.z80XL; break; } case 0x66: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80H = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80H = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80H = cpu.z80Base[sdwAddr]; } break; } case 0x67: { sdwCyclesRemaining -= 9; cpu.z80XH = cpu.z80A; break; } case 0x68: { sdwCyclesRemaining -= 9; cpu.z80XL = cpu.z80B; break; } case 0x69: { sdwCyclesRemaining -= 9; cpu.z80XL = cpu.z80C; break; } case 0x6a: { sdwCyclesRemaining -= 9; cpu.z80XL = cpu.z80D; break; } case 0x6b: { sdwCyclesRemaining -= 9; cpu.z80XL = cpu.z80E; break; } case 0x6c: { sdwCyclesRemaining -= 9; cpu.z80XL = cpu.z80XH; break; } case 0x6d: { sdwCyclesRemaining -= 9; break; } case 0x6e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80L = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80L = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80L = cpu.z80Base[sdwAddr]; } break; } case 0x6f: { sdwCyclesRemaining -= 9; cpu.z80XL = cpu.z80A; break; } case 0x70: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80B, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80B; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80B; } break; } case 0x71: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80C, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80C; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80C; } break; } case 0x72: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80D, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80D; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80D; } break; } case 0x73: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80E, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80E; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80E; } break; } case 0x74: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80H, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80H; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80H; } break; } case 0x75: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80L, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80L; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80L; } break; } case 0x76: { sdwCyclesRemaining -= 19; InvalidInstruction(2); break; } case 0x77: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80A, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80A; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80A; } break; } case 0x78: { InvalidInstruction(2); break; } case 0x79: { InvalidInstruction(2); break; } case 0x7a: { InvalidInstruction(2); break; } case 0x7b: { InvalidInstruction(2); break; } case 0x7c: { sdwCyclesRemaining -= 9; cpu.z80A = cpu.z80XH; break; } case 0x7d: { sdwCyclesRemaining -= 9; cpu.z80A = cpu.z80XL; break; } case 0x7e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IX + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80A = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80A = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80A = cpu.z80Base[sdwAddr]; } break; } case 0x7f: { InvalidInstruction(2); break; } case 0x80: { InvalidInstruction(2); break; } case 0x81: { InvalidInstruction(2); break; } case 0x82: { InvalidInstruction(2); break; } case 0x83: { InvalidInstruction(2); break; } case 0x84: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80XH; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80XH]; InvalidInstruction(2); break; } case 0x85: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80XL; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80XL]; InvalidInstruction(2); break; } case 0x86: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A += bTemp; break; } case 0x87: { InvalidInstruction(2); break; } case 0x88: { InvalidInstruction(2); break; } case 0x89: { InvalidInstruction(2); break; } case 0x8a: { InvalidInstruction(2); break; } case 0x8b: { InvalidInstruction(2); break; } case 0x8c: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80XH + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80XH | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x8d: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80XL + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80XL | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x8e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } bTemp2 = (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A += bTemp + bTemp2; break; } case 0x8f: { InvalidInstruction(2); break; } case 0x90: { InvalidInstruction(2); break; } case 0x91: { InvalidInstruction(2); break; } case 0x92: { InvalidInstruction(2); break; } case 0x93: { InvalidInstruction(2); break; } case 0x94: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80XH; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80XH]; InvalidInstruction(2); break; } case 0x95: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80XL; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80XL]; InvalidInstruction(2); break; } case 0x96: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A -= bTemp; break; } case 0x97: { InvalidInstruction(2); break; } case 0x98: { InvalidInstruction(2); break; } case 0x99: { InvalidInstruction(2); break; } case 0x9a: { InvalidInstruction(2); break; } case 0x9b: { InvalidInstruction(2); break; } case 0x9c: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80XH - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80XH | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x9d: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80XL - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80XL | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x9e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } bTemp2 = cpu.z80A; cpu.z80A = cpu.z80A - bTemp - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) bTemp2 << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; break; } case 0x9f: { InvalidInstruction(2); break; } case 0xa0: { InvalidInstruction(2); break; } case 0xa1: { InvalidInstruction(2); break; } case 0xa2: { InvalidInstruction(2); break; } case 0xa3: { InvalidInstruction(2); break; } case 0xa4: { sdwCyclesRemaining -= 9; cpu.z80A &= cpu.z80XH; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xa5: { sdwCyclesRemaining -= 9; cpu.z80A &= cpu.z80XL; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xa6: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80A &= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa7: { InvalidInstruction(2); break; } case 0xa8: { InvalidInstruction(2); break; } case 0xa9: { InvalidInstruction(2); break; } case 0xaa: { InvalidInstruction(2); break; } case 0xab: { InvalidInstruction(2); break; } case 0xac: { sdwCyclesRemaining -= 9; cpu.z80A ^= cpu.z80XH; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xad: { sdwCyclesRemaining -= 9; cpu.z80A ^= cpu.z80XL; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xae: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80A ^= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xaf: { InvalidInstruction(2); break; } case 0xb0: { InvalidInstruction(2); break; } case 0xb1: { InvalidInstruction(2); break; } case 0xb2: { InvalidInstruction(2); break; } case 0xb3: { InvalidInstruction(2); break; } case 0xb4: { sdwCyclesRemaining -= 9; cpu.z80A |= cpu.z80XH; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xb5: { sdwCyclesRemaining -= 9; cpu.z80A |= cpu.z80XL; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xb6: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80A |= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb7: { InvalidInstruction(2); break; } case 0xb8: { InvalidInstruction(2); break; } case 0xb9: { InvalidInstruction(2); break; } case 0xba: { InvalidInstruction(2); break; } case 0xbb: { InvalidInstruction(2); break; } case 0xbc: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xbd: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xbe: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IX) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; break; } case 0xbf: { InvalidInstruction(2); break; } case 0xc0: { InvalidInstruction(2); break; } case 0xc1: { InvalidInstruction(2); break; } case 0xc2: { InvalidInstruction(2); break; } case 0xc3: { InvalidInstruction(2); break; } case 0xc4: { InvalidInstruction(2); break; } case 0xc5: { InvalidInstruction(2); break; } case 0xc6: { InvalidInstruction(2); break; } case 0xc7: { InvalidInstruction(2); break; } case 0xc8: { InvalidInstruction(2); break; } case 0xc9: { InvalidInstruction(2); break; } case 0xca: { InvalidInstruction(2); break; } case 0xcb: { DDFDCBHandler(0); break; } case 0xcc: { InvalidInstruction(2); break; } case 0xcd: { InvalidInstruction(2); break; } case 0xce: { InvalidInstruction(2); break; } case 0xcf: { InvalidInstruction(2); break; } case 0xd0: { InvalidInstruction(2); break; } case 0xd1: { InvalidInstruction(2); break; } case 0xd2: { InvalidInstruction(2); break; } case 0xd3: { InvalidInstruction(2); break; } case 0xd4: { InvalidInstruction(2); break; } case 0xd5: { InvalidInstruction(2); break; } case 0xd6: { InvalidInstruction(2); break; } case 0xd7: { InvalidInstruction(2); break; } case 0xd8: { InvalidInstruction(2); break; } case 0xd9: { InvalidInstruction(2); break; } case 0xda: { InvalidInstruction(2); break; } case 0xdb: { InvalidInstruction(2); break; } case 0xdc: { InvalidInstruction(2); break; } case 0xdd: { InvalidInstruction(2); break; } case 0xde: { InvalidInstruction(2); break; } case 0xdf: { InvalidInstruction(2); break; } case 0xe0: { InvalidInstruction(2); break; } case 0xe1: { sdwCyclesRemaining -= 14; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80IX = psMemRead->memoryCall(cpu.z80sp, psMemRead); cpu.z80IX |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { cpu.z80IX = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); cpu.z80IX |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80IX = cpu.z80Base[cpu.z80sp]; cpu.z80IX |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } cpu.z80sp += 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ break; } case 0xe2: { InvalidInstruction(2); break; } case 0xe3: { sdwCyclesRemaining -= 23; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { dwAddr = psMemRead->memoryCall(cpu.z80sp, psMemRead); dwAddr |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { dwAddr = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); dwAddr |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { dwAddr = cpu.z80Base[cpu.z80sp]; dwAddr |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80IX & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80IX >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80IX; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80IX >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80IX; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80IX >> 8); } cpu.z80IX = dwAddr; break; } case 0xe4: { InvalidInstruction(2); break; } case 0xe5: { sdwCyclesRemaining -= 15; cpu.z80sp -= 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80IX & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80IX >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80IX; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80IX >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80IX; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80IX >> 8); } break; } case 0xe6: { InvalidInstruction(2); break; } case 0xe7: { InvalidInstruction(2); break; } case 0xe8: { InvalidInstruction(2); break; } case 0xe9: { sdwCyclesRemaining -= 8; pbPC = cpu.z80Base + cpu.z80IX; break; } case 0xea: { InvalidInstruction(2); break; } case 0xeb: { InvalidInstruction(2); break; } case 0xec: { InvalidInstruction(2); break; } case 0xed: { InvalidInstruction(2); break; } case 0xee: { InvalidInstruction(2); break; } case 0xef: { InvalidInstruction(2); break; } case 0xf0: { InvalidInstruction(2); break; } case 0xf1: { InvalidInstruction(2); break; } case 0xf2: { InvalidInstruction(2); break; } case 0xf3: { InvalidInstruction(2); break; } case 0xf4: { InvalidInstruction(2); break; } case 0xf5: { InvalidInstruction(2); break; } case 0xf6: { InvalidInstruction(2); break; } case 0xf7: { InvalidInstruction(2); break; } case 0xf8: { InvalidInstruction(2); break; } case 0xf9: { sdwCyclesRemaining -= 10; cpu.z80sp = cpu.z80IX; break; } case 0xfa: { InvalidInstruction(2); break; } case 0xfb: { InvalidInstruction(2); break; } case 0xfc: { InvalidInstruction(2); break; } case 0xfd: { InvalidInstruction(2); break; } case 0xfe: { InvalidInstruction(2); break; } case 0xff: { InvalidInstruction(2); break; } } } void DDFDCBHandler(UINT32 dwWhich) { if (dwWhich) { dwAddr = (UINT32) ((INT32) cpu.z80IY + ((INT32) *pbPC++)) & 0xffff; } else { dwAddr = (UINT32) ((INT32) cpu.z80IX + ((INT32) *pbPC++)) & 0xffff; } psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } switch (*pbPC++) { case 0x00: { InvalidInstruction(4); break; } case 0x01: { InvalidInstruction(4); break; } case 0x02: { InvalidInstruction(4); break; } case 0x03: { InvalidInstruction(4); break; } case 0x04: { InvalidInstruction(4); break; } case 0x05: { InvalidInstruction(4); break; } case 0x06: { sdwCyclesRemaining -= 23; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); bTemp2 = (bTemp >> 7); bTemp = (bTemp << 1) | bTemp2; cpu.z80F |= bTemp2 | bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x07: { InvalidInstruction(4); break; } case 0x08: { InvalidInstruction(4); break; } case 0x09: { InvalidInstruction(4); break; } case 0x0a: { InvalidInstruction(4); break; } case 0x0b: { InvalidInstruction(4); break; } case 0x0c: { InvalidInstruction(4); break; } case 0x0d: { InvalidInstruction(4); break; } case 0x0e: { sdwCyclesRemaining -= 23; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1) | (bTemp << 7); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x0f: { InvalidInstruction(4); break; } case 0x10: { InvalidInstruction(4); break; } case 0x11: { InvalidInstruction(4); break; } case 0x12: { InvalidInstruction(4); break; } case 0x13: { InvalidInstruction(4); break; } case 0x14: { InvalidInstruction(4); break; } case 0x15: { InvalidInstruction(4); break; } case 0x16: { sdwCyclesRemaining -= 23; bTemp2 = cpu.z80F & Z80_FLAG_CARRY; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp >> 7); bTemp = (bTemp << 1) | bTemp2; cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x17: { InvalidInstruction(4); break; } case 0x18: { InvalidInstruction(4); break; } case 0x19: { InvalidInstruction(4); break; } case 0x1a: { InvalidInstruction(4); break; } case 0x1b: { InvalidInstruction(4); break; } case 0x1c: { InvalidInstruction(4); break; } case 0x1d: { InvalidInstruction(4); break; } case 0x1e: { sdwCyclesRemaining -= 23; bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1) | bTemp2; cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x1f: { InvalidInstruction(4); break; } case 0x20: { InvalidInstruction(4); break; } case 0x21: { InvalidInstruction(4); break; } case 0x22: { InvalidInstruction(4); break; } case 0x23: { InvalidInstruction(4); break; } case 0x24: { InvalidInstruction(4); break; } case 0x25: { InvalidInstruction(4); break; } case 0x26: { sdwCyclesRemaining -= 23; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp >> 7); bTemp = (bTemp << 1); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x27: { InvalidInstruction(4); break; } case 0x28: { InvalidInstruction(4); break; } case 0x29: { InvalidInstruction(4); break; } case 0x2a: { InvalidInstruction(4); break; } case 0x2b: { InvalidInstruction(4); break; } case 0x2c: { InvalidInstruction(4); break; } case 0x2d: { InvalidInstruction(4); break; } case 0x2e: { sdwCyclesRemaining -= 23; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1) | (bTemp & 0x80); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x2f: { InvalidInstruction(4); break; } case 0x30: { InvalidInstruction(4); break; } case 0x31: { InvalidInstruction(4); break; } case 0x32: { InvalidInstruction(4); break; } case 0x33: { InvalidInstruction(4); break; } case 0x34: { InvalidInstruction(4); break; } case 0x35: { InvalidInstruction(4); break; } case 0x36: { sdwCyclesRemaining -= 23; InvalidInstruction(4); break; } case 0x37: { InvalidInstruction(4); break; } case 0x38: { InvalidInstruction(4); break; } case 0x39: { InvalidInstruction(4); break; } case 0x3a: { InvalidInstruction(4); break; } case 0x3b: { InvalidInstruction(4); break; } case 0x3c: { InvalidInstruction(4); break; } case 0x3d: { InvalidInstruction(4); break; } case 0x3e: { sdwCyclesRemaining -= 23; cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY); cpu.z80F |= (bTemp & Z80_FLAG_CARRY); bTemp = (bTemp >> 1); cpu.z80F |= bPostORFlags[bTemp]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x3f: { InvalidInstruction(4); break; } case 0x40: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x41: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x42: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x43: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x44: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x45: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x46: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x01)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x47: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x48: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x49: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x4a: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x4b: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x4c: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x4d: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x4e: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x02)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x4f: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x50: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x51: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x52: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x53: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x54: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x55: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x56: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x04)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x57: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x58: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x59: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x5a: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x5b: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x5c: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x5d: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x5e: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x08)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x5f: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x60: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x61: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x62: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x63: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x64: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x65: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x66: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x10)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x67: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x68: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x69: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x6a: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x6b: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x6c: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x6d: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x6e: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x20)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x6f: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x70: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x71: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x72: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x73: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x74: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x75: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x76: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x40)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x77: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x78: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x79: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x7a: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x7b: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x7c: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x7d: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x7e: { sdwCyclesRemaining -= 20; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY; if (!(bTemp & 0x80)) { cpu.z80F |= Z80_FLAG_ZERO; } break; } case 0x7f: { sdwCyclesRemaining -= 20; InvalidInstruction(4); break; } case 0x80: { InvalidInstruction(4); break; } case 0x81: { InvalidInstruction(4); break; } case 0x82: { InvalidInstruction(4); break; } case 0x83: { InvalidInstruction(4); break; } case 0x84: { InvalidInstruction(4); break; } case 0x85: { InvalidInstruction(4); break; } case 0x86: { sdwCyclesRemaining -= 23; bTemp &= 0xfe; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x87: { InvalidInstruction(4); break; } case 0x88: { InvalidInstruction(4); break; } case 0x89: { InvalidInstruction(4); break; } case 0x8a: { InvalidInstruction(4); break; } case 0x8b: { InvalidInstruction(4); break; } case 0x8c: { InvalidInstruction(4); break; } case 0x8d: { InvalidInstruction(4); break; } case 0x8e: { sdwCyclesRemaining -= 23; bTemp &= 0xfd; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x8f: { InvalidInstruction(4); break; } case 0x90: { InvalidInstruction(4); break; } case 0x91: { InvalidInstruction(4); break; } case 0x92: { InvalidInstruction(4); break; } case 0x93: { InvalidInstruction(4); break; } case 0x94: { InvalidInstruction(4); break; } case 0x95: { InvalidInstruction(4); break; } case 0x96: { sdwCyclesRemaining -= 23; bTemp &= 0xfb; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x97: { InvalidInstruction(4); break; } case 0x98: { InvalidInstruction(4); break; } case 0x99: { InvalidInstruction(4); break; } case 0x9a: { InvalidInstruction(4); break; } case 0x9b: { InvalidInstruction(4); break; } case 0x9c: { InvalidInstruction(4); break; } case 0x9d: { InvalidInstruction(4); break; } case 0x9e: { sdwCyclesRemaining -= 23; bTemp &= 0xf7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x9f: { InvalidInstruction(4); break; } case 0xa0: { InvalidInstruction(4); break; } case 0xa1: { InvalidInstruction(4); break; } case 0xa2: { InvalidInstruction(4); break; } case 0xa3: { InvalidInstruction(4); break; } case 0xa4: { InvalidInstruction(4); break; } case 0xa5: { InvalidInstruction(4); break; } case 0xa6: { sdwCyclesRemaining -= 23; bTemp &= 0xef; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xa7: { InvalidInstruction(4); break; } case 0xa8: { InvalidInstruction(4); break; } case 0xa9: { InvalidInstruction(4); break; } case 0xaa: { InvalidInstruction(4); break; } case 0xab: { InvalidInstruction(4); break; } case 0xac: { InvalidInstruction(4); break; } case 0xad: { InvalidInstruction(4); break; } case 0xae: { sdwCyclesRemaining -= 23; bTemp &= 0xdf; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xaf: { InvalidInstruction(4); break; } case 0xb0: { InvalidInstruction(4); break; } case 0xb1: { InvalidInstruction(4); break; } case 0xb2: { InvalidInstruction(4); break; } case 0xb3: { InvalidInstruction(4); break; } case 0xb4: { InvalidInstruction(4); break; } case 0xb5: { InvalidInstruction(4); break; } case 0xb6: { sdwCyclesRemaining -= 23; bTemp &= 0xbf; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xb7: { InvalidInstruction(4); break; } case 0xb8: { InvalidInstruction(4); break; } case 0xb9: { InvalidInstruction(4); break; } case 0xba: { InvalidInstruction(4); break; } case 0xbb: { InvalidInstruction(4); break; } case 0xbc: { InvalidInstruction(4); break; } case 0xbd: { InvalidInstruction(4); break; } case 0xbe: { sdwCyclesRemaining -= 23; bTemp &= 0x7f; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xbf: { InvalidInstruction(4); break; } case 0xc0: { InvalidInstruction(4); break; } case 0xc1: { InvalidInstruction(4); break; } case 0xc2: { InvalidInstruction(4); break; } case 0xc3: { InvalidInstruction(4); break; } case 0xc4: { InvalidInstruction(4); break; } case 0xc5: { InvalidInstruction(4); break; } case 0xc6: { sdwCyclesRemaining -= 23; bTemp |= 0x01; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xc7: { InvalidInstruction(4); break; } case 0xc8: { InvalidInstruction(4); break; } case 0xc9: { InvalidInstruction(4); break; } case 0xca: { InvalidInstruction(4); break; } case 0xcb: { InvalidInstruction(4); break; } case 0xcc: { InvalidInstruction(4); break; } case 0xcd: { InvalidInstruction(4); break; } case 0xce: { sdwCyclesRemaining -= 23; bTemp |= 0x02; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xcf: { InvalidInstruction(4); break; } case 0xd0: { InvalidInstruction(4); break; } case 0xd1: { InvalidInstruction(4); break; } case 0xd2: { InvalidInstruction(4); break; } case 0xd3: { InvalidInstruction(4); break; } case 0xd4: { InvalidInstruction(4); break; } case 0xd5: { InvalidInstruction(4); break; } case 0xd6: { sdwCyclesRemaining -= 23; bTemp |= 0x04; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xd7: { InvalidInstruction(4); break; } case 0xd8: { InvalidInstruction(4); break; } case 0xd9: { InvalidInstruction(4); break; } case 0xda: { InvalidInstruction(4); break; } case 0xdb: { InvalidInstruction(4); break; } case 0xdc: { InvalidInstruction(4); break; } case 0xdd: { InvalidInstruction(4); break; } case 0xde: { sdwCyclesRemaining -= 23; bTemp |= 0x08; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xdf: { InvalidInstruction(4); break; } case 0xe0: { InvalidInstruction(4); break; } case 0xe1: { InvalidInstruction(4); break; } case 0xe2: { InvalidInstruction(4); break; } case 0xe3: { InvalidInstruction(4); break; } case 0xe4: { InvalidInstruction(4); break; } case 0xe5: { InvalidInstruction(4); break; } case 0xe6: { sdwCyclesRemaining -= 23; bTemp |= 0x10; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xe7: { InvalidInstruction(4); break; } case 0xe8: { InvalidInstruction(4); break; } case 0xe9: { InvalidInstruction(4); break; } case 0xea: { InvalidInstruction(4); break; } case 0xeb: { InvalidInstruction(4); break; } case 0xec: { InvalidInstruction(4); break; } case 0xed: { InvalidInstruction(4); break; } case 0xee: { sdwCyclesRemaining -= 23; bTemp |= 0x20; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xef: { InvalidInstruction(4); break; } case 0xf0: { InvalidInstruction(4); break; } case 0xf1: { InvalidInstruction(4); break; } case 0xf2: { InvalidInstruction(4); break; } case 0xf3: { InvalidInstruction(4); break; } case 0xf4: { InvalidInstruction(4); break; } case 0xf5: { InvalidInstruction(4); break; } case 0xf6: { sdwCyclesRemaining -= 23; bTemp |= 0x40; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xf7: { InvalidInstruction(4); break; } case 0xf8: { InvalidInstruction(4); break; } case 0xf9: { InvalidInstruction(4); break; } case 0xfa: { InvalidInstruction(4); break; } case 0xfb: { InvalidInstruction(4); break; } case 0xfc: { InvalidInstruction(4); break; } case 0xfd: { InvalidInstruction(4); break; } case 0xfe: { sdwCyclesRemaining -= 23; bTemp |= 0x80; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0xff: { InvalidInstruction(4); break; } } } void FDHandler(void) { switch (*pbPC++) { case 0x00: { InvalidInstruction(2); break; } case 0x01: { InvalidInstruction(2); break; } case 0x02: { InvalidInstruction(2); break; } case 0x03: { InvalidInstruction(2); break; } case 0x04: { InvalidInstruction(2); break; } case 0x05: { InvalidInstruction(2); break; } case 0x06: { InvalidInstruction(2); break; } case 0x07: { InvalidInstruction(2); break; } case 0x08: { InvalidInstruction(2); break; } case 0x09: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IY + cpu.z80BC; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IY ^ dwTemp ^ cpu.z80BC) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IY = dwTemp & 0xffff; break; } case 0x0a: { InvalidInstruction(2); break; } case 0x0b: { InvalidInstruction(2); break; } case 0x0c: { InvalidInstruction(2); break; } case 0x0d: { InvalidInstruction(2); break; } case 0x0e: { InvalidInstruction(2); break; } case 0x0f: { InvalidInstruction(2); break; } case 0x10: { InvalidInstruction(2); break; } case 0x11: { InvalidInstruction(2); break; } case 0x12: { InvalidInstruction(2); break; } case 0x13: { InvalidInstruction(2); break; } case 0x14: { InvalidInstruction(2); break; } case 0x15: { InvalidInstruction(2); break; } case 0x16: { InvalidInstruction(2); break; } case 0x17: { InvalidInstruction(2); break; } case 0x18: { InvalidInstruction(2); break; } case 0x19: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IY + cpu.z80DE; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IY ^ dwTemp ^ cpu.z80DE) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IY = dwTemp & 0xffff; break; } case 0x1a: { InvalidInstruction(2); break; } case 0x1b: { InvalidInstruction(2); break; } case 0x1c: { InvalidInstruction(2); break; } case 0x1d: { InvalidInstruction(2); break; } case 0x1e: { InvalidInstruction(2); break; } case 0x1f: { InvalidInstruction(2); break; } case 0x20: { InvalidInstruction(2); break; } case 0x21: { sdwCyclesRemaining -= 14; cpu.z80IY = *pbPC++; cpu.z80IY |= ((UINT32) *pbPC++ << 8); break; } case 0x22: { sdwCyclesRemaining -= 20; dwAddr = *pbPC++; dwAddr |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, (cpu.z80IY & 0xff), psMemWrite); psMemWrite->memoryCall(dwAddr + 1, (cpu.z80IY >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = cpu.z80IY; *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr) + 1) = cpu.z80IY >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) cpu.z80IY; cpu.z80Base[dwAddr + 1] = (UINT8) ((UINT32) cpu.z80IY >> 8); } break; } case 0x23: { sdwCyclesRemaining -= 10; cpu.z80IY++; cpu.z80IY &= 0xffff; break; } case 0x24: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80YH++]; break; } case 0x25: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[cpu.z80YH--]; break; } case 0x26: { sdwCyclesRemaining -= 9; cpu.z80YH = *pbPC++; break; } case 0x27: { InvalidInstruction(2); break; } case 0x28: { InvalidInstruction(2); break; } case 0x29: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IY + cpu.z80IY; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IY ^ dwTemp ^ cpu.z80HL) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IY = dwTemp & 0xffff; break; } case 0x2a: { sdwCyclesRemaining -= 20; dwAddr = *pbPC++; dwAddr |= ((UINT32) *pbPC++ << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80IY = psMemRead->memoryCall(dwAddr, psMemRead); cpu.z80IY |= (UINT32) ((UINT32) psMemRead->memoryCall(dwAddr + 1, psMemRead) << 8); } else { cpu.z80IY = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); cpu.z80IY |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80IY = cpu.z80Base[dwAddr]; cpu.z80IY |= (UINT32) ((UINT32) cpu.z80Base[dwAddr + 1] << 8); } break; } case 0x2b: { sdwCyclesRemaining -= 10; cpu.z80IY--; cpu.z80IY &= 0xffff; break; } case 0x2c: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80YL++]; break; } case 0x2d: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[cpu.z80YL--]; break; } case 0x2e: { sdwCyclesRemaining -= 9; cpu.z80YL = *pbPC++; break; } case 0x2f: { InvalidInstruction(2); break; } case 0x30: { InvalidInstruction(2); break; } case 0x31: { InvalidInstruction(2); break; } case 0x32: { InvalidInstruction(2); break; } case 0x33: { InvalidInstruction(2); break; } case 0x34: { sdwCyclesRemaining -= 23; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[bTemp++]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x35: { sdwCyclesRemaining -= 23; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[bTemp--]; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwAddr >= psMemWrite->lowAddr) && (dwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwAddr, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwAddr - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwAddr] = (UINT8) bTemp; } break; } case 0x36: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, *pbPC++, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = *pbPC++; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) *pbPC++; } break; } case 0x37: { InvalidInstruction(2); break; } case 0x38: { InvalidInstruction(2); break; } case 0x39: { sdwCyclesRemaining -= 15; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80IY + cpu.z80sp; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80IY ^ dwTemp ^ cpu.z80sp) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80IY = dwTemp & 0xffff; break; } case 0x3a: { InvalidInstruction(2); break; } case 0x3b: { InvalidInstruction(2); break; } case 0x3c: { InvalidInstruction(2); break; } case 0x3d: { InvalidInstruction(2); break; } case 0x3e: { InvalidInstruction(2); break; } case 0x3f: { InvalidInstruction(2); break; } case 0x40: { InvalidInstruction(2); break; } case 0x41: { InvalidInstruction(2); break; } case 0x42: { InvalidInstruction(2); break; } case 0x43: { InvalidInstruction(2); break; } case 0x44: { sdwCyclesRemaining -= 9; cpu.z80B = cpu.z80YH; break; } case 0x45: { sdwCyclesRemaining -= 9; cpu.z80B = cpu.z80YL; break; } case 0x46: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80B = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80B = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80B = cpu.z80Base[sdwAddr]; } break; } case 0x47: { InvalidInstruction(2); break; } case 0x48: { InvalidInstruction(2); break; } case 0x49: { InvalidInstruction(2); break; } case 0x4a: { InvalidInstruction(2); break; } case 0x4b: { InvalidInstruction(2); break; } case 0x4c: { sdwCyclesRemaining -= 9; cpu.z80C = cpu.z80YH; break; } case 0x4d: { sdwCyclesRemaining -= 9; cpu.z80C = cpu.z80YL; break; } case 0x4e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80C = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80C = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80C = cpu.z80Base[sdwAddr]; } break; } case 0x4f: { InvalidInstruction(2); break; } case 0x50: { InvalidInstruction(2); break; } case 0x51: { InvalidInstruction(2); break; } case 0x52: { InvalidInstruction(2); break; } case 0x53: { InvalidInstruction(2); break; } case 0x54: { sdwCyclesRemaining -= 9; cpu.z80D = cpu.z80YH; break; } case 0x55: { sdwCyclesRemaining -= 9; cpu.z80D = cpu.z80YL; break; } case 0x56: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80D = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80D = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80D = cpu.z80Base[sdwAddr]; } break; } case 0x57: { InvalidInstruction(2); break; } case 0x58: { InvalidInstruction(2); break; } case 0x59: { InvalidInstruction(2); break; } case 0x5a: { InvalidInstruction(2); break; } case 0x5b: { InvalidInstruction(2); break; } case 0x5c: { sdwCyclesRemaining -= 9; cpu.z80E = cpu.z80YH; break; } case 0x5d: { sdwCyclesRemaining -= 9; cpu.z80E = cpu.z80YL; break; } case 0x5e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80E = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80E = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80E = cpu.z80Base[sdwAddr]; } break; } case 0x5f: { InvalidInstruction(2); break; } case 0x60: { sdwCyclesRemaining -= 9; cpu.z80YH = cpu.z80B; break; } case 0x61: { sdwCyclesRemaining -= 9; cpu.z80YH = cpu.z80C; break; } case 0x62: { sdwCyclesRemaining -= 9; cpu.z80YH = cpu.z80D; break; } case 0x63: { sdwCyclesRemaining -= 9; cpu.z80YH = cpu.z80E; break; } case 0x64: { sdwCyclesRemaining -= 9; break; } case 0x65: { sdwCyclesRemaining -= 9; cpu.z80YH = cpu.z80YL; break; } case 0x66: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80H = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80H = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80H = cpu.z80Base[sdwAddr]; } break; } case 0x67: { sdwCyclesRemaining -= 9; cpu.z80YH = cpu.z80A; break; } case 0x68: { sdwCyclesRemaining -= 9; cpu.z80YL = cpu.z80B; break; } case 0x69: { sdwCyclesRemaining -= 9; cpu.z80YL = cpu.z80C; break; } case 0x6a: { sdwCyclesRemaining -= 9; cpu.z80YL = cpu.z80D; break; } case 0x6b: { sdwCyclesRemaining -= 9; cpu.z80YL = cpu.z80E; break; } case 0x6c: { sdwCyclesRemaining -= 9; cpu.z80YL = cpu.z80YH; break; } case 0x6d: { sdwCyclesRemaining -= 9; break; } case 0x6e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80L = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80L = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80L = cpu.z80Base[sdwAddr]; } break; } case 0x6f: { sdwCyclesRemaining -= 9; cpu.z80YL = cpu.z80A; break; } case 0x70: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80B, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80B; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80B; } break; } case 0x71: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80C, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80C; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80C; } break; } case 0x72: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80D, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80D; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80D; } break; } case 0x73: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80E, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80E; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80E; } break; } case 0x74: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80H, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80H; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80H; } break; } case 0x75: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80L, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80L; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80L; } break; } case 0x76: { sdwCyclesRemaining -= 19; InvalidInstruction(2); break; } case 0x77: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemWrite->lowAddr) && (sdwAddr <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(sdwAddr, cpu.z80A, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (sdwAddr - psMemWrite->lowAddr)) = cpu.z80A; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[sdwAddr] = (UINT8) cpu.z80A; } break; } case 0x78: { InvalidInstruction(2); break; } case 0x79: { InvalidInstruction(2); break; } case 0x7a: { InvalidInstruction(2); break; } case 0x7b: { InvalidInstruction(2); break; } case 0x7c: { sdwCyclesRemaining -= 9; cpu.z80A = cpu.z80YH; break; } case 0x7d: { sdwCyclesRemaining -= 9; cpu.z80A = cpu.z80YL; break; } case 0x7e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; // Get the offset sdwAddr = ((INT32) cpu.z80IY + sdwAddr) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((sdwAddr >= psMemRead->lowAddr) && (sdwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80A = psMemRead->memoryCall(sdwAddr, psMemRead); } else { cpu.z80A = *((UINT8 *) psMemRead->pUserArea + (sdwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80A = cpu.z80Base[sdwAddr]; } break; } case 0x7f: { InvalidInstruction(2); break; } case 0x80: { InvalidInstruction(2); break; } case 0x81: { InvalidInstruction(2); break; } case 0x82: { InvalidInstruction(2); break; } case 0x83: { InvalidInstruction(2); break; } case 0x84: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80YH; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80YH]; InvalidInstruction(2); break; } case 0x85: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80YL; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80YL]; InvalidInstruction(2); break; } case 0x86: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A += bTemp; break; } case 0x87: { InvalidInstruction(2); break; } case 0x88: { InvalidInstruction(2); break; } case 0x89: { InvalidInstruction(2); break; } case 0x8a: { InvalidInstruction(2); break; } case 0x8b: { InvalidInstruction(2); break; } case 0x8c: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80YH + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80YH | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x8d: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A + cpu.z80YL + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80YL | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x8e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } bTemp2 = (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A += bTemp + bTemp2; break; } case 0x8f: { InvalidInstruction(2); break; } case 0x90: { InvalidInstruction(2); break; } case 0x91: { InvalidInstruction(2); break; } case 0x92: { InvalidInstruction(2); break; } case 0x93: { InvalidInstruction(2); break; } case 0x94: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80YH; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80YH]; InvalidInstruction(2); break; } case 0x95: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80YL; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80YL]; InvalidInstruction(2); break; } case 0x96: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A -= bTemp; break; } case 0x97: { InvalidInstruction(2); break; } case 0x98: { InvalidInstruction(2); break; } case 0x99: { InvalidInstruction(2); break; } case 0x9a: { InvalidInstruction(2); break; } case 0x9b: { InvalidInstruction(2); break; } case 0x9c: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80YH - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80YH | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x9d: { sdwCyclesRemaining -= 9; bTemp2 = cpu.z80A - cpu.z80YL - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80YL | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; InvalidInstruction(2); break; } case 0x9e: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } bTemp2 = cpu.z80A; cpu.z80A = cpu.z80A - bTemp - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) bTemp2 << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; break; } case 0x9f: { InvalidInstruction(2); break; } case 0xa0: { InvalidInstruction(2); break; } case 0xa1: { InvalidInstruction(2); break; } case 0xa2: { InvalidInstruction(2); break; } case 0xa3: { InvalidInstruction(2); break; } case 0xa4: { sdwCyclesRemaining -= 9; cpu.z80A &= cpu.z80YH; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xa5: { sdwCyclesRemaining -= 9; cpu.z80A &= cpu.z80YL; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xa6: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80A &= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa7: { InvalidInstruction(2); break; } case 0xa8: { InvalidInstruction(2); break; } case 0xa9: { InvalidInstruction(2); break; } case 0xaa: { InvalidInstruction(2); break; } case 0xab: { InvalidInstruction(2); break; } case 0xac: { sdwCyclesRemaining -= 9; cpu.z80A ^= cpu.z80YH; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xad: { sdwCyclesRemaining -= 9; cpu.z80A ^= cpu.z80YL; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xae: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80A ^= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xaf: { InvalidInstruction(2); break; } case 0xb0: { InvalidInstruction(2); break; } case 0xb1: { InvalidInstruction(2); break; } case 0xb2: { InvalidInstruction(2); break; } case 0xb3: { InvalidInstruction(2); break; } case 0xb4: { sdwCyclesRemaining -= 9; cpu.z80A |= cpu.z80YH; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xb5: { sdwCyclesRemaining -= 9; cpu.z80A |= cpu.z80YL; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xb6: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80A |= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb7: { InvalidInstruction(2); break; } case 0xb8: { InvalidInstruction(2); break; } case 0xb9: { InvalidInstruction(2); break; } case 0xba: { InvalidInstruction(2); break; } case 0xbb: { InvalidInstruction(2); break; } case 0xbc: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xbd: { sdwCyclesRemaining -= 9; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; InvalidInstruction(2); break; } case 0xbe: { sdwCyclesRemaining -= 19; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ dwAddr = (sdwAddr + (INT32) cpu.z80IY) & 0xffff; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(dwAddr, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[dwAddr]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; break; } case 0xbf: { InvalidInstruction(2); break; } case 0xc0: { InvalidInstruction(2); break; } case 0xc1: { InvalidInstruction(2); break; } case 0xc2: { InvalidInstruction(2); break; } case 0xc3: { InvalidInstruction(2); break; } case 0xc4: { InvalidInstruction(2); break; } case 0xc5: { InvalidInstruction(2); break; } case 0xc6: { InvalidInstruction(2); break; } case 0xc7: { InvalidInstruction(2); break; } case 0xc8: { InvalidInstruction(2); break; } case 0xc9: { InvalidInstruction(2); break; } case 0xca: { InvalidInstruction(2); break; } case 0xcb: { DDFDCBHandler(1); break; } case 0xcc: { InvalidInstruction(2); break; } case 0xcd: { InvalidInstruction(2); break; } case 0xce: { InvalidInstruction(2); break; } case 0xcf: { InvalidInstruction(2); break; } case 0xd0: { InvalidInstruction(2); break; } case 0xd1: { InvalidInstruction(2); break; } case 0xd2: { InvalidInstruction(2); break; } case 0xd3: { InvalidInstruction(2); break; } case 0xd4: { InvalidInstruction(2); break; } case 0xd5: { InvalidInstruction(2); break; } case 0xd6: { InvalidInstruction(2); break; } case 0xd7: { InvalidInstruction(2); break; } case 0xd8: { InvalidInstruction(2); break; } case 0xd9: { InvalidInstruction(2); break; } case 0xda: { InvalidInstruction(2); break; } case 0xdb: { InvalidInstruction(2); break; } case 0xdc: { InvalidInstruction(2); break; } case 0xdd: { InvalidInstruction(2); break; } case 0xde: { InvalidInstruction(2); break; } case 0xdf: { InvalidInstruction(2); break; } case 0xe0: { InvalidInstruction(2); break; } case 0xe1: { sdwCyclesRemaining -= 14; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80IY = psMemRead->memoryCall(cpu.z80sp, psMemRead); cpu.z80IY |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { cpu.z80IY = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); cpu.z80IY |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80IY = cpu.z80Base[cpu.z80sp]; cpu.z80IY |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } cpu.z80sp += 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ break; } case 0xe2: { InvalidInstruction(2); break; } case 0xe3: { sdwCyclesRemaining -= 23; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { dwAddr = psMemRead->memoryCall(cpu.z80sp, psMemRead); dwAddr |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { dwAddr = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); dwAddr |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { dwAddr = cpu.z80Base[cpu.z80sp]; dwAddr |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80IY & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80IY >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80IY; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80IY >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80IY; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80IY >> 8); } cpu.z80IY = dwAddr; break; } case 0xe4: { InvalidInstruction(2); break; } case 0xe5: { sdwCyclesRemaining -= 15; cpu.z80sp -= 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80IY & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80IY >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80IY; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80IY >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80IY; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80IY >> 8); } break; } case 0xe6: { InvalidInstruction(2); break; } case 0xe7: { InvalidInstruction(2); break; } case 0xe8: { InvalidInstruction(2); break; } case 0xe9: { sdwCyclesRemaining -= 8; pbPC = cpu.z80Base + cpu.z80IY; break; } case 0xea: { InvalidInstruction(2); break; } case 0xeb: { InvalidInstruction(2); break; } case 0xec: { InvalidInstruction(2); break; } case 0xed: { InvalidInstruction(2); break; } case 0xee: { InvalidInstruction(2); break; } case 0xef: { InvalidInstruction(2); break; } case 0xf0: { InvalidInstruction(2); break; } case 0xf1: { InvalidInstruction(2); break; } case 0xf2: { InvalidInstruction(2); break; } case 0xf3: { InvalidInstruction(2); break; } case 0xf4: { InvalidInstruction(2); break; } case 0xf5: { InvalidInstruction(2); break; } case 0xf6: { InvalidInstruction(2); break; } case 0xf7: { InvalidInstruction(2); break; } case 0xf8: { InvalidInstruction(2); break; } case 0xf9: { sdwCyclesRemaining -= 10; cpu.z80sp = cpu.z80IY; break; } case 0xfa: { InvalidInstruction(2); break; } case 0xfb: { InvalidInstruction(2); break; } case 0xfc: { InvalidInstruction(2); break; } case 0xfd: { InvalidInstruction(2); break; } case 0xfe: { InvalidInstruction(2); break; } case 0xff: { InvalidInstruction(2); break; } } } /* Main execution entry point */ UINT32 mz80exec(UINT32 dwCycles) { UINT8 bOpcode; dwReturnCode = 0x80000000; /* Assume it'll work */ sdwCyclesRemaining = dwCycles; dwOriginalCycles = dwCycles; if (cpu.z80halted) { dwElapsedTicks += dwCycles; return(0x80000000); } pbPC = cpu.z80Base + cpu.z80pc; while (sdwCyclesRemaining > 0) { bOpcode = *pbPC++; switch (bOpcode) { case 0x00: { sdwCyclesRemaining -= 4; /* Intentionally not doing anything - NOP! */ break; } case 0x01: { sdwCyclesRemaining -= 10; cpu.z80BC = *pbPC++; /* LSB First */ cpu.z80BC |= (((UINT32) *pbPC++ << 8)); /* Now the MSB */ break; } case 0x02: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80BC >= psMemWrite->lowAddr) && (cpu.z80BC <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80BC, cpu.z80A, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80BC - psMemWrite->lowAddr)) = cpu.z80A; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80BC] = (UINT8) cpu.z80A; } break; } case 0x03: { sdwCyclesRemaining -= 6; cpu.z80BC++; cpu.z80BC &= 0xffff; break; } case 0x04: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80B++]; break; } case 0x05: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80B--]; break; } case 0x06: { sdwCyclesRemaining -= 7; cpu.z80B = *pbPC++; /* Get immediate byte into register */ break; } case 0x07: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); cpu.z80F |= (cpu.z80A >> 7); cpu.z80A = (cpu.z80A << 1) | (cpu.z80A >> 7); break; } case 0x08: { sdwCyclesRemaining -= 4; dwAddr = (UINT32) cpu.z80AF; cpu.z80AF = cpu.z80afprime; cpu.z80afprime = dwAddr; break; } case 0x09: { sdwCyclesRemaining -= 11; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80HL + cpu.z80BC; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80HL ^ dwTemp ^ cpu.z80BC) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x0a: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80BC >= psMemRead->lowAddr) && (cpu.z80BC <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80A = psMemRead->memoryCall(cpu.z80BC, psMemRead); } else { cpu.z80A = *((UINT8 *) psMemRead->pUserArea + (cpu.z80BC - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80A = cpu.z80Base[cpu.z80BC]; } break; } case 0x0b: { sdwCyclesRemaining -= 6; cpu.z80BC--; cpu.z80BC &= 0xffff; break; } case 0x0c: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80C++]; break; } case 0x0d: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80C--]; break; } case 0x0e: { sdwCyclesRemaining -= 7; cpu.z80C = *pbPC++; /* Get immediate byte into register */ break; } case 0x0f: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY); cpu.z80A = (cpu.z80A >> 1) | (cpu.z80A << 7); break; } case 0x10: { sdwCyclesRemaining -= 8; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ if (--cpu.z80B) { dwElapsedTicks += 5; /* 5 More for jump taken */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff; pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */ } break; } case 0x11: { sdwCyclesRemaining -= 10; cpu.z80DE = *pbPC++; /* LSB First */ cpu.z80DE |= (((UINT32) *pbPC++ << 8)); /* Now the MSB */ break; } case 0x12: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80DE >= psMemWrite->lowAddr) && (cpu.z80DE <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80DE, cpu.z80A, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80DE - psMemWrite->lowAddr)) = cpu.z80A; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80DE] = (UINT8) cpu.z80A; } break; } case 0x13: { sdwCyclesRemaining -= 6; cpu.z80DE++; cpu.z80DE &= 0xffff; break; } case 0x14: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80D++]; break; } case 0x15: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80D--]; break; } case 0x16: { sdwCyclesRemaining -= 7; cpu.z80D = *pbPC++; /* Get immediate byte into register */ break; } case 0x17: { sdwCyclesRemaining -= 4; bTemp = cpu.z80A >> 7; cpu.z80A = (cpu.z80A << 1) | (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY)) | bTemp; break; } case 0x18: { sdwCyclesRemaining -= 12; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff; { sdwCyclesRemaining -= 5; pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */ } break; } case 0x19: { sdwCyclesRemaining -= 11; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80HL + cpu.z80DE; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80HL ^ dwTemp ^ cpu.z80DE) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x1a: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80DE >= psMemRead->lowAddr) && (cpu.z80DE <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80A = psMemRead->memoryCall(cpu.z80DE, psMemRead); } else { cpu.z80A = *((UINT8 *) psMemRead->pUserArea + (cpu.z80DE - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80A = cpu.z80Base[cpu.z80DE]; } break; } case 0x1b: { sdwCyclesRemaining -= 6; cpu.z80DE--; cpu.z80DE &= 0xffff; break; } case 0x1c: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80E++]; break; } case 0x1d: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80E--]; break; } case 0x1e: { sdwCyclesRemaining -= 7; cpu.z80E = *pbPC++; /* Get immediate byte into register */ break; } case 0x1f: { sdwCyclesRemaining -= 4; bTemp = (cpu.z80F & Z80_FLAG_CARRY) << 7; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY)) | (cpu.z80A & Z80_FLAG_CARRY); cpu.z80A = ((cpu.z80A >> 1) | bTemp); break; } case 0x20: { sdwCyclesRemaining -= 7; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff; if (!(cpu.z80F & Z80_FLAG_ZERO)) { sdwCyclesRemaining -= 5; pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */ } break; } case 0x21: { sdwCyclesRemaining -= 10; cpu.z80HL = *pbPC++; /* LSB First */ cpu.z80HL |= (((UINT32) *pbPC++ << 8)); /* Now the MSB */ break; } case 0x22: { sdwCyclesRemaining -= 16; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwTemp >= psMemWrite->lowAddr) && (dwTemp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwTemp, (cpu.z80HL & 0xff), psMemWrite); psMemWrite->memoryCall(dwTemp + 1, (cpu.z80HL >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr)) = cpu.z80HL; *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr) + 1) = cpu.z80HL >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwTemp] = (UINT8) cpu.z80HL; cpu.z80Base[dwTemp + 1] = (UINT8) ((UINT32) cpu.z80HL >> 8); } break; } case 0x23: { sdwCyclesRemaining -= 6; cpu.z80HL++; cpu.z80HL &= 0xffff; break; } case 0x24: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80H++]; break; } case 0x25: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80H--]; break; } case 0x26: { sdwCyclesRemaining -= 7; cpu.z80H = *pbPC++; /* Get immediate byte into register */ break; } case 0x27: { sdwCyclesRemaining -= 4; dwAddr = (((cpu.z80F & Z80_FLAG_CARRY) | ((cpu.z80F & Z80_FLAG_HALF_CARRY) >> 3) | ((cpu.z80F & Z80_FLAG_NEGATIVE) << 1)) << 8) | cpu.z80A; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= (wDAATable[dwAddr] >> 8); cpu.z80A = wDAATable[dwAddr] & 0xff; break; } case 0x28: { sdwCyclesRemaining -= 7; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff; if (cpu.z80F & Z80_FLAG_ZERO) { sdwCyclesRemaining -= 5; pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */ } break; } case 0x29: { sdwCyclesRemaining -= 11; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80HL + cpu.z80HL; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80HL ^ dwTemp ^ cpu.z80HL) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x2a: { sdwCyclesRemaining -= 16; dwAddr = *pbPC++; dwAddr |= ((UINT32) *pbPC++ << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwAddr >= psMemRead->lowAddr) && (dwAddr <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80HL = psMemRead->memoryCall(dwAddr, psMemRead); cpu.z80HL |= (UINT32) ((UINT32) psMemRead->memoryCall(dwAddr + 1, psMemRead) << 8); } else { cpu.z80HL = *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr)); cpu.z80HL |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (dwAddr - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80HL = cpu.z80Base[dwAddr]; cpu.z80HL |= (UINT32) ((UINT32) cpu.z80Base[dwAddr + 1] << 8); } break; } case 0x2b: { sdwCyclesRemaining -= 6; cpu.z80HL--; cpu.z80HL &= 0xffff; break; } case 0x2c: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80L++]; break; } case 0x2d: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80L--]; break; } case 0x2e: { sdwCyclesRemaining -= 7; cpu.z80L = *pbPC++; /* Get immediate byte into register */ break; } case 0x2f: { sdwCyclesRemaining -= 4; cpu.z80A ^= 0xff; cpu.z80F |= (Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); break; } case 0x30: { sdwCyclesRemaining -= 7; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff; if (!(cpu.z80F & Z80_FLAG_CARRY)) { sdwCyclesRemaining -= 5; pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */ } break; } case 0x31: { sdwCyclesRemaining -= 10; cpu.z80sp = *pbPC++; /* LSB First */ cpu.z80sp |= (((UINT32) *pbPC++ << 8)); /* Now the MSB */ break; } case 0x32: { sdwCyclesRemaining -= 13; dwTemp = *pbPC++; dwTemp |= ((UINT32) *pbPC++ << 8); psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((dwTemp >= psMemWrite->lowAddr) && (dwTemp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(dwTemp, cpu.z80A, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (dwTemp - psMemWrite->lowAddr)) = cpu.z80A; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[dwTemp] = (UINT8) cpu.z80A; } break; } case 0x33: { sdwCyclesRemaining -= 6; cpu.z80sp++; cpu.z80sp &= 0xffff; break; } case 0x34: { sdwCyclesRemaining -= 11; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[bTemp]; bTemp++; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x35: { sdwCyclesRemaining -= 11; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostDecFlags[bTemp]; bTemp--; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, bTemp, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = bTemp; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) bTemp; } break; } case 0x36: { sdwCyclesRemaining -= 10; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, *pbPC++, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = *pbPC++; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) *pbPC++; } break; } case 0x37: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE); cpu.z80F |= Z80_FLAG_CARRY; break; } case 0x38: { sdwCyclesRemaining -= 7; sdwAddr = (INT8) *pbPC++; /* Get LSB first */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff; if (cpu.z80F & Z80_FLAG_CARRY) { sdwCyclesRemaining -= 5; pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */ } break; } case 0x39: { sdwCyclesRemaining -= 11; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY); dwTemp = cpu.z80HL + cpu.z80sp; cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80HL ^ dwTemp ^ cpu.z80sp) >> 8) & Z80_FLAG_HALF_CARRY); cpu.z80HL = dwTemp & 0xffff; break; } case 0x3a: { sdwCyclesRemaining -= 13; dwTemp = *pbPC++; dwTemp |= (((UINT32) *pbPC++) << 8); psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((dwTemp >= psMemRead->lowAddr) && (dwTemp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80A = psMemRead->memoryCall(dwTemp, psMemRead); } else { cpu.z80A = *((UINT8 *) psMemRead->pUserArea + (dwTemp - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80A = cpu.z80Base[dwTemp]; } break; } case 0x3b: { sdwCyclesRemaining -= 6; cpu.z80sp--; cpu.z80sp &= 0xffff; break; } case 0x3c: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE); cpu.z80F |= bPostIncFlags[cpu.z80A++]; break; } case 0x3d: { sdwCyclesRemaining -= 4; cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY); cpu.z80F |= bPostDecFlags[cpu.z80A--]; break; } case 0x3e: { sdwCyclesRemaining -= 7; cpu.z80A = *pbPC++; /* Get immediate byte into register */ break; } case 0x3f: { sdwCyclesRemaining -= 4; bTemp = (cpu.z80F & Z80_FLAG_CARRY) << 4; cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE); cpu.z80F ^= Z80_FLAG_CARRY; break; } case 0x40: { sdwCyclesRemaining -= 4; break; } case 0x41: { sdwCyclesRemaining -= 4; cpu.z80B = cpu.z80C; break; } case 0x42: { sdwCyclesRemaining -= 4; cpu.z80B = cpu.z80D; break; } case 0x43: { sdwCyclesRemaining -= 4; cpu.z80B = cpu.z80E; break; } case 0x44: { sdwCyclesRemaining -= 4; cpu.z80B = cpu.z80H; break; } case 0x45: { sdwCyclesRemaining -= 4; cpu.z80B = cpu.z80L; break; } case 0x46: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80B = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80B = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80B = cpu.z80Base[cpu.z80HL]; } break; } case 0x47: { sdwCyclesRemaining -= 4; cpu.z80B = cpu.z80A; break; } case 0x48: { sdwCyclesRemaining -= 4; cpu.z80C = cpu.z80B; break; } case 0x49: { sdwCyclesRemaining -= 4; break; } case 0x4a: { sdwCyclesRemaining -= 4; cpu.z80C = cpu.z80D; break; } case 0x4b: { sdwCyclesRemaining -= 4; cpu.z80C = cpu.z80E; break; } case 0x4c: { sdwCyclesRemaining -= 4; cpu.z80C = cpu.z80H; break; } case 0x4d: { sdwCyclesRemaining -= 4; cpu.z80C = cpu.z80L; break; } case 0x4e: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80C = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80C = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80C = cpu.z80Base[cpu.z80HL]; } break; } case 0x4f: { sdwCyclesRemaining -= 4; cpu.z80C = cpu.z80A; break; } case 0x50: { sdwCyclesRemaining -= 4; cpu.z80D = cpu.z80B; break; } case 0x51: { sdwCyclesRemaining -= 4; cpu.z80D = cpu.z80C; break; } case 0x52: { sdwCyclesRemaining -= 4; break; } case 0x53: { sdwCyclesRemaining -= 4; cpu.z80D = cpu.z80E; break; } case 0x54: { sdwCyclesRemaining -= 4; cpu.z80D = cpu.z80H; break; } case 0x55: { sdwCyclesRemaining -= 4; cpu.z80D = cpu.z80L; break; } case 0x56: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80D = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80D = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80D = cpu.z80Base[cpu.z80HL]; } break; } case 0x57: { sdwCyclesRemaining -= 4; cpu.z80D = cpu.z80A; break; } case 0x58: { sdwCyclesRemaining -= 4; cpu.z80E = cpu.z80B; break; } case 0x59: { sdwCyclesRemaining -= 4; cpu.z80E = cpu.z80C; break; } case 0x5a: { sdwCyclesRemaining -= 4; cpu.z80E = cpu.z80D; break; } case 0x5b: { sdwCyclesRemaining -= 4; break; } case 0x5c: { sdwCyclesRemaining -= 4; cpu.z80E = cpu.z80H; break; } case 0x5d: { sdwCyclesRemaining -= 4; cpu.z80E = cpu.z80L; break; } case 0x5e: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80E = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80E = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80E = cpu.z80Base[cpu.z80HL]; } break; } case 0x5f: { sdwCyclesRemaining -= 4; cpu.z80E = cpu.z80A; break; } case 0x60: { sdwCyclesRemaining -= 4; cpu.z80H = cpu.z80B; break; } case 0x61: { sdwCyclesRemaining -= 4; cpu.z80H = cpu.z80C; break; } case 0x62: { sdwCyclesRemaining -= 4; cpu.z80H = cpu.z80D; break; } case 0x63: { sdwCyclesRemaining -= 4; cpu.z80H = cpu.z80E; break; } case 0x64: { sdwCyclesRemaining -= 4; break; } case 0x65: { sdwCyclesRemaining -= 4; cpu.z80H = cpu.z80L; break; } case 0x66: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80H = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80H = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80H = cpu.z80Base[cpu.z80HL]; } break; } case 0x67: { sdwCyclesRemaining -= 4; cpu.z80H = cpu.z80A; break; } case 0x68: { sdwCyclesRemaining -= 4; cpu.z80L = cpu.z80B; break; } case 0x69: { sdwCyclesRemaining -= 4; cpu.z80L = cpu.z80C; break; } case 0x6a: { sdwCyclesRemaining -= 4; cpu.z80L = cpu.z80D; break; } case 0x6b: { sdwCyclesRemaining -= 4; cpu.z80L = cpu.z80E; break; } case 0x6c: { sdwCyclesRemaining -= 4; cpu.z80L = cpu.z80H; break; } case 0x6d: { sdwCyclesRemaining -= 4; break; } case 0x6e: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80L = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80L = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80L = cpu.z80Base[cpu.z80HL]; } break; } case 0x6f: { sdwCyclesRemaining -= 4; cpu.z80L = cpu.z80A; break; } case 0x70: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80B, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80B; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80B; } break; } case 0x71: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80C, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80C; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80C; } break; } case 0x72: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80D, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80D; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80D; } break; } case 0x73: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80E, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80E; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80E; } break; } case 0x74: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80H, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80H; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80H; } break; } case 0x75: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80L, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80L; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80L; } break; } case 0x76: { sdwCyclesRemaining -= 4; cpu.z80halted = 1; dwElapsedTicks += sdwCyclesRemaining; sdwCyclesRemaining = 0; break; } case 0x77: { sdwCyclesRemaining -= 7; psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemWrite->lowAddr) && (cpu.z80HL <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80HL, cpu.z80A, psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80HL - psMemWrite->lowAddr)) = cpu.z80A; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80HL] = (UINT8) cpu.z80A; } break; } case 0x78: { sdwCyclesRemaining -= 4; cpu.z80A = cpu.z80B; break; } case 0x79: { sdwCyclesRemaining -= 4; cpu.z80A = cpu.z80C; break; } case 0x7a: { sdwCyclesRemaining -= 4; cpu.z80A = cpu.z80D; break; } case 0x7b: { sdwCyclesRemaining -= 4; cpu.z80A = cpu.z80E; break; } case 0x7c: { sdwCyclesRemaining -= 4; cpu.z80A = cpu.z80H; break; } case 0x7d: { sdwCyclesRemaining -= 4; cpu.z80A = cpu.z80L; break; } case 0x7e: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80A = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { cpu.z80A = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80A = cpu.z80Base[cpu.z80HL]; } break; } case 0x7f: { sdwCyclesRemaining -= 4; break; } case 0x80: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80B; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80B]; cpu.z80A = bTemp2; break; } case 0x81: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80C; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80C]; cpu.z80A = bTemp2; break; } case 0x82: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80D; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80D]; cpu.z80A = bTemp2; break; } case 0x83: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80E; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80E]; cpu.z80A = bTemp2; break; } case 0x84: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80H; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80H]; cpu.z80A = bTemp2; break; } case 0x85: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80L; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80L]; cpu.z80A = bTemp2; break; } case 0x86: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = cpu.z80A + bTemp; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A = bTemp2; break; } case 0x87: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80A; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80A]; cpu.z80A = bTemp2; break; } case 0x88: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80B + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80B | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x89: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80C + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80C | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x8a: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80D + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80D | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x8b: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80E + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80E | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x8c: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80H + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80H | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x8d: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80L + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80L | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x8e: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = cpu.z80A + bTemp + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x8f: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A + cpu.z80A + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | cpu.z80A | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x90: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80B; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80B]; cpu.z80A = bTemp2; break; } case 0x91: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80C; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80C]; cpu.z80A = bTemp2; break; } case 0x92: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80D; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80D]; cpu.z80A = bTemp2; break; } case 0x93: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80E; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80E]; cpu.z80A = bTemp2; break; } case 0x94: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80H; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80H]; cpu.z80A = bTemp2; break; } case 0x95: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80L; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80L]; cpu.z80A = bTemp2; break; } case 0x96: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = cpu.z80A - bTemp; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A = bTemp2; break; } case 0x97: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80A; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80A]; cpu.z80A = bTemp2; break; } case 0x98: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80B - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80B | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x99: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80C - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80C | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x9a: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80D - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80D | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x9b: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80E - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80E | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x9c: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80H - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80H | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x9d: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80L - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80L | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x9e: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } bTemp2 = cpu.z80A - bTemp - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0x9f: { sdwCyclesRemaining -= 4; bTemp2 = cpu.z80A - cpu.z80A - (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80A | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = bTemp2; break; } case 0xa0: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80B; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa1: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80C; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa2: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80D; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa3: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80E; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa4: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80H; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa5: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80L; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa6: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80A &= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa7: { sdwCyclesRemaining -= 4; cpu.z80A &= cpu.z80A; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xa8: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80B; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xa9: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80C; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xaa: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80D; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xab: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80E; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xac: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80H; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xad: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80L; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xae: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80A ^= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xaf: { sdwCyclesRemaining -= 4; cpu.z80A ^= cpu.z80A; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb0: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80B; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb1: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80C; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb2: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80D; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb3: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80E; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb4: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80H; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb5: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80L; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb6: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80A |= bTemp; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb7: { sdwCyclesRemaining -= 4; cpu.z80A |= cpu.z80A; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xb8: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80B]; break; } case 0xb9: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80C]; break; } case 0xba: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80D]; break; } case 0xbb: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80E]; break; } case 0xbc: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80H]; break; } case 0xbd: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80L]; break; } case 0xbe: { sdwCyclesRemaining -= 7; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80HL >= psMemRead->lowAddr) && (cpu.z80HL <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { bTemp = psMemRead->memoryCall(cpu.z80HL, psMemRead); } else { bTemp = *((UINT8 *) psMemRead->pUserArea + (cpu.z80HL - psMemRead->lowAddr)); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { bTemp = cpu.z80Base[cpu.z80HL]; } cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; break; } case 0xbf: { sdwCyclesRemaining -= 4; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | cpu.z80A]; break; } case 0xc0: { sdwCyclesRemaining -= 5; if (!(cpu.z80F & Z80_FLAG_ZERO)) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xc1: { sdwCyclesRemaining -= 10; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80BC = psMemRead->memoryCall(cpu.z80sp, psMemRead); cpu.z80BC |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { cpu.z80BC = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); cpu.z80BC |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80BC = cpu.z80Base[cpu.z80sp]; cpu.z80BC |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } cpu.z80sp += 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ break; } case 0xc2: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_ZERO)) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xc3: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ break; } case 0xc4: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_ZERO)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xc5: { sdwCyclesRemaining -= 11; cpu.z80sp -= 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80BC & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80BC >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80BC; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80BC >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80BC; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80BC >> 8); } break; } case 0xc6: { sdwCyclesRemaining -= 7; bTemp = *pbPC++; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A += bTemp; break; } case 0xc7: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x00; /* Normalize the address */ break; } case 0xc8: { sdwCyclesRemaining -= 5; if (cpu.z80F & Z80_FLAG_ZERO) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xc9: { sdwCyclesRemaining -= 10; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ break; } case 0xca: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_ZERO) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xcb: { CBHandler(); break; } case 0xcc: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_ZERO) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xcd: { sdwCyclesRemaining -= 17; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ break; } case 0xce: { sdwCyclesRemaining -= 7; bTemp = *pbPC++ + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbAddAdcTable[((UINT32) cpu.z80A << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A += bTemp; break; } case 0xcf: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x08; /* Normalize the address */ break; } case 0xd0: { sdwCyclesRemaining -= 5; if (!(cpu.z80F & Z80_FLAG_CARRY)) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xd1: { sdwCyclesRemaining -= 10; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80DE = psMemRead->memoryCall(cpu.z80sp, psMemRead); cpu.z80DE |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { cpu.z80DE = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); cpu.z80DE |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80DE = cpu.z80Base[cpu.z80sp]; cpu.z80DE |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } cpu.z80sp += 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ break; } case 0xd2: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_CARRY)) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xd3: { sdwCyclesRemaining -= 11; dwTemp = *pbPC++; psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */ while (psIoWrite->lowIoAddr != 0xffff) { if ((dwTemp >= psIoWrite->lowIoAddr) && (dwTemp <= psIoWrite->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; psIoWrite->IOCall(dwTemp, cpu.z80A, psIoWrite); psIoWrite = NULL; break; } ++psIoWrite; } break; } case 0xd4: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_CARRY)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xd5: { sdwCyclesRemaining -= 11; cpu.z80sp -= 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80DE & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80DE >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80DE; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80DE >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80DE; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80DE >> 8); } break; } case 0xd6: { sdwCyclesRemaining -= 7; bTemp = *pbPC++; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp]; cpu.z80A -= bTemp; break; } case 0xd7: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x10; /* Normalize the address */ break; } case 0xd8: { sdwCyclesRemaining -= 5; if (cpu.z80F & Z80_FLAG_CARRY) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xd9: { sdwCyclesRemaining -= 4; dwTemp = cpu.z80DE; cpu.z80DE = cpu.z80deprime; cpu.z80deprime = dwTemp; dwTemp = cpu.z80BC; cpu.z80BC = cpu.z80bcprime; cpu.z80bcprime = dwTemp; dwTemp = cpu.z80HL; cpu.z80HL = cpu.z80hlprime; cpu.z80hlprime = dwTemp; break; } case 0xda: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_CARRY) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xdb: { sdwCyclesRemaining -= 11; dwTemp = *pbPC++; psIoRead = cpu.z80IoRead; /* Beginning of our handler */ while (psIoRead->lowIoAddr != 0xffff) { if ((dwTemp >= psIoRead->lowIoAddr) && (dwTemp <= psIoRead->highIoAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; cpu.z80A = psIoRead->IOCall(dwTemp, psIoRead); psIoRead = NULL; break; } ++psIoRead; } if (psIoRead) { cpu.z80A = 0xff; /* Unclaimed I/O read */ } break; } case 0xdc: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_CARRY) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xdd: { DDHandler(); break; } case 0xde: { sdwCyclesRemaining -= 7; bTemp = *pbPC++ + (cpu.z80F & Z80_FLAG_CARRY); cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)]; cpu.z80A = cpu.z80A - bTemp; break; } case 0xdf: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x18; /* Normalize the address */ break; } case 0xe0: { sdwCyclesRemaining -= 5; if (!(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY)) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xe1: { sdwCyclesRemaining -= 10; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80HL = psMemRead->memoryCall(cpu.z80sp, psMemRead); cpu.z80HL |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { cpu.z80HL = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); cpu.z80HL |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80HL = cpu.z80Base[cpu.z80sp]; cpu.z80HL |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } cpu.z80sp += 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ break; } case 0xe2: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY)) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xe3: { sdwCyclesRemaining -= 19; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { dwAddr = psMemRead->memoryCall(cpu.z80sp, psMemRead); dwAddr |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { dwAddr = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); dwAddr |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { dwAddr = cpu.z80Base[cpu.z80sp]; dwAddr |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80HL & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80HL >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80HL; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80HL >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80HL; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80HL >> 8); } cpu.z80HL = dwAddr; break; } case 0xe4: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xe5: { sdwCyclesRemaining -= 11; cpu.z80sp -= 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80HL & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80HL >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80HL; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80HL >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80HL; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80HL >> 8); } break; } case 0xe6: { sdwCyclesRemaining -= 7; cpu.z80A &= *pbPC++; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostANDFlags[cpu.z80A]; break; } case 0xe7: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x20; /* Normalize the address */ break; } case 0xe8: { sdwCyclesRemaining -= 5; if (cpu.z80F & Z80_FLAG_OVERFLOW_PARITY) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xe9: { sdwCyclesRemaining -= 4; pbPC = cpu.z80Base + cpu.z80HL; break; } case 0xea: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_OVERFLOW_PARITY) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xeb: { sdwCyclesRemaining -= 4; dwAddr = cpu.z80DE; cpu.z80DE = cpu.z80HL; cpu.z80HL = dwAddr; break; } case 0xec: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_OVERFLOW_PARITY) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xed: { EDHandler(); break; } case 0xee: { sdwCyclesRemaining -= 7; cpu.z80A ^= *pbPC++; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xef: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x28; /* Normalize the address */ break; } case 0xf0: { sdwCyclesRemaining -= 5; if (!(cpu.z80F & Z80_FLAG_SIGN)) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xf1: { sdwCyclesRemaining -= 10; psMemRead = cpu.z80MemRead; /* Beginning of our handler */ while (psMemRead->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemRead->lowAddr) && (cpu.z80sp <= psMemRead->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemRead->memoryCall) { cpu.z80AF = psMemRead->memoryCall(cpu.z80sp, psMemRead); cpu.z80AF |= (UINT32) ((UINT32) psMemRead->memoryCall(cpu.z80sp + 1, psMemRead) << 8); } else { cpu.z80AF = *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr)); cpu.z80AF |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (cpu.z80sp - psMemRead->lowAddr + 1)) << 8); } psMemRead = NULL; break; } ++psMemRead; } if (psMemRead) { cpu.z80AF = cpu.z80Base[cpu.z80sp]; cpu.z80AF |= (UINT32) ((UINT32) cpu.z80Base[cpu.z80sp + 1] << 8); } cpu.z80sp += 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ break; } case 0xf2: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_SIGN)) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xf3: { sdwCyclesRemaining -= 4; cpu.z80iff &= (~IFF1); break; } case 0xf4: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (!(cpu.z80F & Z80_FLAG_SIGN)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xf5: { sdwCyclesRemaining -= 11; cpu.z80sp -= 2; pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */ psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */ while (psMemWrite->lowAddr != 0xffffffff) { if ((cpu.z80sp >= psMemWrite->lowAddr) && (cpu.z80sp <= psMemWrite->highAddr)) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; if (psMemWrite->memoryCall) { psMemWrite->memoryCall(cpu.z80sp, (cpu.z80AF & 0xff), psMemWrite); psMemWrite->memoryCall(cpu.z80sp + 1, (cpu.z80AF >> 8), psMemWrite); } else { *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr)) = cpu.z80AF; *((UINT8 *) psMemWrite->pUserArea + (cpu.z80sp - psMemWrite->lowAddr) + 1) = cpu.z80AF >> 8; } psMemWrite = NULL; break; } ++psMemWrite; } if (psMemWrite) { cpu.z80Base[cpu.z80sp] = (UINT8) cpu.z80AF; cpu.z80Base[cpu.z80sp + 1] = (UINT8) ((UINT32) cpu.z80AF >> 8); } break; } case 0xf6: { sdwCyclesRemaining -= 7; cpu.z80A |= *pbPC++; cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN); cpu.z80F |= bPostORFlags[cpu.z80A]; break; } case 0xf7: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x30; /* Normalize the address */ break; } case 0xf8: { sdwCyclesRemaining -= 5; if (cpu.z80F & Z80_FLAG_SIGN) { dwElapsedTicks += 6; pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */ dwAddr = *pbSP++; /* Pop LSB */ dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */ cpu.z80sp += 2; /* Pop the word off */ pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */ } break; } case 0xf9: { sdwCyclesRemaining -= 6; cpu.z80sp = cpu.z80HL; break; } case 0xfa: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_SIGN) { pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xfb: { sdwCyclesRemaining -= 4; cpu.z80iff |= IFF1; break; } case 0xfc: { sdwCyclesRemaining -= 10; dwAddr = *pbPC++; /* Get LSB first */ dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */ if (cpu.z80F & Z80_FLAG_SIGN) { cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* MSB */ *pbSP = (UINT8) cpu.z80pc; /* LSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + dwAddr; /* Normalize the address */ } break; } case 0xfd: { FDHandler(); break; } case 0xfe: { sdwCyclesRemaining -= 7; cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) | pbSubSbcTable[((UINT32) cpu.z80A << 8) | *pbPC++]; break; } case 0xff: { sdwCyclesRemaining -= 11; cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ pbPC = cpu.z80Base + 0x38; /* Normalize the address */ break; } } } dwElapsedTicks += (dwOriginalCycles - sdwCyclesRemaining); cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base; return(dwReturnCode); /* Indicate success */ } /* Get mz80's context */ void mz80GetContext(void *pData) { memcpy(pData, &cpu, sizeof(CONTEXTMZ80)); } /* Set mz80's context */ void mz80SetContext(void *pData) { memcpy(&cpu, pData, sizeof(CONTEXTMZ80)); } /* Get mz80's context size */ UINT32 mz80GetContextSize(void) { return(sizeof(CONTEXTMZ80)); } /* This will return the elapsed ticks */ UINT32 mz80GetElapsedTicks(UINT32 dwClear) { UINT32 dwTemp = dwElapsedTicks; if (dwClear) { dwElapsedTicks = 0; } return(dwTemp); } /* Releases mz80 from its current timeslice */ void mz80ReleaseTimeslice(void) { dwOriginalCycles -= sdwCyclesRemaining; sdwCyclesRemaining = 0; } /* This routine is mz80's reset handler */ void mz80reset(void) { cpu.z80halted = 0; cpu.z80AF = 0; cpu.z80F = Z80_FLAG_ZERO; cpu.z80BC = 0; cpu.z80DE = 0; cpu.z80HL = 0; cpu.z80afprime = 0; cpu.z80bcprime = 0; cpu.z80deprime = 0; cpu.z80hlprime = 0; cpu.z80i = 0; cpu.z80r = 0; cpu.z80IX = 0xffff; /* Yes, this is intentional */ cpu.z80IY = 0xffff; /* Yes, this is intentional */ cpu.z80pc = 0; cpu.z80sp = 0; cpu.z80interruptMode = 0; cpu.z80intAddr = 0x38; cpu.z80nmiAddr = 0x66; } /* Interrupt handler */ UINT32 mz80int(UINT32 dwLowAddr) { cpu.z80halted = 0; if (0 == (cpu.z80iff & IFF1)) return(0xffffffff); cpu.z80iff &= ~(IFF1 | IFF2); pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ if (2 == cpu.z80interruptMode) { cpu.z80pc = ((UINT16) cpu.z80i << 8) | (dwLowAddr & 0xff); cpu.z80pc = ((UINT16) cpu.z80Base[cpu.z80pc + 1] << 8) | (cpu.z80Base[cpu.z80pc]); } else { cpu.z80pc = cpu.z80intAddr; } pbPC = cpu.z80Base + cpu.z80pc; /* Normalize the address */ return(0); } /* NMI Handler */ UINT32 mz80nmi(void) { cpu.z80halted = 0; pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */ *pbSP-- = cpu.z80pc >> 8; /* LSB */ *pbSP = (UINT8) cpu.z80pc; /* MSB */ cpu.z80sp -= 2; /* Back our stack up */ cpu.z80pc = cpu.z80nmiAddr; /* Our NMI */ return(0); } /* Initialize MZ80 for action */ void mz80init(void) { UINT32 dwLoop; UINT8 *pbTempPtr; UINT8 *pbTempPtr2; UINT8 bNewAdd; UINT8 bNewSub; UINT8 bFlag; UINT8 bLow; UINT8 bHigh; UINT8 bCarry; if (NULL == pbAddAdcTable) { pbAddAdcTable = malloc(256*256*2); if (NULL == pbAddAdcTable) { return; } pbTempPtr = pbAddAdcTable; pbSubSbcTable = malloc(256*256*2); if (NULL == pbSubSbcTable) { return; } pbTempPtr2 = pbSubSbcTable; for (dwLoop = 0; dwLoop < (256*256*2); dwLoop++) { bLow = dwLoop & 0xff; bHigh = (dwLoop >> 8) & 0xff; bCarry = (dwLoop >> 16); bFlag = 0; bNewAdd = bHigh + bLow + bCarry; if (0 == bNewAdd) { bFlag |= Z80_FLAG_ZERO; } else { bFlag = bNewAdd & 0x80; /* Sign flag */ } if (((UINT32) bLow + (UINT32) bHigh + (UINT32) bCarry) >= 0x100) { bFlag |= Z80_FLAG_CARRY; } if ( ((bLow ^ bHigh ^ 0x80) & (bLow ^ (bNewAdd & 0x80))) & 0x80) { bFlag |= Z80_FLAG_OVERFLOW_PARITY; } if (((bLow & 0x0f) + (bHigh & 0x0f) + bCarry) >= 0x10) { bFlag |= Z80_FLAG_HALF_CARRY; } *pbTempPtr++ = bFlag; /* Store our new flag */ // Now do subtract - Zero bFlag = Z80_FLAG_NEGATIVE; bNewSub = bHigh - bLow - bCarry; if (0 == bNewSub) { bFlag |= Z80_FLAG_ZERO; } else { bFlag |= bNewSub & 0x80; /* Sign flag */ } if ( ((INT32) bHigh - (INT32) bLow - (INT32) bCarry) < 0) { bFlag |= Z80_FLAG_CARRY; } if ( ((INT32) (bHigh & 0xf) - (INT32) (bLow & 0x0f) - (INT32) bCarry) < 0) { bFlag |= Z80_FLAG_HALF_CARRY; } if ( ((bLow ^ bHigh) & (bHigh ^ bNewSub) & 0x80) ) { bFlag |= Z80_FLAG_OVERFLOW_PARITY; } *pbTempPtr2++ = bFlag; /* Store our sub flag */ } } } /* Shut down MZ80 */ void mz80shutdown(void) { } dgen-sdl-1.23/tobin.c 644 1750 1750 1513 7027317556 7550 // A little utility to convert SMDs to BINs #include #include // No C header for the function, so I have to prototype them int load_rom_into(char *name, unsigned char *into); int main(int argc, char *argv[]) { int size; FILE *out; unsigned char *rom; if(argc < 3) { printf("Usage: %s from.smd to.bin\n", argv[0]); return 1; } // Get size, so we can malloc it size = load_rom_into(argv[1], NULL); if(size == -1) { fprintf(stderr, "Couldn't open source rom %s!\n", argv[1]); return 1; } rom = malloc(size); // Get the rom load_rom_into(argv[1], rom); // Write it to disk if(!(out = fopen(argv[2], "w"))) { fprintf(stderr, "Couldn't write destination rom %s!\n", argv[2]); return 1; } fwrite(rom, 1, size, out); fclose(out); free(rom); // That was easy. ;) return 0; } dgen-sdl-1.23/md-phil.cpp 644 1750 1750 10642 7245114273 10343 // Ripped Snes9X joystick code and made it Genesis friendly, with a few // slight modifications. [PKH] #include #include #include #include #include #include #include "md.h" #include "md-phil.h" // Default setup for Gravis GamePad Pro 10 button controllers. // Yellow ... A // Green .... C // Red ...... A // Blue ..... B // L1 ....... Y // R1 ....... Z // L2 ....... X // R2 ....... X // Start .... START :) // Select ... MODE // Mappings are configurable via dgenrc. Mappings are done from 0-16 // Standard 2 button joysticks will only have buttons 0 and 1. [PKH] extern int js_map_button [2][16]; #ifdef LINUX_JOYSTICK_SUPPORT #warning USING LINUX JOYSTICK #include int joypads[2] = {0}; int js_fd[2] = {-1, -1}; char *js_device [2] = {"/dev/js0", "/dev/js1"}; void md::init_joysticks() { #ifdef JSIOCGVERSION int version; unsigned char axes, buttons; if ((js_fd [0] = open (js_device [0], O_RDONLY | O_NONBLOCK)) < 0) { perror (js_device [0]); return; } if (ioctl (js_fd [0], JSIOCGVERSION, &version)) { puts("joystick: You need at least driver version 1.0 for joystick support"); close (js_fd [0]); return; } js_fd [1] = open (js_device [1], O_RDONLY | O_NONBLOCK); #ifdef JSIOCGNAME char name [130]; bzero (name, 128); if (ioctl (js_fd [0], JSIOCGNAME(128), name) > 0) { printf ("Using %s (%s) as pad1", name, js_device [0]); if (js_fd [1] > 0) { ioctl (js_fd [1], JSIOCGNAME(128), name); printf ("and %s (%s) as pad2", name, js_device [1]); } } else #endif // JSIOCGNAME { ioctl (js_fd [0], JSIOCGAXES, &axes); ioctl (js_fd [0], JSIOCGBUTTONS, &buttons); printf ("Using %d-axis %d-button joystick (%s) as pad1", axes, buttons, js_device [0]); if (js_fd [1] > 0) { ioctl (js_fd [0], JSIOCGAXES, &axes); ioctl (js_fd [0], JSIOCGBUTTONS, &buttons); printf (" and %d-axis %d-button (%s) as pad2", axes, buttons, js_device [1]); } } puts ("."); #endif // JSIOCGVERSION } void md::read_joysticks() { #ifdef JSIOCGVERSION struct js_event js_ev; int i; for (i = 0; i < 2 && js_fd [i] >= 0; i++) { while (read (js_fd[i], &js_ev, sizeof (struct js_event)) == sizeof (struct js_event) ) { switch (js_ev.type & ~JS_EVENT_INIT) { case JS_EVENT_AXIS: if (js_ev.number == 0) { if(js_ev.value < -16384) { pad[i] &= ~MD_LEFT_MASK; pad[i] |= MD_RIGHT_MASK; break; } if (js_ev.value > 16384) { pad[i] |= MD_LEFT_MASK; pad[i] &= ~MD_RIGHT_MASK; break; } pad[i] |= MD_LEFT_MASK; pad[i] |= MD_RIGHT_MASK; break; } if (js_ev.number == 1) { if (js_ev.value < -16384) { pad[i] &= ~MD_UP_MASK; pad[i] |= MD_DOWN_MASK; break; } if (js_ev.value > 16384) { pad[i] |= MD_UP_MASK; pad[i] &= ~MD_DOWN_MASK; break; } pad[i] |= MD_UP_MASK; pad[i] |= MD_DOWN_MASK; break; } break; case JS_EVENT_BUTTON: if (js_ev.number > 15) break; if (js_ev.value) pad[i] &= ~js_map_button [i][js_ev.number]; else pad[i] |= js_map_button [i][js_ev.number]; break; } } } #endif // JSIOCGVERSION } #elif defined(SDL_JOYSTICK_SUPPORT) #warning USING SDL JOYSTICK #include #include static SDL_Joystick *js_handle[2] = { NULL, NULL }; void md::init_joysticks() { // Initialize the joystick support // Thanks to Cameron Moore if(SDL_Init(SDL_INIT_JOYSTICK) < 0) { fprintf(stderr, "joystick: Unable to initialize joystick system\n"); return; } // Open the first couple of joysticks, if possible js_handle[0] = SDL_JoystickOpen(0); js_handle[1] = SDL_JoystickOpen(1); // If neither opened, quit if(!(js_handle[0] || js_handle[1])) { fprintf(stderr, "joystick: Unable to open any joysticks\n"); return; } // Print the joystick names printf("Using "); if(js_handle[0]) printf("%s (#0) as pad1 ", SDL_JoystickName(0)); if(js_handle[0] && js_handle[1]) printf("and "); if(js_handle[1]) printf("%s (#1) as pad2 ", SDL_JoystickName(1)); printf("\n"); // Enable joystick events SDL_JoystickEventState(SDL_ENABLE); } // This does nothing; SDL joystick handling is in the main event loop in // sdl/sdl.cpp void md::read_joysticks() { //empty } #endif dgen-sdl-1.23/sample.dgenrc 644 1750 1750 12712 7320144366 10752 # This is a sample .dgenrc file # It simply sets everything to their default values # Lines that BEGIN with a hash (#) (i.e. NOTHING before it) are comments. # Also, everything after the "field = value" is ignored (but don't count on it) # Note that your own RC file doesn't need to include every field like this # one does, any ones you exclude simply have their compiled-in default values. # Also, you can have multiple RC files, and use the -r option to dgen # to pick the rc you want to load. # Fields beginning with "key_" take key names. The valid key names are listed # in the dgenrc(5) manpage. # Fields beginning with "bool_" are boolean, i.e. they take a true or false # value: # "true", "yes", any number except 0: true # "false", "no", "0" : false # Fields beginning with "int_" take a _positive_ integer. Simple enough, huh? ;) # The syntax and fields of this file are documented in a bit more detail in the # dgenrc(5) manpage. # These are the controls for pad 1 key_pad1_up = up key_pad1_down = down key_pad1_left = left key_pad1_right = right key_pad1_a = a key_pad1_b = s key_pad1_c = d key_pad1_x = q key_pad1_y = w key_pad1_z = e key_pad1_mode = backspace key_pad1_start = return # The same for pad 2 # Yes, I KNOW the default player 2 keys are awful. Pick your own! key_pad2_up = kp_up key_pad2_down = kp_down key_pad2_left = kp_left key_pad2_right = kp_right key_pad2_a = delete key_pad2_b = end key_pad2_c = page_down key_pad2_x = insert key_pad2_y = home key_pad2_z = page_up key_pad2_mode = kp_plus key_pad2_start = kp_enter # Fix checksum, needed by some games with Game Genie codes key_fix_checksum = f1 # Quit dgen key_quit = escape # Toggle split screen and crap-tv key_splitscreen_toggle = f4 key_craptv_toggle = f5 # Screenshot key_screenshot = f12 # Reset Genesis key_reset = tab # Toggle fullscreen mode key_fullscreen_toggle = alt-enter # Use this to toggle which CPU core to use, no need to reset! :) # If you don't have multiple CPU cores, it won't do anything! key_cpu_toggle = f11 # This pauses emulation :) key_stop = z # Pick save slot key_slot_0 = 0 key_slot_1 = 1 key_slot_2 = 2 key_slot_3 = 3 key_slot_4 = 4 key_slot_5 = 5 key_slot_6 = 6 key_slot_7 = 7 key_slot_8 = 8 key_slot_9 = 9 # Save/load game to current slot key_save = f2 key_load = f3 # This sets whether split-screen and crap-tv should be enabled on startup. bool_splitscreen_startup = no # There are now multiple CTV effects to try. Pick your favorite: # off - No CTV # blur - Blur bitmap (this is the CTV from older versions) # scanline - Attenuate every other scanline, by Phillip K. Hornung # interlace - Unstable crappy television (I had one that looked like this ;), by me! ctv_craptv_startup = off # These decide whether DGen should automatically load slot 0 on startup, # and/or autosave to slot 0 on exit. bool_autoload = no bool_autosave = no # Skip frames to keep time? (faster, but can make things look bad) # This doesn't matter if you have sound enabled, since the sound code has its # own frameskipping bool_frameskip = yes # Show cartridge header info at startup, like Snes9X? Causes a 3-second pause, # but might be interesting to hackers or other curious people (like me :) bool_show_carthead = no # Sound? bool_sound = yes # The sound rate to use. int_soundrate = 22050 # Leave this true for 16-bit sound, but if you're unfortunate enough to have # an old 8-bit card make it false. bool_16bit = yes # Number of sound segments for buffering. Lower values yield faster # speed, and less latency in controls and sound, but at the cost of CPU # Values can be 4, 8, 16, or 32 (frames) int_soundsegs = 8 # This is how many microseconds DGen should sleep every frame. Even little # amounts can decrease CPU overhead significantly, and the default of 20 # doesn't hurt performance terribly. Of course, set it to 0 if you don't # mind DGen eating all your CPU (like me ;) int_nice = 0 # Run fullscreen? bool_fullscreen = no # If you want to increase the size of the window, increase this value. # It currently must be a whole number. int_scale = 1 # Use a joystick? bool_joystick = no # Use OpenGL mode? bool_opengl = no # Set these to the resolution you want to run OpenGL mode in. int_opengl_width = 640 int_opengl_height = 480 # These are the joypad mappings for both controllers. Defaults are # tailored for Gravis GamePad Pros. (10 button) Configure the variables: # joypadX_bY, where X is the joypad number (1 or 2) and Y is the # corresponding button. It may take some tweaking to get the values just # right. You can define up to 16 buttons (0-15) and can define Genesis # buttons more than once and can leave them blank. Acceptable identifiers # are: # A, a, B, b, C, c, X, x, Y, y, Z, z, MODE, mode, M, m, START, start, S, s # NOTE: For now, you have to uncomment the buttons you are using, or the # default mappings will be used. You will get warnings about invalid RC # lines if you don't compile joystick support in. [PKH] # Joypad 1 #joypad1_b0 = A #joypad1_b1 = C #joypad1_b2 = A #joypad1_b3 = B #joypad1_b4 = Y #joypad1_b5 = Z #joypad1_b6 = X #joypad1_b7 = X #joypad1_b8 = START #joypad1_b9 = MODE #joypad1_b10 = #joypad1_b11 = #joypad1_b12 = #joypad1_b13 = #joypad1_b14 = #joypad1_b15 = # Joypad 2 #joypad2_b0 = A #joypad2_b1 = C #joypad2_b2 = A #joypad2_b3 = B #joypad2_b4 = Y #joypad2_b5 = Z #joypad2_b6 = X #joypad2_b7 = X #joypad2_b8 = START #joypad2_b9 = MODE #joypad2_b10 = #joypad2_b11 = #joypad2_b12 = #joypad2_b13 = #joypad2_b14 = #joypad2_b15 = dgen-sdl-1.23/dgen.1 644 1750 1750 5700 7245042747 7271 .Dd February 21, 2001 .Dt DGEN 1 .Sh NAME .Nm dgen .Nd Sega Genesis/MegaDrive emulator .Sh SYNOPSIS .Nm dgen .Op Fl PRfhjv .Op Fl D Ar DEMONAME .Op Fl d Ar DEMONAME .Op Fl n Ar USEC .Op Fl p Ar CODE,CODE... .Op Fl r Ar RCFILE .Op Fl X Ar XFACT .Op Fl Y Ar YFACT .Op Fl S Ar FACT .Op Fl G Ar XxY .Op Fl s Ar SLOT .Ar romname .Sh DESCRIPTION The rom image in the file .Ar romname is executed, as emulated on a Sega Genesis or MegaDrive running in 60Hz NTSC mode (unless the .Fl P option is specified, in which case 50Hz PAL mode is used). .Ar romname should be in raw binary or SMD format, and may be compressed with .Xr gzip 1 , .Xr zip 1 , or .Xr bzip2 1 . .Pp The options are as follows: .Bl -tag -width Fl .It Fl P Emulate 50Hz PAL mode (as used in European models of the MegaDrive). .It Fl R If running with root priviledges, set priority to -20, so no other processes interrupt (including the X server, which can be a Bad Thing). .It Fl f Run fullscreen, if possible. .It Fl h Show a brief synopsis of all options. .It Fl j Use joystick, if running on Linux with joystick drivers >= 1.0. .It Fl v Show the version number, and exit. .It Fl D Ar DEMONAME Play back a demo recorded with the .Fl d option. .It Fl d Ar DEMONAME Record a demo of the program running, which can be later replayed with the .Fl D switch. .It Fl n Ar USEC Sleep for a number of microseconds after every frame, to give time to other processes. .It Fl p Ar CODE,CODE... Modify the ROM image in memory, using Game Genie or Hex style codes. Game Genie codes are of the form .Ar ABCD-EFGH and Hex codes are in the form .Ar 123456:ABCD . To specify more than one code, separate them with commas (do .Ar not use spaces). .It Fl r Ar RCFILE Parse another rc file after $HOME/.dgen/dgenrc. Values in the specified file override those in the preceding files. .It Fl X Ar XFACT Scale the window XFACT times in the X direction. XFACT must be a positive integer. .It Fl Y Ar YFACT Scale the window YFACT times in the Y direction. YFACT must be a positive integer. .It Fl S Ar FACT Scale the window FACT times in both directions. FACT must be a positive integer. .It Fl G Ar XxY Use OpenGL to render the screen, if available. The parameter is the width and height of the desired screen (e.g. 640x480, 800x600, etc.) .It Fl s Ar SLOT Load the saved state from the given slot at startup (0-9) .El .Sh FILES .Bl -tag -width $HOME/.dgen/dgen/saves/* -compact .It Pa $HOME/.dgen/dgenrc Contains user settings for the emulator. .It Pa $HOME/.dgen/saves/* Save states generated by the emulator. .It Pa $HOME/.dgen/ram/* Battery-backup RAM images, generated by the emulator for ROMs with save RAM. .El .Sh SEE ALSO .Xr gzip 1 , .Xr bzip2 1 , .Xr zip 1 , .Xr dgenrc 5 .Sh AUTHORS This manual page was written by .An Joe Groff Aq joe@pknet.com . .Sh BUGS PAL mode does not work very well yet. Numerous buffer overruns (think twice before making dgen setuid-root). .Pp Send any bugs you find (and fixes too, please :) to .An Joe Groff Aq joe@pknet.com . dgen-sdl-1.23/dgenrc.5 644 1750 1750 15637 7320165310 7636 .Dd February 21, 2001 .Dt DGENRC 5 .Os .Sh NAME .Nm dgenrc .Nd file containing settings for .Xr dgen 1 .Sh SYNOPSIS $HOME/.dgen/dgenrc .Sh DESCRIPTION The file .Pa $HOME/.dgen/dgenrc is parsed by .Xr dgen 1 when the emuator is started. It is used to set controller keys, as well as other characteristics of the emulation. The contents of this file may be overriden with the contents of another similarly-formatted file, via the .Fl r commandline switch. .Sh FILE FORMAT Each rc file consists of an unlimited number of lines, which each have the format 'fieldname = value'. A line may also be a comment, if it begins with the hash mark (#) character. .Pp Each .Ar fieldname is prepended by a name, which identifies the type of this field: .Bl -tag -width bool_* .It Ar key_* A key value. May be set to a key identifier listed in the .Sx KEY INDENTIFIERS section below. .It Ar bool_* A boolean value. "false", "no", and "0" values are taken as false, while "true", "yes", and any number except 0 are taken as true. .It Ar int_* An integer value, greater than or equal to 0. .El .Pp Some fields take special value sets, which are addressed in their respective sections. None of the field names or values are case-sensitive. .Pp The fields fall under a few basic groups. They are listed below, with their default values in brackets ([]): .Sh CONTROLLERS .Bl -tag -width xxxx .It key_pad1_up [up] .It key_pad1_down [down] .It key_pad1_left [left] .It key_pad1_right [right] .It key_pad1_a [a] .It key_pad1_b [s] .It key_pad1_c [d] .It key_pad1_x [q] .It key_pad1_y [w] .It key_pad1_z [e] .It key_pad1_mode [backspace] .It key_pad1_start [return] Map keys to the first Genesis controller. Each of these fields has a corresponding "key_pad2" field, to map to the second controller. .It bool_joystick [false] Use joysticks to emulate the controllers. Note that the keyboard keys will still work if this value is set. This field is only available if you have joystick support enabled. .It joypadX_bY Maps button number Y, on joystick X to a Genesis controller button. Valid button values are "a", "b", "c", "x", "y", "z", "mode", and "start". Joystick 1 will always emulate controller 1, and joystick 2 will always emulate controller 2. .El .Sh AUDIO .Bl -tag -width xxxx .It bool_sound [true] Enable the sound subsystem. .It int_soundrate [22050] Sound frequency to play at, in hertz (Hz). .It bool_16bit [true] Use 16-bit sound. If this is false, sound will be condensed to 8-bit (which causes a speed penalty). .It int_soundsegs [8] Number of sound segments to use for sound buffering. Choosing a lower value will lower the sound latency, but may cause performance to hiccup if set too low. Should be a power of two from 4 to 32. .El .Sh VIDEO .Bl -tag -width xxxx .It bool_opengl [false] Use the OpenGL renderer, if it is available. .It int_opengl_width [640] The width of the OpenGL window to use. .It int_opengl_height [480] The height of the OpenGL window to use. .It bool_fullscreen [false] Try to run fullscreen, if possible. .It int_scale [1] Amount by which to scale the window from the default 320x240 resolution. This does not affect the OpenGL renderer; it only has effect if the software renderer is in use. .It key_fullscreen_toggle [alt-enter] Key to toggle fullscreen mode (this may do nothing if SDL doesn't support fullscreen toggling on your platform.) .El .Sh SAVE STATES .Bl -tag -width xxxx .It key_slot_X [X] Sets the current save-state slot to number X. .It key_save [f2] Saves state to the current slot. .It key_load [f3] Loads state from the current slot. .El .Sh MISCELLANEOUS KEYS .Bl -tag -width xxxx .It key_fix_checksum [f1] Fixes the checksum value. Some older games will freeze with a red screen if the ROM has been hacked or modified with Game Genie codes. If it does, pressing this, and resetting should fix the problem. .It key_quit [escape] Exit DGen. .It key_craptv_toggle [f5] Toggles Crap-TV image filters. So far, these filters are only available if DGen was compiled with the x86 assembly routines. .It key_reset [tab] Restart the Genesis emulation. .It key_cpu_toggle [f11] Switch CPU emulators. The x86 assembly CPU emulator StarScream is fast, but has glitches which affect a few games. Switching to the slower Musashi core will fix these problems, at a speed penalty. .It key_stop [z] Pause emulation, so you can concentrate on real life for a few seconds. :) .It key_screenshot [f12] Take a screenshot. .El .Sh PREFERENCES .Bl -tag -width xxxx .It bool_autoload [false] Automatically load the saved state from slot 0 when DGen starts. .It bool_autosave [false] Automatically save the saved state to slot 0 upon exit. Setting both of these fields true, you can exit DGen, and automatically start a game where you left off when you start it again. .It bool_frameskip [true] Automatically skip frames, when it is necessary to maintain proper emulation speed. This has no effect if sound is enabled, as the sound loop skips frames automatically to maintain constant sound speed. .It bool_fullscreen [false] Run in fullscreen mode, if it is available. .It int_scale [1] Amount by which to scale the window. Setting this to 2 will double the dimensions of the window, 3 will triple it, and so on. It must be a positive integer. .It bool_opengl [false] Use OpenGL mode to render the screen, if available. .It int_opengl_width [640] Width of the OpenGL resolution to use. .It int_opengl_height [480] Height of the OpenGL resolution to use. .It int_nice [0] If set to a non-zero value, DGen will call .Xr usleep 3 with the specified parameter after rendering each frame. This will slow the program down (if it is running too fast on your computer), and allow the operating system to reclaim some CPU time. .El .Sh EXAMPLES See the file "sample.dgenrc" in the DGen/SDL distribution. .Sh KEY IDENTIFIERS A key identifier can have the prefixes "shift-", "ctrl-", "alt-" and "meta-", or any combination thereof, to require that the specified modifier be pressed in combination with the key. For example, the identifier "alt-enter" would correspond to holding down the Alt key while pressing Enter. The numbers "0" through "9" ("kp_0" through "kp_9" for the numeric keypad), letters "A" through "Z", and function keys "F1" through "F12" map to their key equivalents. In addition, the following identifiers map to their similarly-labeled key counterparts. Identifiers on the same line map to the same key: .Bd -literal -offset indent escape backspace tab capslock caps_lock lshift shift_l rshift shift_r lctrl ctrl_l lmeta meta_l lalt alt_l ralt alt_r rmeta meta_r rctrl ctrl_r return enter space scrollock scroll_lock numlock num_lock insert home page_up pageup delete end page_down pagedown left right up down kp_home kp_up kp_pageup kp_page_up kp_left kp_right kp_end kp_down kp_pagedown kp_page_down kp_insert kp_delete kp_period kp_enter kp_divide kp_minus kp_multiply kp_plus ` ~ - _ = + \ | [ { ] } : ; ' " , < \. > / ? .Sh SEE ALSO .Xr dgen 1 .Sh AUTHORS This manual page was written by .An Joe Groff Aq joe@pknet.com . dgen-sdl-1.23/tobin.1 644 1750 1750 1167 7245055104 7461 .Dd February 21, 2001 .Dt DGEN 1 .Sh NAME .Nm tobin .Nd Convert SMD-format Genesis/Megadrive image to raw (BIN) format .Sh SYNOPSIS .Nm tobin .Ar FROMSMD .Ar TOBIN .Sh DESCRIPTION The ROM image .Ar FROMSMD is converted into a raw image, as seen by the Genesis/MegaDrive console itself. The raw image is written into .Ar TOBIN . Technically, .Ar FROMSMD does not have to be an SMD file; it can be any format dgen(1) can comprehend, such as an image compressed with .Xr gzip 1 , .Xr zip 1 , or .Xr bzip2 1 . .Sh SEE ALSO .Xr dgen 1 .Sh AUTHORS This manual page was written by .An Joe Groff Aq joe@pknet.com . .Sh BUGS None (yet :-) dgen-sdl-1.23/Makefile.asm.am 644 1750 1750 246 7037472025 11060 # Tell how to make assembler files SUFFIXES += .asmu .asm .asm.o: @NASM@ -f @NASM_FMT@ $< .asmu.o: @@CHOP_@ $< > .$< @NASM@ -f @NASM_FMT@ -o $@ .$< @rm -f .$< dgen-sdl-1.23/star/Makefile.in 644 1750 1750 17070 7320414777 11333 # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # DGen/SDL v1.20+ # Automakefile for StarScream # Tell how to make assembler files SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_alias = @build_alias@ build_triplet = @build@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ AWK = @AWK@ CC = @CC@ CHOP_ = @CHOP_@ CPP = @CPP@ CPUDIRS = @CPUDIRS@ CXX = @CXX@ CXXCPP = @CXXCPP@ EXTRAOBJS = @EXTRAOBJS@ INTERFACE = @INTERFACE@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ MUSA = @MUSA@ MZ80 = @MZ80@ NASM = @NASM@ NASM_FMT = @NASM_FMT@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STAR = @STAR@ VERSION = @VERSION@ SUFFIXES = .asmu .asm # Safety net, so all of StarScream is distributed (as per the StarScream # license) EXTRA_DIST = cpudebug.c cpudebug.h star.c starcpu.h stardoc.txt INCLUDES = -I.. noinst_LIBRARIES = libstarcpu.a libstarcpu_a_SOURCES = libstarcpu_a_LIBADD = starcpu.o libstarcpu_a_DEPENDENCIES = starcpu.o EXTRA_libstarcpu_a_SOURCES = star.c DISTCLEANFILES = starcpu.asmu star mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ libstarcpu_a_OBJECTS = AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(libstarcpu_a_SOURCES) $(EXTRA_libstarcpu_a_SOURCES) OBJECTS = $(libstarcpu_a_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .asm .asmu .c .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.asm.am cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps star/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status mostlyclean-noinstLIBRARIES: clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: libstarcpu.a: $(libstarcpu_a_OBJECTS) $(libstarcpu_a_DEPENDENCIES) -rm -f libstarcpu.a $(AR) cru libstarcpu.a $(libstarcpu_a_OBJECTS) $(libstarcpu_a_LIBADD) $(RANLIB) libstarcpu.a tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = star distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done info-am: info: info-am dvi-am: dvi: dvi-am check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am install-exec-am: install-exec: install-exec-am install-data-am: install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am uninstall-am: uninstall: uninstall-am all-am: Makefile $(LIBRARIES) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ mostlyclean-tags mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ mostlyclean-am clean: clean-am distclean-am: distclean-noinstLIBRARIES distclean-compile \ distclean-tags distclean-generic clean-am distclean: distclean-am maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean-compile maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-am .PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile tags mostlyclean-tags distclean-tags \ clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ check-am installcheck-am installcheck install-exec-am install-exec \ install-data-am install-data install-am install uninstall-am uninstall \ all-redirect all-am all installdirs mostlyclean-generic \ distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean distclean maintainer-clean .asm.o: @NASM@ -f @NASM_FMT@ $< .asmu.o: @@CHOP_@ $< > .$< @NASM@ -f @NASM_FMT@ -o $@ .$< @rm -f .$< star: star.c $(CC) -o star star.c starcpu.asmu: star ./star -hog starcpu.asmu # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: dgen-sdl-1.23/star/Makefile.am 644 1750 1750 1035 7320166053 11263 # DGen/SDL v1.20+ # Automakefile for StarScream include $(top_srcdir)/Makefile.asm.am # Safety net, so all of StarScream is distributed (as per the StarScream # license) EXTRA_DIST = cpudebug.c cpudebug.h star.c starcpu.h stardoc.txt INCLUDES += -I.. noinst_LIBRARIES = libstarcpu.a star: star.c $(CC) -o star star.c starcpu.asmu: star ./star -hog starcpu.asmu libstarcpu_a_SOURCES = libstarcpu_a_LIBADD = starcpu.o libstarcpu_a_DEPENDENCIES = starcpu.o EXTRA_libstarcpu_a_SOURCES = star.c DISTCLEANFILES = starcpu.asmu star dgen-sdl-1.23/star/star.c 644 1750 1750 415535 7027345130 10421 /* ** Starscream 680x0 emulation library ** Copyright 1997, 1998, 1999 Neill Corlett ** ** Refer to STARDOC.TXT for terms of use, API reference, and directions on ** how to compile. */ #define STAR_VERSION "0.26a" /***************************************************************************/ /* ** NOTE ** ** All 68020-related variables and functions are currently experimental, and ** unsupported. */ #include #include #include #include /***************************************************************************/ /* ** Register Usage ** -------------- ** ** This is fairly consistent throughout the file. Occasionally, EAX or EDX ** will be used as a scratch register (in some cases the x86 instruction set ** demands this). ** ** EAX: Bit 0 : V flag ** Bit 1-7 : MUST BE ZERO ** Bit 8 : C flag ** Bit 14 : Z flag ** Bit 15 : N flag ** Bit 16-31: undefined ** EBX: Lower 16 bits: Current instruction word or register number ** Upper 16 bits: zero ** ECX: Primary data ** EDX: Primary address ** EBP: Current base offset of PC ** ESI: Current PC, including base offset ** EDI: Cycle counter */ /***************************************************************************/ /* ** 68010 Loop Mode Timing ** ---------------------- ** ** Loop mode is implemented entirely in the DBRA instruction. It will ** detect when it's supposed to be in loop mode, and adjust its timing when ** applicable. ** ** The __loopmode variable controls when loop mode is active. It is set to ** 1 after an eligible loop is completed. It is set to 0 when the loop ** terminates, or when an interrupt / exception occurs. ** ** Loop info byte: ** ** Bits 1-3: Continuation cycles / 2 ** Bits 4-6: Termination cycles / 2 ** Bits 7-0: (Expiration cycles - continuation cycles) / 2 ** (bit 7 wraps around to bit 0) ** ** With the loop info byte in AL: ** To get the continuation cycles: ** and eax,byte 0Eh ** To get the termination cycles: ** shr al,3 ** and eax,byte 0Eh ** To get the continue/expire difference: ** rol al,2 ** and eax,byte 06h ** ** Default = DBh ** (11011011) ** 101 : 101 = 5 2*5 = 10 continuation cycles ** 101 : 101 = 5 2*5 = 10 termination cycles ** 1 1: 11 = 3 2*3 = 6 10+6 = 16 expiration cycles ** ** (10/10/16 corresponds to the normal DBRA timing behavior) */ /***************************************************************************/ /* ** Algorithm for trace checkpoint in s680x0exec: ** ** If the SR trace flag is set { ** Set the trace trickybit. This differentiates us from the out-of-time ** case above. ** Set cycles_leftover = cycles_needed. ** Force a context switch. ** } otherwise { ** Clear the trace trickybit. ** } ** Begin the fetch/decode/execute loop as usual. ** ** ** In selected ret_timing routines: ** ** Subtract usual number of cycles from edi ** If I'm out of time (edi is negative) { ** Jump to execend with SF set, as usual. ** } otherwise (guaranteed at least one more instruction) { ** Jump to the s680x0exec trace checkpoint. ** } ** ** ** Make sure that the group 1 exception handler clears the trace trickybit. ** ** ** Upon reaching execend: ** ** If the trace trickybit is set { ** Set cycles_needed = cycles_leftover. ** Add cycles_needed to edi. ** Generate a trace exception (clearing the SR trace flag in the process). ** Clear the trace trickybit. ** If edi is positive, resume the fetch/decode/execute loop. ** Otherwise, fall through to the usual epilogue code. ** } */ /***************************************************************************/ /* ** Rebasing notes ** -------------- ** ** Cached rebase happens on: ** * JMP, JSR, RTS, RTE, RTR, RTD ** * Exceptions (except hardware interrupts) ** ** Uncached rebase happens on: ** * Entry to s680x0exec() ** * Hardware interrupts ** * Supervisor flag change ** * Cache disable/invalidate (68020+) ** ** I can't think of any good reason why the hardware interrupt case should be ** uncached, except it happens to be convenient. */ typedef unsigned char byte; typedef unsigned short word; typedef unsigned int dword; static int use_stack = -1; static int hog = -1; static int addressbits = -1; static int cputype = -1; static char *sourcename = NULL; /* This counts the number of instruction handling routines. There's not much ** point to it except for curiosity. */ static int routine_counter = 0; /* Misc. constants */ static char *x86ax [5] = {"?", "al" , "ax" , "?", "eax" }; static char *x86bx [5] = {"?", "bl" , "bx" , "?", "ebx" }; static char *x86cx [5] = {"?", "cl" , "cx" , "?", "ecx" }; static char *x86dx [5] = {"?", "dl" , "dx" , "?", "edx" }; static char *sizename[5] = {"?", "byte", "word", "?", "dword"}; static int quickvalue[8] = {8, 1, 2, 3, 4, 5, 6, 7}; static char direction[2] = {'r','l'}; /* Output file where code will be emitted */ static FILE *codefile; /* Line number - used to make temporary labels i.e. "ln1234" */ static int linenum; /* Effective address modes */ enum eamode { dreg, areg, aind, ainc, adec, adsp, axdp, absw, absl, pcdp, pcxd, immd }; /* Loop information (68010) */ static int loop_c_cycles; static int loop_t_cycles; static int loop_x_cycles; static unsigned char loopinfo[0x10000]; /* ** Misc. global variables which are used while generating instruction ** handling routines. Some of these may assume more than one role. */ static enum eamode main_eamode; /* EA mode, usually source */ static enum eamode main_destmode; /* EA mode, destination (for MOVE) */ static int main_size; /* Operand size (1, 2, or 4) */ static int sizedef; /* Size field in instruction word */ static int main_reg; /* Register number */ static int main_cc; /* Condition code (0-F) */ static int main_dr; /* Direction (right or left) */ static int main_ir; /* Immediate or register (for shifts) */ static int main_qv; /* Quick value */ /* Emit a line of code (format string with other junk) */ static void emit(const char *fmt, ...) { va_list a; va_start(a, fmt); if(codefile) { vfprintf(codefile, fmt, a); } else { fprintf(stderr, "Bad news: Tried to emit() to null file\n"); exit(1); } } /* Dump all options. This is delivered to stderr and to the code file. */ static void optiondump(FILE *o, char *prefix) { fprintf(o, "%sCPU type: %d (%d-bit addresses)\n", prefix, cputype, addressbits); fprintf(o, "%sIdentifiers begin with \"%s\"\n", prefix, sourcename); fprintf(o, "%s%s calling conventions\n", prefix, use_stack ? "Stack" : "Register"); fprintf(o, "%sHog mode: %s\n", prefix, hog ? "On" : "Off"); } static void gen_banner(void) { emit("; Generated by STARSCREAM version " STAR_VERSION "\n"); emit("; For assembly by NASM only\n"); emit(";\n"); emit("; Options:\n"); optiondump(codefile, "; * "); emit(";\n"); emit("bits 32\n"); } static void align(int n) { emit("times ($$-$)&%d db 0\n", n - 1); } static void maskaddress(char *reg) { if(addressbits < 32) { emit("and %s,%d\n", reg, (1 << addressbits) - 1); } } static void begin_source_proc(char *fname) { emit("global _%s%s\n", sourcename, fname); emit("global %s%s_\n", sourcename, fname); emit("_%s%s:\n", sourcename, fname); emit("%s%s_:\n", sourcename, fname); } /* Generate variables */ static void gen_variables(void) { emit("section .data\n"); emit("bits 32\n"); emit("global _%scontext\n", sourcename); align(8); emit("_%scontext:\n", sourcename); emit("contextbegin:\n"); /* ** CONTEXTINFO_MEM16 ** CONTEXTINFO_MEM16FC ** ** 16-bit memory interface */ if(cputype <= 68010) { emit("__fetch dd 0\n"); emit("__readbyte dd 0\n"); emit("__readword dd 0\n"); emit("__writebyte dd 0\n"); emit("__writeword dd 0\n"); emit("__s_fetch dd 0\n"); emit("__s_readbyte dd 0\n"); emit("__s_readword dd 0\n"); emit("__s_writebyte dd 0\n"); emit("__s_writeword dd 0\n"); emit("__u_fetch dd 0\n"); emit("__u_readbyte dd 0\n"); emit("__u_readword dd 0\n"); emit("__u_writebyte dd 0\n"); emit("__u_writeword dd 0\n"); if(cputype == 68010) { emit("__f_readbyte dd 0\n"); emit("__f_readword dd 0\n"); emit("__f_writebyte dd 0\n"); emit("__f_writeword dd 0\n"); } /* ** CONTEXTINFO_MEM32 ** ** 32-bit memory interface */ } else { emit("__fetch dd 0\n"); emit("__readbus dd 0\n"); emit("__writebus dd 0\n"); emit("__s_fetch dd 0\n"); emit("__s_readbus dd 0\n"); emit("__s_writebus dd 0\n"); emit("__u_fetch dd 0\n"); emit("__u_readbus dd 0\n"); emit("__u_writebus dd 0\n"); emit("__f_readbus dd 0\n"); emit("__f_writebus dd 0\n"); } /* ** CONTEXTINFO_COMMON ** ** Registers and other info common to all CPU types ** ** It should be noted that on a double fault, bit 0 of both __pc and ** __interrupts will be set to 1. */ if(cputype >= 68000) { emit("__resethandler dd 0\n"); emit("__reg:\n"); emit("__dreg dd 0,0,0,0,0,0,0,0\n"); emit("__areg dd 0,0,0,0,0,0,0\n"); emit("__a7 dd 0\n"); emit("__asp dd 0\n"); emit("__pc dd 0\n"); emit("__odometer dd 0\n"); /* Bit 0 of __interrupts = stopped state */ emit("__interrupts db 0,0,0,0,0,0,0,0\n"); emit("__sr dw 0\n"); } /* ** CONTEXTINFO_68000SPECIFIC */ if(cputype == 68000) { emit("__contextfiller00 dw 0\n"); } /* ** CONTEXTINFO_68010 ** ** Registers used on the 68010 and higher */ if(cputype >= 68010) { emit("__sfc db 0\n"); emit("__dfc db 0\n"); emit("__vbr dd 0\n"); emit("__bkpthandler dd 0\n"); } /* ** CONTEXTINFO_68010SPECIFIC ** ** Registers used only on the 68010 */ if(cputype == 68010) { emit("__loopmode db 0\n"); emit("__contextfiller10 db 0,0,0\n"); } /* ** CONTEXTINFO_68020 ** ** Registers used on the 68020 and higher */ if(cputype >= 68020) { /* ** 68020 stack pointer rules (tentative) ** ** First of all, the 68000/68010 stack pointer behavior has ** not changed: ** ** 1. In supervisor mode, __a7 contains the supervisor stack ** pointer and __asp contains the user stack pointer. ** 2. In user mode, __a7 contains the user stack pointer and ** __asp contains the supervisor stack pointer. ** ** The only difference is that the "supervisor stack pointer" ** can be either ISP or MSP. __xsp contains whichever stack ** pointer is _not_ the current "supervisor stack pointer". ** ** Here's a table summarizing the above rules: ** ** S M | __a7 __asp __xsp ** ----+----------------- ** 0 0 | USP ISP MSP ** 0 1 | USP MSP ISP ** 1 0 | ISP USP MSP ** 1 1 | MSP USP ISP ** ** As usual, whenever SR changes, we have to play Stack ** Pointer Switcheroo: ** ** * If S changes: swap __asp and __a7 (as usual) ** * If M changes: ** - If S=0, swap __xsp and __asp ** - If S=1, swap __xsp and __a7 */ emit("__xsp dd 0\n"); } /* align(4);*/ emit("contextend:\n"); emit("__cycles_needed dd 0\n"); emit("__cycles_leftover dd 0\n"); emit("__fetch_region_start dd 0\n");/* Fetch region cache */ emit("__fetch_region_end dd 0\n"); emit("__xflag db 0\n"); /* ** Format of __execinfo: ** Bit 0: s680x0exec currently running ** Bit 1: PC out of bounds ** Bit 2: Special I/O section ** ** "Special I/O section" is enabled during group 0 exception ** processing, and it means a couple things: ** * Address and bus errors will not be tolerated (the CPU will ** just keel over and die). Therefore, information such as the ** current PC is not relevant. ** * Registers are not necessarily live. Since special I/O ** sections are guaranteed not to cause exceptions, this is not a ** problem. */ emit("__execinfo db 0\n"); emit("__trace_trickybit db 0\n");/* Pending trace exception */ emit("__filler db 0\n"); emit("__io_cycle_counter dd -1\n");/*always -1 when idle*/ emit("__io_fetchbase dd 0\n"); emit("__io_fetchbased_pc dd 0\n"); emit("__access_address dd 0\n"); } /* Prepare to leave into the cold, dark world of compiled C code */ static void airlock_exit(void) { emit("mov [__io_cycle_counter],edi\n"); emit("mov [__io_fetchbase],ebp\n"); emit("mov [__io_fetchbased_pc],esi\n"); emit("push ebx\n"); emit("push eax\n"); } /* Prepare to return to the warm fuzzy world of assembly code ** (where everybody knows your name) */ static void airlock_enter(void) { emit("pop eax\n"); emit("pop ebx\n"); emit("mov edi,[__io_cycle_counter]\n"); emit("mov ebp,[__io_fetchbase]\n"); emit("mov esi,[__io_fetchbased_pc]\n"); } enum { airlock_stacksize = 8 }; static void cache_ccr(void) { emit("mov al,[__sr]\n"); /* read CCR -> AL */ /* ????????000XNZVC */ emit("mov ah,al\n"); /* copy to AH */ /* 000XNZVC000XNZVC */ emit("and ax,0C10h\n"); /* isolate NZ...X */ /* 0000NZ00000X0000 */ emit("shl ah,3\n"); /* put NZ almost where we want it */ /* 0NZ00000000X0000 */ emit("shr al,4\n"); /* shift X flag into bit 0 */ /* 0NZ000000000000X */ emit("mov [__xflag],al\n"); /* store X flag */ /* 0NZ000000000000X al -> xflag */ emit("mov al,[__sr]\n"); /* read CCR -> AL again */ /* 0NZ00000000XNZVC */ emit("and al,3\n"); /* isolate VC */ /* 0NZ00000000000VC */ emit("shr al,1\n"); /* just V */ /* 0NZ000000000000V carry */ emit("adc ah,ah\n"); /* append C to rest of flags */ /* NZ00000C0000000V */ } static void writeback_ccr(void) { emit("shr ah,1\n"); /* C flag -> x86 carry */ /* 0NZ?????0000000V carry */ emit("adc ax,ax\n"); /* append to V flag */ /* NZ?????0000000VC */ emit("and ax,0C003h\n"); /* isolate NZ.......VC */ /* NZ000000000000VC */ emit("or ah,[__xflag]\n"); /* load X flag */ /* NZ00000X000000VC */ emit("ror ah,4\n"); /* now we have XNZ....VC */ /* 000XNZ00000000VC */ emit("or al,ah\n"); /* OR them together */ /* 000XNZ00000XNZVC */ emit("mov [__sr],al\n"); /* store the result */ /* 000XNZ00000XNZVC al -> sr */ } /* ** This will make edi _very_ negative... far enough negative that the ** leftover cycle incorporation at the end of s68000exec() shouldn't be ** enough to make it positive. */ static void force_context_switch(void) { emit("sub edi,[__cycles_needed]\n"); emit("mov dword[__cycles_needed],0\n"); } /* ** Put all the unused cycles in the leftover cycle bank, so we can call ** attention to the tricky bit processor. */ static void force_trickybit_process(void) { emit("inc edi\n"); emit("add [__cycles_leftover],edi\n"); emit("or edi,byte -1\n");/* smaller than a mov */ } /* "newpc" has been renamed to this */ void perform_cached_rebase(void); /* Copy either __s_* or __u_* memory map pointers */ static void copy_memory_map(char *map, char *reg) { emit("mov %s,[__%s_fetch]\n", reg, map); emit("mov [__fetch],%s\n", reg); if(cputype < 68020) { emit("mov %s,[__%s_readbyte]\n" , reg, map); emit("mov [__readbyte],%s\n" , reg); emit("mov %s,[__%s_readword]\n" , reg, map); emit("mov [__readword],%s\n" , reg); emit("mov %s,[__%s_writebyte]\n", reg, map); emit("mov [__writebyte],%s\n", reg); emit("mov %s,[__%s_writeword]\n", reg, map); emit("mov [__writeword],%s\n", reg); } else { emit("mov %s,[__%s_readbus]\n" , reg, map); emit("mov [__readbus],%s\n" , reg); emit("mov %s,[__%s_writebus]\n" , reg, map); emit("mov [__writebus],%s\n" , reg); } } /***************************************************************************/ static void gen_interface(void) { emit("section .text\n"); emit("bits 32\n"); emit("top:\n"); /***************************************************************************/ /* ** s680x0init() ** ** Entry: Nothing ** Exit: Zero ** ** This must be called before anything else. It decompresses the main jump ** table (and loop info, in the case of the 68010). */ begin_source_proc("init"); emit("pushad\n"); emit("mov edi,__jmptbl\n"); emit("mov esi,__jmptblcomp\n"); if(cputype == 68010) { emit("mov ebx,__looptbl\n"); } emit(".decomp:\n"); emit("lodsd\n"); emit("mov ecx,eax\n"); emit("and eax,0FFFFFFh\n"); emit("shr ecx,24\n"); emit("add eax,top\n"); emit("inc ecx\n"); if(cputype == 68010) { emit("mov ebp,ecx\n"); } emit(".jloop:\n"); emit("mov [edi],eax\n"); emit("add edi,byte 4\n"); emit("dec ecx\n"); emit("jnz short .jloop\n"); if(cputype == 68010) { emit("lodsb\n"); emit(".lloop:\n"); emit("mov [ebx],al\n"); emit("inc ebx\n"); emit("dec ebp\n"); emit("jnz short .lloop\n"); } emit("cmp edi,__jmptbl+262144\n"); emit("jne short .decomp\n"); emit("popad\n"); emit("xor eax,eax\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0exec(cycles) ** ** Entry: EAX = # cycles to execute ** Exit: 80000000h: success ** 80000001h: PC out of range ** 80000002h: unsupported stack frame ** FFFFFFFFh: CPU is dead because of a double fault ** < 80000000h: invalid instruction = address of invalid instr. */ begin_source_proc("exec"); if(use_stack) emit("mov eax,[esp+4]\n"); /* ** Check for stopped and double-faulted states. */ emit("test byte[__interrupts],1\n"); emit("jz .notstopped\n"); emit("test byte[__pc],1\n"); emit("jz .notfaulted\n"); emit("or eax,byte -1\n"); emit("ret\n"); emit(".notfaulted:\n"); emit("add [__odometer],eax\n"); emit("mov eax,80000000h\n"); emit("ret\n"); emit(".notstopped:\n"); emit("push ebp\n"); emit("push ebx\n"); emit("push ecx\n"); emit("push edx\n"); emit("push esi\n"); emit("push edi\n"); emit("mov [__cycles_needed],eax\n"); emit("mov edi,eax\n");/* store # of cycles to execute */ emit("dec edi\n"); emit("xor ebx,ebx\n"); emit("mov esi,[__pc]\n"); cache_ccr(); emit("xor ebp,ebp\n"); emit("mov byte[__execinfo],1\n"); /* ** Force an uncached re-base. ** This fulfills the "Entry to s680x0exec()" case. */ emit("call basefunction\n"); emit("add esi,ebp\n"); emit("test byte[__execinfo],2\n"); /* Check for PC out of bounds */ emit("jnz near exec_bounderror\n"); emit("mov dword[__cycles_leftover],0\n");/* an extra precaution */ /* PPL and Trace checkpoint */ emit("exec_checkpoint:\n"); emit("js short execquit\n"); /* Check PPL */ emit("mov cl,[__sr+1]\n"); emit("and ecx,byte 7\n"); emit("inc ecx\n"); emit("mov ch,[__interrupts]\n"); emit("or ch,ch\n"); emit("js short .yesint\n"); emit("shr ch,cl\n"); emit("jz short .noint\n"); emit(".yesint:\n"); emit("call flush_interrupts\n"); /* Force an uncached re-base */ emit("call basefunction\n"); emit("add esi,ebp\n"); emit("test byte[__execinfo],2\n"); /* Check for PC out of bounds */ emit("jnz near exec_bounderror\n"); emit(".noint:\n"); /* ** If the SR Trace flag is set, generate a pending trace exception. */ emit("mov ch,[__sr+1]\n"); emit("and ch,80h\n"); /* isolate trace flag */ emit("mov [__trace_trickybit],ch\n"); emit("jz short execloop\n"); /* ** Activate the tricky bit processor. ** ** Because edi isn't checked for negativity before entering the ** fetch/decode/execute loop, we're guaranteed to execute at least ** one more instruction before any trace exception. ** ** If another group 1 exception happens in the course of executing ** this next instruction, then the group_1_exception routine will ** clear the trace tricky bit and re-adjust the cycle counters, and ** we'll pretend none of this ever happened. */ force_trickybit_process(); emit("execloop:\n"); /* emit("xor ebx,ebx\n");suffice to say, bits 16-31 should be zero... */ emit("mov bx,[esi]\n"); emit("add esi,byte 2\n"); emit("jmp dword[__jmptbl+ebx*4]\n"); /* Traditional loop - used when hog mode is off */ if(!hog) { emit("execend:\n"); emit("jns short execloop\n"); } emit("execquit:\n"); /* ** Tricky Bit Processor */ /* Look for trace tricky bit */ emit("cmp byte[__trace_trickybit],0\n"); emit("je short execquit_notrace\n"); /* Generate trace exception */ emit("mov edx,24h\n"); emit("call group_1_exception\n"); perform_cached_rebase(); /* Subtract time used by exception processing */ emit("sub edi,byte %d\n", (cputype == 68010) ? 38 : 34); emit("execquit_notrace:\n"); /* ** Look for pending interrupts that exceed the current PPL. These ** are higher priority and are therefore processed last (the ISR will ** end up getting control). */ emit("mov cl,[__sr+1]\n"); emit("and ecx,byte 7\n"); emit("inc ecx\n"); emit("mov ch,[__interrupts]\n"); emit("or ch,ch\n"); emit("js short execquit_yesinterrupt\n"); emit("shr ch,cl\n"); emit("jz short execquit_nointerrupt\n"); emit("execquit_yesinterrupt:\n"); emit("call flush_interrupts\n"); /* ** Force an uncached re-base. ** This fulfills the "Hardware interrupt" case. */ emit("call basefunction\n"); emit("add esi,ebp\n"); emit("test byte[__execinfo],2\n"); /* Check for PC out of bounds */ emit("jnz short exec_bounderror\n"); emit("execquit_nointerrupt:\n"); /* ** Incorporate leftover cycles (if any) and see if we should keep ** running. */ emit("add edi,[__cycles_leftover]\n"); emit("mov dword[__cycles_leftover],0\n"); emit("jns short execloop\n"); /* Leave s680x0exec with "Success" code. */ emit("mov ecx,80000000h\n"); /* ** Exit the s680x0exec routine. By this time the return code should ** already be in ecx. */ emit("execexit:\n"); emit("sub esi,ebp\n"); writeback_ccr(); emit("mov [__pc],esi\n"); emit("inc edi\n"); emit("mov edx,[__cycles_needed]\n"); emit("sub edx,edi\n"); emit("add [__odometer],edx\n"); emit("mov byte[__execinfo],0\n"); /* ** Remember: __io_cycle_counter is always -1 when idle! ** ** This prevents us from having to check __execinfo during the ** readOdometer / tripOdometer calls. */ emit("mov dword[__cycles_needed],0\n"); emit("mov dword[__io_cycle_counter],-1\n"); emit("mov eax,ecx\n");/* return code */ emit("pop edi\n"); emit("pop esi\n"); emit("pop edx\n"); emit("pop ecx\n"); emit("pop ebx\n"); emit("pop ebp\n"); emit("ret\n"); /* ** Leave s680x0exec with "Out of bounds" code. */ emit("exec_bounderror:\n"); emit("mov ecx,80000001h\n"); emit("jmp short execexit\n"); /* ** Invalid instruction handler */ emit("invalidins:\n"); emit("sub esi,byte 2\n"); /* back up one word */ emit("mov ecx,esi\n");/* get address in ecx */ emit("sub ecx,ebp\n");/* subtract base */ maskaddress("ecx"); if(addressbits == 32) { emit("and ecx,7FFFFFFFh\n"); } /* emit("or byte[__stopped],2\n");*/ emit("jmp short execexit\n"); /***************************************************************************/ /* ** s680x0reset() ** ** Entry: Nothing ** Exit: 0 on success ** 1 on failure: ** * if there's no Supervisor Program entry for address 0 ** * if s680x0exec() is active ** -1 on double fault */ begin_source_proc("reset"); emit("mov eax,1\n"); emit("test [__execinfo],al\n"); /* Ensure s680x0exec() inactive */ emit("jnz near .return\n"); emit("cmp dword[__s_fetch],0\n"); emit("je near .return\n"); emit("dec eax\n"); emit("mov [__execinfo],al\n"); emit("sub eax,byte 16\n"); emit(".gp:\n"); emit("mov dword[__reg+64+eax*4],0\n"); emit("inc eax\n"); emit("jnz short .gp\n"); emit("mov [__asp],eax\n"); if(cputype >= 68020) emit("mov [__xsp],eax\n"); /* Set up SR for no tracing, supervisor mode, ISP, PPL 7 */ emit("mov word[__sr],2700h\n"); if(cputype >= 68010) { emit("mov [__vbr],eax\n"); emit("mov [__sfc],al\n"); emit("mov [__dfc],al\n"); } if(cputype == 68010) { emit("mov [__loopmode],al\n"); } /* Copy supervisor address space information */ copy_memory_map("s", "eax"); /* Generate Supervisor Program Space reads to get the initial PC and ** SSP/ISP */ emit("mov eax,1\n"); /* assume failure */ emit("mov [__pc],eax\n"); emit("mov [__interrupts],al\n"); emit("push esi\n"); emit("push ebp\n"); emit("xor esi,esi\n"); emit("call basefunction\n");/* will preserve eax */ emit("test byte[__execinfo],2\n"); emit("jnz short .exit\n"); emit("add esi,ebp\n"); emit("mov eax,[esi]\n"); emit("rol eax,16\n"); emit("mov [__a7],eax\n"); emit("mov eax,[esi+4]\n"); emit("rol eax,16\n"); emit("mov [__pc],eax\n"); /* An address error here will cause a double fault */ emit("and eax,byte 1\n"); emit("mov [__interrupts],al\n"); emit("neg eax\n"); /* -1 on double fault, 0 on success */ emit(".exit:\n"); emit("pop ebp\n"); emit("pop esi\n"); emit(".return:\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0interrupt(level, vector) ** ** Entry: EAX = interrupt level ** EDX = vector (-1 for auto, -2 for spurious) ** Exit: EAX = 0 on success ** 1 on failure, previous vector exists ** 2 on invalid input */ begin_source_proc("interrupt"); emit("push edx\n"); if(use_stack) { emit("mov eax,[esp+8]\n"); /* eax = level */ emit("mov edx,[esp+12]\n"); /* edx = vector */ } /* ** Verify parameters. */ emit("cmp eax,byte 7\n"); emit("ja short .badinput\n"); emit("or eax,eax\n"); emit("jz short .badinput\n"); emit("cmp edx,255\n"); emit("jg short .badinput\n"); emit("cmp edx,byte -2\n"); emit("jl short .badinput\n"); /* ** Calculate the vector number. */ emit("jne short .notspurious\n"); emit("mov edx,18h\n"); emit(".notspurious:\n"); emit("or edx,edx\n"); emit("jns short .notauto\n"); emit("lea edx,[eax+18h]\n"); emit(".notauto:\n"); /* ** Test to see if this interrupt level is already pending. ** If it is, return with failure. */ emit("push ecx\n"); emit("mov cl,al\n"); emit("mov ah,1\n"); emit("shl ah,cl\n"); emit("pop ecx\n"); emit("test [__interrupts],ah\n"); emit("jnz .failure\n"); /* ** Commit the given interrupt and vector number. */ emit("or [__interrupts],ah\n"); emit("mov ah,0\n"); emit("mov [__interrupts+eax],dl\n"); emit("and byte[__interrupts],0FEh\n"); /* ** Notify the tricky bit handler. If we're doing this outside of ** s680x0exec(), then the notification will have no effect, because ** __io_cycle_counter is always -1 when idle. */ emit("mov edx,[__io_cycle_counter]\n"); emit("inc edx\n"); emit("add [__cycles_leftover],edx\n"); emit("mov dword[__io_cycle_counter],-1\n"); /* ** Success (0) */ emit("pop edx\n"); emit("xor eax,eax\n"); emit("ret\n"); /* ** Failure (1) */ emit(".failure:\n"); emit("pop edx\n"); emit("mov eax,1\n"); emit("ret\n"); /* ** Bad input (2) */ emit(".badinput:\n"); emit("pop edx\n"); emit("mov eax,2\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0flushInterrupts() ** ** Flushes all pending interrupts. ** ** Entry: Nothing ** Exit: Nothing */ begin_source_proc("flushInterrupts"); /* ** If s680x0exec() is already running, then the interrupts are about ** to get flushed anyway. So ignore this call. */ emit("test byte[__execinfo],1\n"); emit("jnz .noflush\n"); /* Make registers "live" */ emit("pushad\n"); emit("mov esi,[__pc]\n"); emit("xor ebp,ebp\n"); cache_ccr(); emit("xor edi,edi\n"); /* well, semi-live */ emit("call flush_interrupts\n"); emit("sub [__odometer],edi\n"); /* edi will be <= 0 here */ emit("mov [__pc],esi\n"); /* PC guaranteed unbased */ writeback_ccr(); emit("popad\n"); emit(".noflush:\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0GetContextSize() ** ** Entry: Nothing ** Exit: Size of context array (in bytes) */ begin_source_proc("GetContextSize"); emit("mov eax,contextend-contextbegin\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0GetContext(context) ** ** Entry: Address of context in EAX ** Exit: Nothing */ begin_source_proc("GetContext"); emit("push edx\n"); emit("push edi\n"); if(use_stack) emit("mov edi,[esp+12]\n"); else emit("mov edi,eax\n"); emit("%%assign i 0\n"); emit("%%rep ((contextend-contextbegin) / 8)\n"); emit(" mov eax,[contextbegin+i+0]\n"); emit(" mov edx,[contextbegin+i+4]\n"); emit(" mov [edi+i+0],eax\n"); emit(" mov [edi+i+4],edx\n"); emit("%%assign i i+8\n"); emit("%%endrep\n"); emit("%%if ((contextend-contextbegin) %% 8)!=0\n"); emit(" mov eax,[contextbegin+i+0]\n"); emit(" mov [edi+i+0],eax\n"); emit("%%endif\n"); emit("pop edi\n"); emit("pop edx\n"); emit("xor eax,eax\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0SetContext(context) ** ** Entry: Address of context in EAX ** Exit: Nothing */ begin_source_proc("SetContext"); emit("push edx\n"); emit("push esi\n"); if(use_stack) emit("mov esi,[esp+12]\n"); else emit("mov esi,eax\n"); emit("%%assign i 0\n"); emit("%%rep ((contextend-contextbegin) / 8)\n"); emit(" mov eax,[esi+i+0]\n"); emit(" mov edx,[esi+i+4]\n"); emit(" mov [contextbegin+i+0],eax\n"); emit(" mov [contextbegin+i+4],edx\n"); emit("%%assign i i+8\n"); emit("%%endrep\n"); emit("%%if ((contextend-contextbegin) %% 8)!=0\n"); emit(" mov eax,[esi+i+0]\n"); emit(" mov [contextbegin+i+0],eax\n"); emit("%%endif\n"); emit("pop esi\n"); emit("pop edx\n"); emit("xor eax,eax\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0fetch(address) ** ** (Will need to be rewritten to handle function codes) ** ** Reads a word from memory using the _supervisor_ fetch map. ** Entry: Address in EAX ** Exit: The fetched word (or -1 if the address was invalid) */ begin_source_proc("fetch"); if(use_stack) emit("mov eax,[esp+4]\n"); emit("push ebx\n"); emit("push esi\n"); emit("push edi\n");/* can be destroyed by rebase */ emit("push ebp\n"); emit("push dword[__fetch]\n"); emit("mov ebx,[__s_fetch]\n"); emit("mov [__fetch],ebx\n"); /* Must save the fetch region cache as well */ emit("push dword[__fetch_region_start]\n"); emit("push dword[__fetch_region_end]\n"); /* and __execinfo */ emit("mov bl,[__execinfo]\n"); emit("push ebx\n"); emit("xor ebp,ebp\n"); emit("mov esi,eax\n"); emit("and byte[__execinfo],0FDh\n"); /* Force re-base */ emit("call basefunction\n"); emit("test byte[__execinfo],2\n"); emit("mov eax,-1\n"); emit("jnz short .badfetch\n"); emit("add esi,ebp\n"); emit("inc eax\n"); /* make eax zero */ emit("mov ax,[esi]\n"); emit(".badfetch:\n"); emit("pop ebx\n"); emit("mov [__execinfo],bl\n"); emit("pop dword[__fetch_region_end]\n"); emit("pop dword[__fetch_region_start]\n"); emit("pop dword[__fetch]\n"); emit("pop ebp\n"); emit("pop edi\n"); emit("pop esi\n"); emit("pop ebx\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0readOdometer() ** ** Reads the odometer (works from anywhere) ** Entry: Nothing ** Exit: Odometer in EAX */ begin_source_proc("readOdometer"); emit("mov eax,[__cycles_needed]\n"); emit("sub eax,[__io_cycle_counter]\n"); emit("dec eax\n"); /* eax = elapsed cycles */ emit("sub eax,[__cycles_leftover]\n"); emit("add eax,[__odometer]\n"); /* add to old __odometer */ emit("ret\n"); /***************************************************************************/ /* ** s680x0tripOdometer() ** ** Reads and then clears the odometer (works from anywhere) ** Entry: Nothing ** Exit: Old odometer value in EAX */ begin_source_proc("tripOdometer"); /* Read */ emit("mov eax,[__cycles_needed]\n"); emit("sub eax,[__io_cycle_counter]\n"); emit("dec eax\n"); /* eax = elapsed cycles */ emit("sub eax,[__cycles_leftover]\n"); emit("add [__odometer],eax\n"); /* add to old __odometer */ /* Clear */ emit("mov eax,[__io_cycle_counter]\n"); emit("inc eax\n"); emit("mov [__cycles_needed],eax\n"); emit("mov eax,[__odometer]\n"); emit("mov dword[__odometer],0\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0controlOdometer(n) ** ** Reads the odometer, clears it only if n != 0 ** Entry: n in EAX ** Exit: Old odometer value in EAX */ begin_source_proc("controlOdometer"); if(use_stack) emit("mov eax,[esp+4]\n"); emit("or eax,eax\n"); emit("jnz short _%stripOdometer\n", sourcename); emit("jmp short _%sreadOdometer\n", sourcename); /***************************************************************************/ /* ** s680x0releaseTimeslice() ** ** Ends the s680x0exec call prematurely. The early exit is reflected in ** __odometer. ** Entry: Nothing ** Exit: Nothing */ begin_source_proc("releaseTimeslice"); emit("mov eax,[__cycles_needed]\n"); emit("sub [__io_cycle_counter],eax\n"); emit("xor eax,eax\n"); emit("mov [__cycles_needed],eax\n"); emit("ret\n"); /***************************************************************************/ /* ** s680x0readPC() ** ** Returns the current program counter. Works anywhere, including I/O, ** RESET, and BKPT handlers. ** ** Note that the value returned won't necessarily coincide exactly with the ** beginning of an instruction. */ begin_source_proc("readPC"); emit("test byte[__execinfo],1\n"); emit("jnz short .live\n"); emit("mov eax,[__pc]\n"); emit("ret\n"); emit(".live:\n"); emit("mov eax,[__io_fetchbased_pc]\n"); emit("sub eax,[__io_fetchbase]\n"); emit("ret\n"); } /***************************************************************************/ /* ** Routine that flushes pending interrupts (with correct priority). ** Assumes "live" registers, including EDI and EBP. ** ** Does not rebase the PC. In fact, it will un-base the PC even if there ** aren't any pending interrupts. ** ** s680x0flushInterrupts() is actually a wrapper for this. */ static void gen_flush_interrupts(void) { int cycles = (cputype == 68010) ? 46 : 44; align(16); emit("flush_interrupts:\n"); /* Unbase PC */ emit("sub esi,ebp\n"); emit("xor ebp,ebp\n"); /* This loop is intentionally post-tested because interrupt level 7 ** is non-maskable. */ emit("mov edx,7\n"); emit("mov cl,80h\n"); emit("mov ch,[__sr+1]\n"); /* current PPL */ emit("and ch,7\n"); emit(".loop:\n"); emit("test [__interrupts],cl\n"); emit("jz short .noint\n"); emit("mov dl,[__interrupts+edx]\n"); emit("not cl\n"); emit("and [__interrupts],cl\n"); emit("shl edx,2\n"); emit("call group_1_exception\n"); emit("sub edi,byte %d\n", cycles); emit("jmp short .intdone\n"); emit(".noint:\n"); emit("dec edx\n"); emit("jz short .intdone\n"); emit("shr cl,1\n"); emit("cmp dl,ch\n"); emit("jg short .loop\n"); emit(".intdone:\n"); emit("ret\n"); } /***************************************************************************/ static void ret_timing(int n) { if(n) { emit("sub edi,%s%d\n", (n < 128) ? "byte " : "", n); } else { emit("or edi,edi\n"); } /* If hog mode is off, jump back to the main loop */ if(!hog) { emit("jmp execend\n"); /* If hog mode is on, fetch and execute the next instruction */ } else { emit("js near execquit\n"); emit("mov bx,[esi]\n"); emit("add esi,byte 2\n"); emit("jmp dword[__jmptbl+ebx*4]\n"); } } /* ** This version of ret_timing does a trace flag check. ** ** Note: this only needs to be used for instructions which can potentially ** _set_ the trace flag. Instructions which can't set the trace flag (even ** if they can clear it) are OK to use ret_timing as usual. Why? Well, if ** an instruction is run in trace mode, that instruction is doomed to be ** traced, regardless if it clears the trace flag during its execution. ** Furthermore, the trace exception (being a group 1 exception after all) ** will clear the trace tricky bit as well as the trace flag. */ static void ret_timing_checkpoint(int n) { if(n) { emit("sub edi,%s%d\n", (n < 128) ? "byte " : "", n); } else { emit("or edi,edi\n"); } emit("jmp exec_checkpoint\n"); } /***************************************************************************/ /* This routine decodes an extension word into EDX. */ static void gen_decode_ext(void) { align(16); emit("decode_ext:\n"); if(cputype <= 68010) { emit("push ecx\n"); emit("movzx edx,word[esi]\n"); emit("movsx ecx,dl\n"); emit("add esi,byte 2\n"); emit("shr edx,12\n"); emit("mov edx,[__reg+edx*4]\n"); emit("jc short .long\n"); emit("movsx edx,dx\n"); emit(".long:\n"); emit("add edx,ecx\n"); emit("pop ecx\n"); emit("ret\n"); } else { /* For future expansion... */ /* need an extra jump table here */ } } /***************************************************************************/ /* ** Perform a cached rebase */ void perform_cached_rebase(void) { int myline = linenum; linenum += 2; emit("cmp esi,[__fetch_region_start]\n"); emit("jb short ln%d\n", myline); emit("cmp esi,[__fetch_region_end]\n"); emit("jbe short ln%d\n", myline + 1); emit("ln%d:\n", myline); emit("call basefunction\n"); emit("ln%d:\n", myline + 1); emit("add esi,ebp\n"); } /***************************************************************************/ /* ** This is the function that generates a base for a given 68K PC. ** ** Entry: 68K PC in ESI ** Exit: Newly calculated base in EBP ** ** Sounds like a simple lookup into the __fetch array, and in the case of ** 32-bit addresses, it is. But for anything less, we'll need to compensate ** for potential garbage in the unused address bits, by subtracting the value ** of these unused bits from the base. This way the full 32 bits of the PC ** are preserved, even if they're not used. ** ** The only registers which need to be "live" here are ESI and EBP. The ** fetch region cache is updated, and bit 1 of __execinfo is set if the base ** couldn't be calculated. */ static void gen_basefunction(void) { align(16); emit("basefunction:\n"); /* ** Prepare ESI by masking off unused address bits (but save it ** first). */ if(addressbits < 32) { emit("push esi\n"); maskaddress("esi"); } emit("mov ebp,[__fetch]\n"); emit(".check:\n"); emit("db 3Eh\n"); emit("cmp esi,[ebp]\n"); /* Are we smaller? */ emit("jb short .next\n"); /* Yes, go to next address */ emit("db 3Eh\n"); emit("cmp esi,[ebp+4]\n"); /* Are we bigger? */ emit("jbe short .base\n"); emit(".next:\n"); emit("db 3Eh\n"); emit("cmp dword [ebp],byte -1\n"); /* End of list? */ emit("je short .outofrange\n"); emit("add ebp,byte 12\n"); /* To the next structure */ emit("jmp short .check\n"); /* Bad news... we jumped out into the weeds. */ emit(".outofrange:\n"); if(addressbits < 32) emit("pop esi\n"); emit("xor ebp,ebp\n"); emit("mov dword[__fetch_region_start],-1\n"); emit("mov dword[__fetch_region_end],ebp\n"); force_context_switch(); emit("or byte[__execinfo],2\n"); emit("ret\n"); emit(".base:\n"); /* ** Dealing with addressbits < 32 again... if the unused PC bits are ** anything but zero, then we'll need to adjust the base to ** compensate. */ if(addressbits < 32) { emit("mov esi,[esp]\n"); emit("and esi,%d\n", 0xFFFFFFFF << addressbits); } emit("push edx\n"); emit("mov edx,ebp\n"); /* ** Update the fetch region cache, adding in the garbage bits where ** applicable. */ emit("mov ebp,[edx]\n"); if(addressbits < 32) emit("or ebp,esi\n"); emit("mov [__fetch_region_start],ebp\n"); emit("mov ebp,[edx+4]\n"); if(addressbits < 32) emit("or ebp,esi\n"); emit("mov [__fetch_region_end],ebp\n"); emit("mov ebp,[edx+8]\n"); emit("pop edx\n"); if(addressbits < 32) { /* ** Subtract garbage bits from the base, and restore the ** original 32-bit PC value. */ emit("sub ebp,esi\n"); emit("pop esi\n"); } emit("ret\n"); } /***************************************************************************/ /* Read flags from CL into our CCR. CX is unmodified. */ static void cl2ccr(void){ emit("mov al,cl\n"); /* read CCR -> AL */ /* ???????????XNZVC */ emit("mov ah,al\n"); /* copy to AH */ /* ???XNZVC???XNZVC */ emit("and ax,0C10h\n"); /* isolate NZ...X */ /* 0000NZ00000X0000 */ emit("shl ah,3\n"); /* put NZ almost where we want it */ /* 0NZ00000000X0000 */ emit("shr al,4\n"); /* shift X flag into bit 0 */ /* 0NZ000000000000X */ emit("mov [__xflag],al\n"); /* store X flag */ /* 0NZ000000000000X al -> xflag */ emit("mov al,cl\n"); /* read CCR -> AL again */ /* 0NZ00000000XNZVC */ emit("and al,3\n"); /* isolate VC */ /* 0NZ00000000000VC */ emit("shr al,1\n"); /* just V */ /* 0NZ000000000000V carry */ emit("adc ah,ah\n"); /* append C to rest of flags */ /* NZ00000C0000000V */ } /* ** Read flags from CX into our SR, performing a mode switch where applicable. ** CX is unmodified. Uses 4 bytes of stack. ** ** This does not do any of the trace flag mojo, so be sure to check for it ** explicitly where applicable (hint: ret_timing_checkpoint). */ static void cx2sr(void){ int myline = linenum; linenum += 2; emit("push ecx\n"); /* Step 1: switch supervisor mode */ /* Is the new mode different from the last? */ emit("mov cl,[__sr+1]\n"); emit("and cx,2020h\n"); emit("xor ch,cl\n"); emit("jz near ln%d\n", myline); /* If so, swap stack pointers */ emit("mov ecx,[__a7]\n"); emit("xchg ecx,[__asp]\n"); emit("mov [__a7],ecx\n"); /* and copy the appropriate memory map */ emit("test byte[esp+1],20h\n"); emit("jz short ln%d\n", myline + 1); copy_memory_map("s", "ecx"); emit("jmp short ln%d\n", myline); emit("ln%d:\n", myline + 1); copy_memory_map("u", "ecx"); emit("ln%d:\n", myline); emit("pop ecx\n"); /* Step 2: set new PPL / supervisor mode / trace flag */ emit("mov [__sr+1],ch\n"); emit("and byte[__sr+1],0A7h\n"); /* Step 3: Store CL into CCR */ cl2ccr(); } /* Read flags from our CCR into CL. CH is zeroed. */ static void ccr2cl(void){ /* Read XNZ */ emit("mov ch,[__xflag]\n"); /* 0000000X???????? */ emit("mov cl,ah\n"); /* 0000000XNZ?????C */ emit("shr cx,6\n"); /* 0000000000000XNZ */ /* Read V */ emit("add cl,cl\n"); /* 000000000000XNZ0 */ emit("or cl,al\n"); /* 000000000000XNZV */ /* Read C */ emit("mov ch,ah\n"); /* NZ?????C0000XNZV */ emit("shl ch,8\n"); /* 000000000000XNZV carry */ emit("adc cl,cl\n"); /* 00000000000XNZVC */ } /* Read flags from our SR into CX. */ static void sr2cx(void){ /* Condition codes */ ccr2cl(); /* PPL / supervisor mode / trace flag */ emit("mov ch,[__sr+1]\n"); } /* Switch to supervisor mode. Can potentially destroy ECX. */ static void supervisor(void){ int myline=linenum;linenum++; emit("test byte[__sr+1],20h\n"); emit("jnz short ln%d\n",myline); emit("mov ecx,[__a7]\n"); emit("xchg ecx,[__asp]\n"); emit("mov [__a7],ecx\n"); copy_memory_map("s", "ecx"); emit("or byte[__sr+1],20h\n"); emit("ln%d:\n",myline); } /***************************************************************************/ static void gen_readbw(int size){ char z='x'; if(size==1)z='b'; if(size==2)z='w'; align(16); emit("readmemory%s:\n",sizename[size]); emit("mov [__access_address],edx\n"); maskaddress("edx"); emit("mov ecx,[__read%s]\n",sizename[size]); emit("read%c_check:\n",z); emit("cmp edx,[ecx]\n"); /* Are we smaller? */ emit("jb short read%c_next\n",z); /* Yes, go to next address */ emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("jbe short read%c_call\n",z); emit("read%c_next:\n",z); emit("cmp dword[ecx],byte -1\n");/* End of list? */ emit("je short read%c_outofrange\n",z); emit("add ecx,byte 16\n"); /* To the next structure */ emit("jmp short read%c_check\n",z); emit("read%c_outofrange:\n",z); emit("or ecx,byte -1\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("read%c_call:\n",z); emit("cmp dword[ecx+8],byte 0\n"); emit("jne short read%c_callio\n",z); emit("sub edx,[ecx]\n"); emit("add edx,[ecx+12]\n"); if(size==1){ emit("xor edx,byte 1\n"); emit("mov cl,[edx]\n"); }else{ emit("mov cx,[edx]\n"); } emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("read%c_callio:\n",z); airlock_exit(); /* ** What's this undocumented thingy? Read/write handlers actually get ** an extra parameter (the address of the record that caused the ** call). */ emit("mov eax,edx\n"); /* address */ emit("mov edx,ecx\n"); /* pointer to structure */ if(use_stack){ emit("push edx\n"); emit("push eax\n"); } emit("call dword[edx+8]\n"); if(use_stack)emit("add esp,byte 8\n"); emit("mov ecx,eax\n"); airlock_enter(); emit("mov edx,[__access_address]\n"); emit("ret\n"); } static void gen_readl(void){ align(16); emit("readmemory%s:\n",sizename[4]); emit("mov [__access_address],edx\n"); maskaddress("edx"); emit("mov ecx,[__readword]\n"); emit("readl_check:\n"); emit("cmp edx,[ecx]\n"); /* Are we smaller? */ emit("jb short readl_next\n"); /* Yes, go to next address */ emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("jbe short readl_call\n"); emit("readl_next:\n"); emit("cmp dword[ecx],byte -1\n");/* End of list? */ emit("je short readl_outofrange\n"); emit("add ecx,byte 16\n"); /* To the next structure */ emit("jmp short readl_check\n"); emit("readl_outofrange:\n"); emit("add edx,byte 2\n"); emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("mov ecx,-1\n"); emit("ja near readl_lower\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("readl_call:\n"); emit("cmp dword[ecx+8],byte 0\n"); emit("jne short readl_callio\n"); emit("add edx,byte 2\n"); emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("ja short readl_split\n"); /* Unsplit version */ emit("sub edx,[ecx]\n"); emit("add edx,[ecx+12]\n"); emit("mov ecx,[edx-2]\n"); emit("rol ecx,16\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("readl_callio:\n"); emit("add edx,byte 2\n"); emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("ja near readl_iosplit\n"); emit("sub edx,byte 2\n"); /* Unsplit version */ airlock_exit(); emit("mov eax,edx\n"); /* address */ emit("mov edx,ecx\n"); /* pointer to structure */ emit("push eax\n"); emit("push edx\n"); if(use_stack){ emit("push edx\n"); emit("push eax\n"); } emit("call dword[edx+8]\n"); if(use_stack)emit("add esp,byte 8\n"); emit("pop edx\n"); emit("xchg eax,[esp]\n"); emit("add eax,byte 2\n"); /* maskaddress("eax");*/ /* this case would force a split read anyway */ if(use_stack){ emit("push edx\n"); emit("push eax\n"); } emit("call dword[edx+8]\n"); if(use_stack)emit("add esp,byte 8\n"); emit("pop ecx\n"); emit("shl ecx,16\n"); emit("mov cx,ax\n"); airlock_enter(); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("readl_split:\n"); emit("sub edx,[ecx]\n"); emit("add edx,[ecx+12]\n"); emit("mov cx,[edx-2]\n"); emit("readl_lower:\n"); emit("mov edx,[esp]\n"); emit("add edx,byte 2\n"); emit("shl ecx,16\n"); emit("push ecx\n"); emit("call readmemoryword\n"); emit("and ecx,0FFFFh\n"); emit("or ecx,[esp]\n"); emit("add esp,byte 4\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("readl_iosplit:\n"); emit("sub edx,byte 2\n"); airlock_exit(); emit("mov eax,edx\n"); /* address */ emit("mov edx,ecx\n"); /* pointer to structure */ if(use_stack){ emit("push edx\n"); emit("push eax\n"); } emit("call dword[edx+8]\n"); if(use_stack)emit("add esp,byte 8\n"); emit("mov ecx,eax\n"); airlock_enter(); emit("jmp short readl_lower\n"); } static void gen_writebw(int size){ char z='x'; if(size==1)z='b'; if(size==2)z='w'; align(16); emit("writememory%s:\n",sizename[size]); emit("mov [__access_address],edx\n"); emit("push ecx\n"); emit("write%c_top:\n",z); maskaddress("edx"); emit("mov ecx,[__write%s]\n",sizename[size]); emit("write%c_check:\n",z); emit("cmp edx,[ecx]\n"); /* Are we smaller? */ emit("jb short write%c_next\n",z); /* Yes, go to next address */ emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("jbe short write%c_call\n",z); emit("write%c_next:\n",z); emit("cmp dword[ecx],byte -1\n");/* End of list? */ emit("je short write%c_end\n",z); emit("add ecx,byte 16\n"); /* To the next structure */ emit("jmp short write%c_check\n",z); emit("write%c_call:\n",z); emit("cmp dword[ecx+8],byte 0\n"); emit("jne short write%c_callio\n",z); emit("sub edx,[ecx]\n"); emit("add edx,[ecx+12]\n"); if(z=='b')emit("xor edx,byte 1\n"); emit("pop ecx\n"); emit("mov [edx],%s\n",x86cx[size]); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("write%c_callio:\n",z); /* --- we have: ** index in ecx ** address in edx ** value in [esp] ** --- we want: ** index in anything (saved first) ** address in eax ** value in edx */ airlock_exit(); emit("mov ebx,ecx\n"); /* pointer to structure */ emit("mov eax,edx\n"); /* address */ emit("xor edx,edx\n"); /* data */ emit("mov %s,[esp+%d]\n",x86dx[size],airlock_stacksize); if(use_stack){ emit("push ebx\n"); emit("push edx\n"); emit("push eax\n"); } emit("call dword[ebx+8]\n"); if(use_stack)emit("add esp,byte 12\n"); airlock_enter(); emit("write%c_end:\n",z); emit("pop ecx\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); } static void gen_writel(void){ align(16); emit("writememory%s:\n",sizename[4]); emit("mov [__access_address],edx\n"); emit("push ecx\n"); maskaddress("edx"); emit("mov ecx,[__write%s]\n",sizename[2]); emit("writel_check:\n"); emit("cmp edx,[ecx]\n"); /* Are we smaller? */ emit("jb short writel_next\n"); /* Yes, go to next address */ emit("cmp edx,[ecx+4]\n"); /* Are we bigger? */ emit("jbe short writel_call\n"); emit("writel_next:\n"); emit("cmp dword[ecx],byte -1\n");/* End of list? */ emit("je short writel_outofrange\n"); emit("add ecx,byte 16\n"); /* To the next structure */ emit("jmp short writel_check\n"); /* The top word was out of range, but the bottom word might not be */ emit("writel_outofrange:\n"); emit("add edx,byte 2\n"); emit("jmp writew_top\n"); emit("writel_call:\n"); emit("cmp dword[ecx+8],byte 0\n"); emit("jne short writel_callio\n"); emit("add edx,byte 2\n"); emit("cmp edx,[ecx+4]\n"); emit("ja short writel_split\n"); emit("sub edx,[ecx]\n"); emit("add edx,[ecx+12]\n"); emit("pop ecx\n"); emit("rol ecx,16\n"); emit("mov [edx-2],ecx\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("writel_callio:\n"); emit("add edx,byte 2\n"); emit("cmp edx,[ecx+4]\n"); emit("ja short writel_iosplit\n"); emit("sub edx,byte 2\n"); /* Unsplit version */ /* --- we have: ** index in ecx ** address in edx ** value in [esp] ** --- we want: ** index in anything (saved first) ** address in eax ** value in edx */ airlock_exit(); emit("mov ebx,ecx\n"); /* pointer to structure */ emit("mov eax,edx\n"); /* address */ emit("xor edx,edx\n"); /* data */ emit("mov dx,[esp+%d]\n",airlock_stacksize+2); emit("push eax\n"); emit("push ebx\n"); if(use_stack){ emit("push ebx\n"); emit("push edx\n"); emit("push eax\n"); } emit("call dword[ebx+8]\n"); if(use_stack)emit("add esp,byte 12\n"); emit("pop ebx\n"); emit("pop eax\n"); emit("add eax,byte 2\n"); /* maskaddress("eax");*/ /*this case would force a split write anyway */ emit("xor edx,edx\n"); /* data */ emit("mov dx,[esp+%d]\n",airlock_stacksize); if(use_stack){ emit("push ebx\n"); emit("push edx\n"); emit("push eax\n"); } emit("call dword[ebx+8]\n"); if(use_stack)emit("add esp,byte 12\n"); airlock_enter(); emit("writel_end:\n"); emit("pop ecx\n"); emit("mov edx,[__access_address]\n"); emit("ret\n"); emit("writel_split:\n"); emit("sub edx,[ecx]\n"); emit("add edx,[ecx+12]\n"); emit("mov cx,[esp+2]\n"); emit("mov [edx-2],cx\n"); emit("mov edx,[esp+4]\n"); emit("add edx,byte 2\n"); emit("jmp writew_top\n"); emit("writel_iosplit:\n"); /* --- we have: ** index in ecx ** address in edx ** value in [esp] ** --- we want: ** index in anything (saved first) ** address in eax ** value in edx */ airlock_exit(); emit("mov ebx,ecx\n"); /* pointer to structure */ emit("mov eax,edx\n"); /* address */ emit("xor edx,edx\n"); /* data */ emit("mov dx,[esp+%d]\n",airlock_stacksize+2); if(use_stack){ emit("push ebx\n"); emit("push edx\n"); emit("push eax\n"); } emit("call dword[ebx+8]\n"); if(use_stack)emit("add esp,byte 12\n"); airlock_enter(); emit("mov edx,[esp+4]\n"); emit("add edx,byte 2\n"); emit("jmp writew_top\n"); } /***************************************************************************/ /* ** Group 1 and 2 exceptions ** Exception address is passed in EDX ** ** Does not fix the new PC! */ static void gen_group_12_exception(void) { align(16); emit("group_1_exception:\n"); emit("group_2_exception:\n"); emit("and byte[__interrupts],0FEh\n"); /* first thing's first */ if(cputype == 68010) { emit("mov byte[__loopmode],0\n"); } if(cputype >= 68010) { emit("push edx\n"); emit("add edx,[__vbr]\n"); } emit("call readmemorydword\n"); if(cputype >= 68010) { emit("pop edx\n"); } emit("push ecx\n");/* dest. PC */ sr2cx(); emit("push ecx\n");/* old SR */ supervisor(); /* ** Exception handlers do not like being traced, so clear the SR trace ** flag as well as the trace tricky bit. ** ** Leave the cycle leftover count alone, in case we still need to ** call attention to other unrelated tricky bits. */ emit("and byte[__sr+1],27h\n"); emit("mov byte[__trace_trickybit],0\n"); emit("mov ecx,esi\n"); emit("sub ecx,ebp\n"); if(cputype >= 68010) { emit("push ecx\n");/* old PC */ emit("mov ecx,edx\n"); } emit("mov edx,[__a7]\n"); if(cputype >= 68010) { emit("and ecx,0FFCh\n");/* Format code */ emit("sub edx,byte 2\n"); emit("call writememoryword\n"); emit("pop ecx\n"); } emit("sub edx,byte 4\n"); emit("call writememorydword\n"); emit("pop ecx\n");/* old SR */ emit("sub edx,byte 2\n"); emit("call writememoryword\n"); emit("mov [__a7],edx\n"); emit("pop esi\n");/* dest. PC */ emit("ret\n"); } /***************************************************************************/ /* Privilege violation */ static void gen_privilege_violation(void){ align(16); emit("privilege_violation:\n"); emit("sub esi,byte 2\n"); emit("mov edx,20h\n"); emit("call group_1_exception\n"); perform_cached_rebase(); ret_timing((cputype==68010)?38:34); } /***************************************************************************/ static void usereg(void) { emit("and ebx,byte 7\n"); } /* usereg only where applicable */ static void selective_usereg(void) { switch(main_eamode) { case dreg: case areg: case aind: case ainc: case adec: case adsp: case axdp: usereg(); default: } } static void selftest(int size) { emit("test %s,%s\n", x86cx[size], x86cx[size]); } /***************************************************************************/ /* Get condition: Less Than (N^V) ** If true, the x86 sign flag will be set */ static void getcondition_l_s_ns(void) { emit("push eax\n"); emit("neg al\n"); emit("xor al,ah\n"); emit("pop eax\n"); } /* Get condition: Less Than or Equal ((N^V)|Z) ** If true, the x86 sign flag will be set */ static void getcondition_le_s_ns(void) { emit("push eax\n"); emit("neg al\n"); emit("xor al,ah\n"); emit("add ah,ah\n"); emit("or al,ah\n"); emit("pop eax\n"); } static char optcc[5]; static char optrc[5]; static void getcondition(int cc) { switch(cc) { case 0x0: case 0x1: break; case 0x2:/* a */ emit("test ah,41h\n"); sprintf(optcc, "z"); sprintf(optrc, "nz"); break; case 0x3:/* be */ emit("test ah,41h\n"); sprintf(optcc, "nz"); sprintf(optrc, "z"); break; case 0x4:/* nc */ emit("test ah,1\n"); sprintf(optcc, "z"); sprintf(optrc, "nz"); break; case 0x5:/* c */ emit("test ah,1\n"); sprintf(optcc, "nz"); sprintf(optrc, "z"); break; case 0x6:/* ne */ emit("test ah,40h\n"); sprintf(optcc, "z"); sprintf(optrc, "nz"); break; case 0x7:/* e */ emit("test ah,40h\n"); sprintf(optcc, "nz"); sprintf(optrc, "z"); break; case 0x8:/* no */ emit("test al,1\n"); sprintf(optcc, "z"); sprintf(optrc, "nz"); break; case 0x9:/* o */ emit("test al,1\n"); sprintf(optcc, "nz"); sprintf(optrc, "z"); break; case 0xA:/* ns */ emit("or ah,ah\n"); sprintf(optcc, "ns"); sprintf(optrc, "s"); break; case 0xB:/* s */ emit("or ah,ah\n"); sprintf(optcc, "s"); sprintf(optrc, "ns"); break; case 0xC:/* ge */ getcondition_l_s_ns(); sprintf(optcc, "ns"); sprintf(optrc, "s"); break; case 0xD:/* l */ getcondition_l_s_ns(); sprintf(optcc, "s"); sprintf(optrc, "ns"); break; case 0xE:/* g */ getcondition_le_s_ns(); sprintf(optcc, "ns"); sprintf(optrc, "s"); break; case 0xF:/* le */ getcondition_le_s_ns(); sprintf(optcc, "s"); sprintf(optrc, "ns"); break; default:break; } } static void flags(void) { emit("lahf\n"); emit("seto al\n"); } static void flags_v0(void) { emit("lahf\n"); emit("mov al,0\n"); } /* Put one of the x86 flags into the 68K zero flag. */ static void flag_to_z(char *f) { int myline = linenum; linenum += 2; emit("j%s short ln%d\n", f, myline); emit("and ah,0BFh\n"); emit("jmp short ln%d\n", myline + 1); emit("ln%d:\n", myline); emit("or ah,40h\n"); emit("ln%d:\n", myline + 1); } /* carry to X flag */ static void c2x(void) { emit("setc [__xflag]\n"); } /* with previous flags in another register, adjust for non-changing zero */ static void adjzero(char *reg) { int myline = linenum; linenum++; emit("jnz short ln%d\n", myline); emit("or %s,0BFh\n", reg); emit("and ah,%s\n", reg); emit("ln%d:\n", myline); } /* Check for privilege violation */ static void privilegecheck(void) { emit("test byte[__sr+1],20h\n"); emit("jz near privilege_violation\n"); } /**************************************************************************** ** EFFECTIVE ADDRESS GENERATION ****************************************************************************/ /* ** There are five types of EA activity: ** ** 1. Read: precalc -> read -> postcalc ** 2. Write: precalc -> write -> postcalc ** 3. R-M-W: precalc -> read -> (modify) -> write -> postcalc ** 4. Move: Read followed by Write ** 5. Control: precalc */ /* Calculate address */ static void ea_step_precalc(int size, enum eamode mode, int reg) { char regs[100]; if(reg == -1) sprintf(regs, "ebx*4"); else sprintf(regs, "%d", reg * 4); switch(mode) { case dreg: case areg: break; case aind: case ainc: case adec: emit("mov edx,[__areg+%s]\n",regs); if(mode == adec) { /* Compensate for byte-sized stack ops */ if(size == 1) { if(reg == -1) { emit("cmp bl,7\n"); emit("adc edx,byte -2\n"); } else if(reg == 7) { emit("sub edx,byte 2\n"); } else { emit("dec edx\n"); } } else { emit("sub edx,byte %d\n", size); } } break; case adsp: emit("movsx edx,word[esi]\n"); emit("add esi,byte 2\n"); emit("add edx,[__areg+%s]\n", regs); break; case axdp: emit("call decode_ext\n"); emit("add edx,[__areg+%s]\n", regs); break; case absw: emit("movsx edx,word[esi]\n"); emit("add esi,byte 2\n"); break; case absl: emit("mov edx,dword[esi]\n"); emit("add esi,byte 4\n"); emit("rol edx,16\n"); break; case pcdp: emit("movsx edx,word[esi]\n"); emit("add edx,esi\n"); emit("sub edx,ebp\n"); emit("add esi,byte 2\n"); break; case pcxd: emit("call decode_ext\n"); emit("add edx,esi\n"); emit("sub edx,ebp\n"); emit("sub edx,byte 2\n"); break; case immd: break; default: emit("#error ea_step_precalc\n"); break; } } static void ea_step_read(int size, enum eamode mode, int reg) { char regs[100]; if(reg == -1) sprintf(regs, "ebx*4"); else sprintf(regs, "%d", reg * 4); switch(mode) { case dreg: emit("mov ecx,[__dreg+%s]\n", regs); break; case areg: emit("mov ecx,[__areg+%s]\n", regs); break; case aind: case ainc: case adec: case adsp: case axdp: case absw: case absl: case pcdp: case pcxd: emit("call readmemory%s\n", sizename[size]); break; case immd: switch(size) { case 1: case 2: emit("mov cx,[esi]\n"); emit("add esi,byte 2\n"); break; case 4: emit("mov ecx,[esi]\n"); emit("add esi,byte 4\n"); emit("rol ecx,16\n"); break; default: emit("#error ea_step_read\n"); break; } break; default: emit("#error ea_step_read\n"); break; } } /* ** Special case for when you need to load a word and sign-extend it. ** This cuts some fat out of a few instructions (i.e. MOVEA). */ static void ea_step_read_signword(enum eamode mode, int reg) { char regs[100]; if(reg == -1) sprintf(regs, "ebx*4"); else sprintf(regs, "%d", reg * 4); switch(mode) { case dreg: emit("movsx ecx,word[__dreg+%s]\n", regs); break; case areg: emit("movsx ecx,word[__areg+%s]\n", regs); break; case aind: case ainc: case adec: case adsp: case axdp: case absw: case absl: case pcdp: case pcxd: emit("call readmemory%s\n", sizename[2]); emit("movsx ecx,cx\n"); break; case immd: emit("movsx ecx,word[esi]\n"); emit("add esi,byte 2\n"); break; default: emit("#error ea_step_read_signword\n"); break; } } static void ea_step_write(int size, enum eamode mode, int reg) { char regs[100]; if(reg == -1) sprintf(regs, "ebx*4"); else sprintf(regs, "%d", reg * 4); switch(mode) { case dreg: emit("mov [__dreg+%s],%s\n", regs, x86cx[size]); break; case aind: case ainc: case adec: case adsp: case axdp: case absw: case absl: emit("call writememory%s\n", sizename[size]); break; default: emit("#error ea_step_write\n"); break; } } static void ea_step_postcalc(int size, enum eamode mode, int reg) { char regs[100]; if(reg == -1) sprintf(regs, "ebx*4"); else sprintf(regs, "%d", reg * 4); switch(mode) { case ainc: /* Compensate for byte-sized stack ops */ if(size == 1) { if(reg == -1) { emit("cmp bl,7\n"); emit("sbb edx,byte -2\n"); } else if(reg == 7) { emit("add edx,byte 2\n"); } else { emit("inc edx\n"); } } else { emit("add edx,byte %d\n", size); } /* Fall through */ case adec: /* Store already-predecremented address */ emit("mov [__areg+%s],edx\n", regs); break; case dreg: case areg: case aind: case adsp: case axdp: case absw: case absl: case pcdp: case pcxd: case immd: break; default: emit("#error ea_step_postcalc\n"); break; } } /* Combined EA routines */ static void ea_load(int size, enum eamode mode, int reg) { ea_step_precalc (size, mode, reg); ea_step_read (size, mode, reg); ea_step_postcalc(size, mode, reg); } static void ea_load_signword(enum eamode mode, int reg) { ea_step_precalc (2, mode, reg); ea_step_read_signword( mode, reg); ea_step_postcalc (2, mode, reg); } static void ea_store(int size, enum eamode mode, int reg) { ea_step_precalc (size, mode, reg); ea_step_write (size, mode, reg); ea_step_postcalc(size, mode, reg); } static void ea_rmw_load(int size, enum eamode mode, int reg) { ea_step_precalc (size, mode, reg); ea_step_read (size, mode, reg); } static void ea_rmw_store(int size, enum eamode mode, int reg) { ea_step_write (size, mode, reg); ea_step_postcalc(size, mode, reg); } static void ea_control(enum eamode mode, int reg) { ea_step_precalc (0, mode, reg); } static void main_ea_load(void) { ea_load(main_size, main_eamode, -1); } static void main_ea_load_signed(void) { if(main_size < 4) { ea_load_signword(main_eamode, -1); } else { ea_load(main_size, main_eamode, -1); } } static void main_ea_store(void) { ea_store(main_size, main_eamode, -1); } static void main_ea_rmw_load(void) { ea_rmw_load(main_size, main_eamode, -1); } static void main_ea_rmw_store(void) { ea_rmw_store(main_size, main_eamode, -1); } static void main_ea_control(void) { ea_control(main_eamode, -1); } /***************************************************************************/ /* ** Calculate cycles for main EA mode ** (68000, 68010) */ static int main_ea_cycles(void) { int l; if(main_size == 4) l = 4; else l = 0; switch(main_eamode) { case aind: return(l + 4); case ainc: return(l + 4); case adec: return(l + 6); case adsp: return(l + 8); case axdp: return(l + 10); case absw: return(l + 8); case absl: return(l + 12); case pcdp: return(l + 8); case pcxd: return(l + 10); case immd: return(l + 4); default: break; } return 0; } /* Calculate cycles for main EA mode, without fetching (68010 only) */ static int main_ea_cycles_nofetch(void){ switch(main_eamode) { case aind: return(2); case ainc: return(4); case adec: return(4); case adsp: return(4); case axdp: return(8); case absw: return(4); case absl: return(8); default: break; } return 0; } /**************************************************************************** ** PREFIXES / SUFFIXES ****************************************************************************/ /* ** Prefixes - stuff that appears before the instruction handling routines */ static void prefixes(void) { /* Basic stuff - banner, variable section, API */ gen_banner(); gen_variables(); gen_interface(); /* Internal functions - PC rebasing, I/O, etc. */ gen_basefunction(); gen_decode_ext(); gen_readbw(1); gen_readbw(2); gen_readl(); gen_writebw(1); gen_writebw(2); gen_writel(); gen_group_12_exception(); gen_privilege_violation(); gen_flush_interrupts(); } /* ** Suffixes - stuff that appears after the instruction handling routines and ** the jump table / loop info table */ static void suffixes(void) { emit("end\n"); } /**************************************************************************** ** INSTRUCTION HANDLING ROUTINES ****************************************************************************/ /* called 600 times (!) */ static void i_move(void) { int cycles; selective_usereg(); main_ea_load(); ea_store(main_size, main_destmode, main_reg); selftest(main_size); flags_v0(); cycles = 4 + main_ea_cycles(); switch(main_destmode) { case aind: if(main_size == 4) cycles += 4; cycles += 4; break; case ainc: if(main_size == 4) cycles += 4; cycles += 4; break; case adec: if(main_size == 4) cycles += 4; cycles += 4; break; case adsp: if(main_size == 4) cycles += 4; cycles += 8; break; case axdp: if(main_size == 4) cycles += 4; cycles += 10; break; case absw: if(main_size == 4) cycles += 4; cycles += 8; break; case absl: if(main_size == 4) cycles += 4; cycles += 12; break; default: break; } /* Calculate loop mode timings */ if(cputype == 68010) { switch(main_eamode) { case dreg: case areg: switch(main_destmode) { case aind: case ainc: if(main_size <= 2) { loop_c_cycles = 2; loop_t_cycles = 10; loop_x_cycles = 8; }else{ loop_c_cycles = 2; loop_t_cycles = 8; loop_x_cycles = 6; } break; default:break; } break; case aind: case ainc: case adec: switch(main_destmode) { case aind: case ainc: loop_c_cycles = 2; loop_t_cycles = 8; loop_x_cycles = 6; break; case adec: loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; break; default:break; } break; default:break; } } ret_timing(cycles); } static void i_moveq(void) { emit("movsx ecx,bl\n"); emit("mov [__dreg+%d],ecx\n", main_reg * 4); selftest(1); flags_v0(); /* No loop mode */ ret_timing(4); } static void op_to_areg(char *s) { selective_usereg(); main_ea_load_signed(); /* sign extends to ecx where necessary */ emit("%s [__areg+%d],ecx\n", s, main_reg * 4); } static void i_movea(void) { op_to_areg("mov"); /* No loop mode */ ret_timing(4 + main_ea_cycles()); } /* ADDA or SUBA */ static void addsuba(char *op) { int base_cycles; op_to_areg(op); if(main_size==4){ base_cycles=6; /* Register direct / immediate penalty (68000) */ if(cputype==68000){ switch(main_eamode){ case areg:case dreg:case immd: base_cycles+=2; break; default:break; } } }else{ base_cycles=8; } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: if(main_size<=2){ loop_c_cycles = 6; loop_t_cycles = 12; loop_x_cycles = 10; }else{ loop_c_cycles = 8; loop_t_cycles = 14; loop_x_cycles = 12; } break; default:break; } } ret_timing(base_cycles+main_ea_cycles()); } static void i_adda(void){addsuba("add");} static void i_suba(void){addsuba("sub");} static void i_cmpa(void){ op_to_areg("cmp"); flags(); /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: if(main_size<=2){ loop_c_cycles = 2; loop_t_cycles = 8; loop_x_cycles = 6; }else{ loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 6; } break; default:break; } } ret_timing(6+main_ea_cycles()); } static void i_move_to_sr(void){ main_size=2; privilegecheck(); selective_usereg(); main_ea_load(); cx2sr(); /* No loop mode; check PPL and trace flag */ ret_timing_checkpoint(12+main_ea_cycles()); } static void i_move_to_ccr(void){ main_size=2;/* WEIRD! But it works! */ selective_usereg(); main_ea_load(); cl2ccr(); /* No loop mode */ ret_timing(12+main_ea_cycles()); } static void i_move_from_sr(void){ int cycles; /* This is privileged on 68010 and up */ if(cputype>=68010)privilegecheck(); main_size=2; selective_usereg(); sr2cx(); main_ea_store(); if(cputype==68010){ cycles=8+main_ea_cycles_nofetch(); }else{ cycles=8+main_ea_cycles(); } if((main_eamode==dreg)||(main_eamode==areg)){ cycles-=2; /* Speed demon 68010 can do it in 2 fewer cycles... :p */ if(cputype==68010)cycles-=2; } /* No loop mode */ ret_timing(cycles); } /* 68000/68008 aren't supposed to have this */ static void i_move_from_ccr(void){ int cycles; main_size=2; selective_usereg(); ccr2cl(); main_ea_store(); if(cputype==68010){ cycles=8+main_ea_cycles_nofetch(); }else{ cycles=8+main_ea_cycles(); } if((main_eamode==dreg)||(main_eamode==areg)){ cycles-=2; if(cputype==68010)cycles-=2; } /* No loop mode */ ret_timing(cycles); } static void op_to_ccr(char*op){ ccr2cl(); emit("%s cl,[esi]\n",op); emit("add esi,byte 2\n"); cl2ccr(); /* No loop mode */ ret_timing((cputype==68010)?16:20); } static void op_to_sr(char*op){ privilegecheck(); sr2cx(); emit("%s cx,[esi]\n",op); emit("add esi,byte 2\n"); cx2sr(); /* No loop mode */ /* Check PPL and trace flag */ ret_timing_checkpoint((cputype==68010)?16:20); } static void i_ori_ccr(void){op_to_ccr("or" );} static void i_andi_ccr(void){op_to_ccr("and");} static void i_eori_ccr(void){op_to_ccr("xor");} static void i_ori_sr (void){op_to_sr ("or" );} static void i_andi_sr (void){op_to_sr ("and");} static void i_eori_sr (void){op_to_sr ("xor");} static void i_clr(void){ int cycles=0; selective_usereg(); emit("xor ecx,ecx\n"); main_ea_store(); if(cputype==68000){ cycles=main_ea_cycles(); if((main_eamode==dreg)||(main_eamode==areg)){ cycles+=4;if(main_size==4)cycles+=4; }else{ cycles+=6;if(main_size==4)cycles+=6; } }else if(cputype==68010){ switch(main_eamode){ case dreg:cycles= 4;break; case aind:cycles= 8;break; case ainc:cycles= 8;break; case adec:cycles=10;break; case adsp:cycles=12;break; case axdp:cycles=16;break; case absw:cycles=12;break; case absl:cycles=16;break; default:break; } if(main_size==4){ cycles+=4; if(main_eamode==dreg)cycles-=2; } /* Calculate loop mode timings */ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 2; loop_t_cycles = 10; loop_x_cycles = 8; break; default:break; } } emit("mov ax,4000h\n"); ret_timing(cycles); } static void i_tst(void){ selective_usereg(); main_ea_load(); /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: if(main_size<=2){ loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; }else{ loop_c_cycles = 6; loop_t_cycles = 12; loop_x_cycles = 8; } break; default:break; } } selftest(main_size); flags_v0(); ret_timing(4+main_ea_cycles()); } /* Always affects X flag ** (except for #,An which affects no flags whatsoever) */ static void op_quick(char*op){ int cycles; selective_usereg(); if(main_eamode==dreg){ emit( "%s %s[__dreg+ebx*4],byte %d\n", op,sizename[main_size],quickvalue[main_qv] ); flags(); c2x(); cycles=4; }else if(main_eamode==areg){ emit( "%s dword[__areg+ebx*4],byte %d\n", op,quickvalue[main_qv] ); cycles=4; /* SUBQ.W #,An incurs 4-cycle penalty (68000 only) */ if(cputype==68000){ if((main_size==2)&&(op[0]=='s'))cycles+=4; } }else{ main_ea_rmw_load(); emit( "%s %s,byte %d\n",op,x86cx[main_size],quickvalue[main_qv] ); flags(); c2x(); main_ea_rmw_store(); cycles=8+main_ea_cycles(); } if(main_size==4)cycles+=4; /* No loop mode */ ret_timing(cycles); } static void i_addq(void){op_quick("add");} static void i_subq(void){op_quick("sub");} static void op_to_dn(char*op,int affectx,int logical){ int cycles; selective_usereg(); main_ea_load(); emit("%s [__dreg+%d],%s\n", op,main_reg*4,x86cx[main_size] ); if(logical){ flags_v0(); }else{ flags(); } if(affectx)c2x(); cycles=4+main_ea_cycles(); if(main_size==4){ cycles+=2; /* Register direct / immediate penalty (68000) */ if((cputype==68000)&&(op[0]!='c')){ switch(main_eamode){ case areg:case dreg:case immd: cycles+=2; break; default:break; } } } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: switch(op[0]){ case 'a':/* ADD, AND */ case 'o':/* OR */ loop_c_cycles = 8; loop_t_cycles = 14; loop_x_cycles = 12; break; case 's':/* SUB */ if(main_size<=2){ loop_c_cycles = 8; loop_t_cycles = 14; loop_x_cycles = 12; }else{ loop_c_cycles = 6; loop_t_cycles = 12; loop_x_cycles = 10; } break; case 'c':/* CMP */ loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; if(main_size==4)loop_x_cycles = 6; break; default:break; } break; default:break; } } ret_timing(cycles); } static void i_cmp_dn(void){op_to_dn("cmp",0,0);} static void i_add_dn(void){op_to_dn("add",1,0);} static void i_sub_dn(void){op_to_dn("sub",1,0);} static void i_and_dn(void){op_to_dn("and",0,1);} static void i_or_dn (void){op_to_dn("or" ,0,1);} static void op_to_ea(char*op,int logical){ int cycles; selective_usereg(); main_ea_rmw_load(); emit( "%s %s,[__dreg+%d]\n", op,x86cx[main_size],main_reg*4 ); if(logical){ flags_v0(); }else{ flags(); } /* Logical instructions don't affect X flag */ if(!logical)c2x(); main_ea_rmw_store(); cycles=8+main_ea_cycles(); if(main_size==4)cycles+=4; /* EOR Dn,Dn takes fewer cycles than we'd expect */ if((op[0]=='x')&&(main_eamode==dreg)){ cycles-=4; if(cputype==68010)cycles-=2; } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; break; default:break; } } ret_timing(cycles); } static void i_eor_ea(void){op_to_ea("xor",1);} static void i_add_ea(void){op_to_ea("add",0);} static void i_sub_ea(void){op_to_ea("sub",0);} static void i_and_ea(void){op_to_ea("and",1);} static void i_or_ea (void){op_to_ea("or" ,1);} /* called 144 times */ /* ** c1: Total cycles for #,Dn (byte/word) ** c2: Total cycles for #,Dn (long) ** c3: Basic cycles for #,M (byte/word) ** c4: Basic cycles for #,M (long) */ static void im_to_ea(char*op,int wback,int affectx,int logical, int c1,int c2,int c3,int c4){ int cycles; selective_usereg(); switch(main_size){ case 1: case 2: emit("mov cx,[esi]\n"); emit("add esi,byte 2\n"); break; case 4: emit("mov ecx,[esi]\n"); emit("rol ecx,16\n"); emit("add esi,byte 4\n"); break; default:break; } if(main_eamode==dreg){ emit("%s [__dreg+ebx*4],%s\n", op,x86cx[main_size] ); if(logical){ flags_v0(); }else{ flags(); } if(affectx)c2x(); if(main_size<4)cycles=c1;else cycles=c2; }else{ emit("push ecx\n"); if(wback)main_ea_rmw_load();else main_ea_load(); emit("%s %s,[esp]\n",op,x86cx[main_size]); if(logical){ flags_v0(); }else{ flags(); } if(affectx)c2x(); emit("add esp,byte 4\n"); if(wback)main_ea_rmw_store(); if(main_size<4)cycles=c3;else cycles=c4; cycles+=main_ea_cycles(); } /* No loop mode */ ret_timing(cycles); } /* each called 24 times */ static void i_addi(void){im_to_ea("add",1,1,0,8,(cputype==68010)?14:16,12,20);} static void i_subi(void){im_to_ea("sub",1,1,0,8,(cputype==68010)?14:16,12,20);} static void i_cmpi(void){im_to_ea("cmp",0,0,0,8,(cputype==68010)?12:14, 8,12);} static void i_andi(void){im_to_ea("and",1,0,1,8,(cputype==68010)?14:14,12,20);} static void i_ori (void){im_to_ea("or" ,1,0,1,8,(cputype==68010)?14:16,12,20);} static void i_eori(void){im_to_ea("xor",1,0,1,8,(cputype==68010)?14:16,12,20);} static void flick_reg(char*op,int needxf,int affectx,int asl,int rotate){ int cycles; char tmps[5]; int i; usereg(); cycles=6; if(main_size==4)cycles+=2; /* ASR doesn't need overflow checking */ if(direction[main_dr]=='r')asl=0; if(main_ir==1){ int myline=linenum;linenum++; emit("mov ecx,[__dreg+%d]\n",main_reg*4); emit("and ecx,byte 63\n"); emit("jnz short ln%d\n",myline); /* The shift count was zero. Strange things are about to ** happen... */ ea_load(main_size,dreg,-1);/* get data in eax */ selftest(main_size); flags_v0(); if(needxf){/* ROXL/ROXR: Set C flag equal to X */ emit("and ah,0FEh\n"); emit("or ah,[__xflag]\n"); } ret_timing(cycles); /* Shift count non-zero */ emit("ln%d:\n",myline); emit("sub edi,ecx\n"); emit("sub edi,ecx\n"); sprintf(tmps,"cl"); }else{ sprintf(tmps,"%d",quickvalue[main_reg]); cycles+=2*quickvalue[main_reg]; } if(asl){ switch(tmps[0]){ case 'c':/* register shift count */ emit("mov edx,[__dreg+ebx*4]\n"); emit("mov al,0\n");/* overflow starts at 0 */ emit("ln%d:\n",linenum); emit("add %s,%s\n", x86dx[main_size],x86dx[main_size] ); emit("lahf\n");/* grab N,Z,C flags */ emit("seto ch\n"); emit("or al,ch\n");/* add overflow */ emit("dec cl\n"); emit("jnz short ln%d\n",linenum);linenum++; emit("mov [__dreg+ebx*4],%s\n",x86dx[main_size]); if(affectx){ emit("mov cl,ah\n"); emit("and cl,1\n"); emit("mov [__xflag],cl\n"); } break; case '1':/* immediate shift count ==1 */ emit("sal %s[__dreg+ebx*4],1\n", sizename[main_size] ); flags(); if(affectx)c2x(); break; default:/* immediate shift count >1 */ emit("mov edx,[__dreg+ebx*4]\n"); emit("mov al,0\n");/* overflow starts at 0 */ for(i='1';i<=tmps[0];i++){ emit("add %s,%s\n", x86dx[main_size],x86dx[main_size] ); if(i==tmps[0]){ /* grab N,Z,C flags */ emit("lahf\n"); } emit("seto ch\n"); emit("or al,ch\n");/* add overflow */ } emit("mov [__dreg+ebx*4],%s\n",x86dx[main_size]); if(affectx){ emit("mov cl,ah\n"); emit("and cl,1\n"); emit("mov [__xflag],cl\n"); } break; } }else{ if(rotate){ emit("mov edx,[__dreg+ebx*4]\n"); if(needxf){ emit("mov al,[__xflag]\n"); emit("shr al,1\n"); }else{ emit("mov al,0\n"); } emit("%s%c %s,%s\n", op,direction[main_dr],x86dx[main_size],tmps ); emit("adc al,al\n"); emit("or %s,%s\n", x86dx[main_size],x86dx[main_size] ); emit("lahf\n"); emit("or ah,al\n"); if(affectx){ emit("mov [__xflag],al\n"); } emit("mov al,0\n"); emit("mov [__dreg+ebx*4],%s\n",x86dx[main_size]); }else{ if(needxf){ emit("mov al,[__xflag]\n"); emit("shr al,1\n"); }else{ emit("mov al,0\n"); } emit("%s%c %s[__dreg+ebx*4],%s\n", op,direction[main_dr],sizename[main_size],tmps ); emit("lahf\n"); if(affectx)c2x(); } } /* No loop mode */ ret_timing(cycles); } static void i_lsx_reg(void){flick_reg("sh",0,1,0,0);} static void i_asx_reg(void){flick_reg("sa",0,1,1,0);} static void i_rox_reg(void){flick_reg("ro",0,0,0,1);} static void i_rxx_reg(void){flick_reg("rc",1,1,0,1);} static void flick_mem(char*op,int needxf,int affectx,int vf,int rotate){ /* ASR doesn't need overflow checking */ if(direction[main_dr]=='r')vf=0; main_size=2; selective_usereg(); main_ea_rmw_load(); if(needxf){ emit("mov al,[__xflag]\n"); emit("shr al,1\n"); }else{ if(rotate)emit("mov al,0\n"); } emit("%s%c cx,1\n",op,direction[main_dr]); if(rotate){ emit("adc al,al\n"); emit("test cx,cx\n"); emit("lahf\n"); emit("or ah,al\n"); if(affectx)emit("mov [__xflag],al\n"); emit("mov al,0\n"); }else{ if(vf){ flags(); }else{ flags_v0(); } if(affectx)c2x(); } main_ea_rmw_store(); /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 6; loop_t_cycles = 12; loop_x_cycles = 10; break; default:break; } } ret_timing(8+main_ea_cycles()); } static void i_lsx_mem(void){flick_mem("sh",0,1,0,0);} static void i_asx_mem(void){flick_mem("sa",0,1,1,0);} static void i_rox_mem(void){flick_mem("ro",0,0,0,1);} static void i_rxx_mem(void){flick_mem("rc",1,1,0,1);} static int created_bra_b=0; static void i_bra_b(void){ if(!created_bra_b){emit("r_bra_b:\n");created_bra_b=1;} emit("movsx ebx,bl\n"); emit("add esi,ebx\n"); emit("xor ebx,ebx\n"); ret_timing(10); } static int created_bra_w=0; static void i_bra_w(void){ if(!created_bra_w){emit("r_bra_w:\n");created_bra_w=1;} emit("movsx ebx,word[esi]\n"); emit("add esi,ebx\n"); emit("xor ebx,ebx\n"); ret_timing(10); } static void i_bsr_b(void){ emit("movsx ebx,bl\n"); emit("mov ecx,esi\n"); emit("sub ecx,ebp\n"); emit("add esi,ebx\n"); emit("xor ebx,ebx\n"); ea_store(4,adec,7); ret_timing(18); } static void i_bsr_w(void){ emit("movsx ebx,word[esi]\n"); emit("mov ecx,esi\n"); emit("add ecx,byte 2\n"); emit("sub ecx,ebp\n"); emit("add esi,ebx\n"); emit("xor ebx,ebx\n"); ea_store(4,adec,7); ret_timing(18); } static void i_bcc_b(void){ getcondition(main_cc); emit("j%s near r_bra_b\n",optcc); ret_timing((cputype==68010)?6:8); } static void i_bcc_w(void){ getcondition(main_cc); emit("j%s near r_bra_w\n",optcc); emit("add esi,byte 2\n");/* skip relative offset */ ret_timing(12); } /* called once */ static void i_dbra(void){ emit("r_dbra:\n"); usereg(); if(cputype==68010){ emit("movsx ecx,word[esi]\n"); emit("cmp ecx,byte -4\n"); emit("je short r_loopmode_dbra\n"); /* Regular DBRA */ emit("r_regular_dbra:\n"); emit("sub word[__dreg+ebx*4],byte 1\n"); emit("jc short r_dbra_expire\n"); emit("add esi,ecx\n"); ret_timing(10); emit("r_dbra_expire:\n"); emit("add esi,byte 2\n"); ret_timing(16); /* Loop mode DBRA */ emit("r_loopmode_dbra:\n"); emit("cmp byte[__loopmode],0\n"); emit("jnz short r_loopmode_dbra_inloop\n"); emit("mov byte[__loopmode],1\n"); emit("jmp short r_regular_dbra\n"); emit("r_loopmode_dbra_inloop:\n"); emit("sub word[__dreg+ebx*4],byte 1\n"); emit("jc short r_loopmode_dbra_expire\n"); /* Continue */ emit("mov bx,word[esi-4]\n"); emit("add esi,ecx\n"); /* Subtract continuation cycles */ emit("mov cl,byte[__looptbl+ebx]\n"); emit("and ecx,byte 0Eh\n"); emit("sub edi,ecx\n"); ret_timing(0); /* Expire */ emit("r_loopmode_dbra_expire:\n"); emit("mov bx,word[esi-4]\n"); emit("mov byte[__loopmode],0\n"); /* Subtract continuation and extra expiration cycles */ emit("mov cl,byte[__looptbl+ebx]\n"); emit("mov ebx,ecx\n"); emit("rol cl,2\n"); emit("add esi,byte 2\n"); emit("and ebx,byte 0Eh\n"); emit("and ecx,byte 06h\n"); emit("sub edi,ebx\n"); emit("sub edi,ecx\n"); ret_timing(0); /* Terminate (visited externally by i_dbcc) */ emit("r_dbra_terminate:\n"); emit("cmp word[esi],byte -4\n"); emit("jne short r_dbra_terminate_regular\n"); emit("cmp byte[__loopmode],0\n"); emit("je short r_dbra_terminate_regular\n"); emit("mov bx,word[esi-4]\n"); emit("mov byte[__loopmode],0\n"); /* Subtract termination cycles */ emit("mov cl,byte[__looptbl+ebx]\n"); emit("shr cl,3\n"); emit("add esi,byte 2\n"); emit("and ecx,byte 0Eh\n"); emit("sub edi,ecx\n"); ret_timing(0); emit("r_dbra_terminate_regular:\n"); ret_timing(10); }else{ emit("sub word[__dreg+ebx*4],byte 1\n"); emit("jnc near r_bra_w\n"); emit("add esi,byte 2\n"); ret_timing(14); } } static void i_dbcc(void){ getcondition(main_cc); emit("j%s near r_dbra\n",optrc); /* Terminate */ if(cputype==68010){ emit("jmp r_dbra_terminate\n"); }else{ emit("add esi,byte 2\n"); ret_timing(12); } } static void i_scc(void){ int cycles; main_size=1; selective_usereg(); if(main_cc>1){ if((main_eamode==dreg)||(main_eamode==areg)){ if(cputype==68000){ emit("xor ecx,ecx\n"); } getcondition(main_cc); emit("set%s cl\n",optcc); if(cputype==68000){ /* 2 extra cycles if it's true */ emit("sub edi,ecx\n"); emit("sub edi,ecx\n"); } emit("neg cl\n"); cycles=4; }else{ getcondition(main_cc); emit("set%s cl\n",optcc); emit("neg cl\n"); cycles=8; } }else{ emit("mov cl,%d\n",(main_cc^1)*0xFF); if((main_eamode==dreg)||(main_eamode==areg)){ cycles=4; if(cputype==68000){ /* 2 extra cycles if it's true */ if(!main_cc)cycles+=2; } }else{ cycles=8; } } main_ea_store(); if(cputype==68010){ cycles+=main_ea_cycles_nofetch(); }else{ cycles+=main_ea_cycles(); } /* No loop mode */ ret_timing(cycles); } /* bit operations */ /* called 315 times */ /* 0=btst,1=bchg,2=bclr,3=bset */ static void bitop(int static_cycles){ int cycles; selective_usereg(); emit("and ecx,byte %d\n",(main_eamode==dreg)?31:7); if(main_eamode==dreg){ main_size=4; if(!main_cc){/* BTST */ emit("mov edx,1\n"); emit("shl edx,cl\n"); emit("test [__dreg+ebx*4],edx\n"); flag_to_z("z"); }else{ emit("mov edx,1\n"); emit("shl edx,cl\n"); emit("mov ecx,[__dreg+ebx*4]\n"); emit("test ecx,edx\n"); flag_to_z("z"); switch(main_cc){ case 1:emit("xor ecx,edx\n");break; case 2:emit("not edx\nand ecx,edx\n");break; case 3:emit("or ecx,edx\n");break; default:break; } emit("mov [__dreg+ebx*4],ecx\n"); } cycles=6+static_cycles; if(main_cc)cycles+=2; if(main_cc==2)cycles+=2; }else{ main_size=1; if(!main_cc){ emit("push ecx\n"); main_ea_load(); emit("mov edx,ecx\n"); emit("pop ecx\n"); emit("inc cl\n"); emit("shr dl,cl\n"); flag_to_z("nc"); }else{ emit("mov dl,1\n"); emit("shl dl,cl\n"); emit("push edx\n"); main_ea_rmw_load(); emit("xchg edx,[esp]\n"); emit("test cl,dl\n"); flag_to_z("z"); switch(main_cc){ case 1:emit("xor cl,dl\n");break; case 2:emit("not dl\nand cl,dl\n");break; case 3:emit("or cl,dl\n");break; default:break; } emit("pop edx\n"); main_ea_rmw_store(); } cycles=4+static_cycles+main_ea_cycles(); if(main_cc)cycles+=4; if((cputype==68010)&&(main_cc==2))cycles+=2; } ret_timing(cycles); } /* called 35 times */ static void i_bitop_imm(void){ emit("mov cl,[esi]\n"); emit("add esi,byte 2\n"); bitop(4); } /* called 280 times */ static void i_bitop_reg(void){ emit("mov cl,byte[__dreg+%d]\n",main_reg*4); bitop(0); } static void i_jmp(void){ int cycles=0; selective_usereg(); main_ea_control(); emit("mov esi,edx\n"); perform_cached_rebase(); switch(main_eamode){ case aind:cycles= 8;break; case adsp:cycles=10;break; case axdp:cycles=14;break; case absw:cycles=10;break; case absl:cycles=12;break; case pcdp:cycles=10;break; case pcxd:cycles=14;break; default:break; } /* No loop mode */ ret_timing(cycles); } static void i_jsr(void){ int cycles=0; selective_usereg(); main_ea_control(); emit("mov ecx,esi\n"); emit("sub ecx,ebp\n"); emit("mov esi,edx\n"); perform_cached_rebase(); ea_store(4,adec,7); switch(main_eamode){ case aind:cycles=16;break; case adsp:cycles=18;break; case axdp:cycles=22;break; case absw:cycles=18;break; case absl:cycles=20;break; case pcdp:cycles=18;break; case pcxd:cycles=22;break; default:break; } /* No loop mode */ ret_timing(cycles); } static void i_rts(void){ ea_load(4,ainc,7); emit("mov esi,ecx\n"); perform_cached_rebase(); /* No loop mode */ ret_timing(16); } /* 68010 and higher */ static void i_rtd(void){ emit("mov edx,[__a7]\n"); emit("call readmemorydword\n"); emit("movsx ebx,word[esi]\n"); emit("add edx,ebx\n"); emit("mov esi,ecx\n"); emit("add edx,byte 4\n"); emit("xor ebx,ebx\n"); emit("mov [__a7],edx\n"); perform_cached_rebase(); /* No loop mode */ ret_timing(16); } static void i_rtr(void){ ea_load(2,ainc,7); cl2ccr(); ea_load(4,ainc,7); emit("mov esi,ecx\n"); perform_cached_rebase(); /* No loop mode */ ret_timing(20); } static void i_rte(void){ int myline=linenum; linenum++; privilegecheck(); if(cputype>=68010){ /* Check stack frame format - must be 0xxx or 8xxx */ emit("mov edx,[__a7]\n"); emit("add edx,byte 6\n"); emit("call readmemory%s\n",sizename[2]); emit("test ch,70h\n"); emit("jnz short ln%d_formatok\n",myline); /* Generate Format Error exception where necessary */ emit("mov edx,38h\n"); emit("call group_1_exception\n"); perform_cached_rebase(); ret_timing(50);/* RTE, Illegal Format */ emit("ln%d_formatok:\n",myline); /* Now _we_ check to make sure the format isn't 8xxx (since ** that's not implemented yet). */ emit("or ch,ch\n"); emit("jns short ln%d_formatok2\n",myline); /* Double fault with error code 80000002h. */ emit("mov ecx,80000002h\n"); emit("or byte[__pc],1\n"); emit("or byte[__interrupts],1\n"); emit("jmp execexit\n"); emit("ln%d_formatok2:\n",myline); /* Now RTE as usual */ emit("sub edx,byte 6\n"); emit("call readmemory%s\n",sizename[2]); emit("add edx,byte 2\n"); cx2sr(); emit("test ch,20h\n"); emit("jz short ln%d_nosupe\n",myline); emit("add dword [__a7],byte 8\n"); emit("jmp short ln%d_finish\n",myline); emit("ln%d_nosupe:\n",myline); emit("add dword [__asp],byte 8\n"); emit("ln%d_finish:\n",myline); emit("call readmemory%s\n",sizename[4]); emit("mov esi,ecx\n"); perform_cached_rebase(); ret_timing_checkpoint(24);/* RTE with no trouble */ }else{ emit("mov edx,[__a7]\n"); emit("call readmemory%s\n",sizename[2]); emit("add edx,byte 2\n"); cx2sr(); emit("test ch,20h\n"); emit("jz short ln%d_nosupe\n",myline); emit("add dword [__a7],byte 6\n"); emit("jmp short ln%d_finish\n",myline); emit("ln%d_nosupe:\n",myline); emit("add dword [__asp],byte 6\n"); emit("ln%d_finish:\n",myline); emit("call readmemory%s\n",sizename[4]); emit("mov esi,ecx\n"); perform_cached_rebase(); ret_timing_checkpoint(20); } } static void i_lea(void){ int cycles=0; selective_usereg(); main_ea_control(); emit("mov [__areg+%d],edx\n",main_reg*4); switch(main_eamode){ case aind:cycles= 4;break; case adsp:cycles= 8;break; case axdp:cycles=12;break; case absw:cycles= 8;break; case absl:cycles=12;break; case pcdp:cycles= 8;break; case pcxd:cycles=12;break; default:break; } /* No loop mode */ ret_timing(cycles); } static void i_pea(void){ int cycles=0; selective_usereg(); main_ea_control(); emit("mov ecx,edx\n"); ea_store(4,adec,7); switch(main_eamode){ case aind:cycles=12;break; case adsp:cycles=16;break; case axdp:cycles=20;break; case absw:cycles=16;break; case absl:cycles=20;break; case pcdp:cycles=16;break; case pcxd:cycles=20;break; default:break; } /* No loop mode */ ret_timing(cycles); } static void i_nop(void){ /* No loop mode */ ret_timing(4); } static void i_movem_control(void){ int cycles=0; int myline=linenum;linenum+=2; emit("push eax\n"); selective_usereg(); emit("mov ax,[esi]\n"); emit("add esi,byte 2\n"); main_ea_control(); emit("xor ebx,ebx\n"); emit("ln%d:\n",myline); emit("shr eax,1\n"); emit("jnc short ln%d\n",myline+1); if(main_dr==0){/*register->memory*/ switch(main_eamode){ case aind:cycles= 8;break; case adsp:cycles=12;break; case axdp:cycles=14;break; case absw:cycles=12;break; case absl:cycles=16;break; default:break; } emit("mov ecx,[__reg+ebx]\n"); emit("call writememory%s\n",sizename[main_size]); }else{/*memory->register*/ switch(main_eamode){ case aind:cycles=12; if((cputype==68010)&&(main_size==4))cycles=24; break; case adsp:cycles=16;break; case axdp:cycles=18;break; case absw:cycles=16;break; case absl:cycles=20;break; case pcdp:cycles=16;break; case pcxd:cycles=18;break; default:break; } emit("call readmemory%s\n",sizename[main_size]); if(main_size==2)emit("movsx ecx,cx\n"); emit("mov [__reg+ebx],ecx\n"); } emit("add edx,byte %d\n",main_size); emit("sub edi,byte %d\n",main_size*2); emit("ln%d:\n",myline+1); emit("add ebx,byte 4\n"); emit("cmp ebx,byte 64\n"); emit("jne short ln%d\n",myline); emit("pop eax\n"); ret_timing(cycles); } static void i_movem_postinc(void){ int myline=linenum;linenum+=2; usereg(); emit("push eax\n"); emit("mov ax,[esi]\n"); emit("add esi,byte 2\n"); emit("mov edx,[__areg+ebx*4]\n"); emit("push ebx\n"); emit("xor ebx,ebx\n"); emit("ln%d:\n",myline); emit("shr eax,1\n"); emit("jnc short ln%d\n",myline+1); emit("call readmemory%s\n",sizename[main_size]); if(main_size==2)emit("movsx ecx,cx\n"); emit("mov [__reg+ebx],ecx\n"); emit("add edx,byte %d\n",main_size); emit("sub edi,byte %d\n",main_size*2); emit("ln%d:\n",myline+1); emit("add ebx,byte 4\n"); emit("cmp ebx,byte 64\n"); emit("jne short ln%d\n",myline); emit("pop ebx\n"); emit("pop eax\n"); emit("mov [__areg+ebx*4],edx\n"); ret_timing(12); } static void i_movem_predec(void){ int myline=linenum;linenum+=2; usereg(); emit("push eax\n"); emit("mov ax,[esi]\n"); emit("add esi,byte 2\n"); emit("mov edx,[__areg+ebx*4]\n"); emit("push ebx\n"); emit("mov ebx,60\n"); emit("ln%d:\n",myline); emit("shr eax,1\n"); emit("jnc short ln%d\n",myline+1); emit("mov ecx,[__reg+ebx]\n"); emit("sub edx,byte %d\n",main_size); emit("sub edi,byte %d\n",main_size*2); emit("call writememory%s\n",sizename[main_size]); emit("ln%d:\n",myline+1); emit("sub ebx,byte 4\n"); emit("jns short ln%d\n",myline); emit("pop ebx\n"); emit("pop eax\n"); emit("mov [__areg+ebx*4],edx\n"); ret_timing(8); } static void i_link(void){ usereg(); emit("mov ecx,[__areg+ebx*4]\n"); ea_store(4,adec,7); emit("mov ecx,[__a7]\n"); emit("mov [__areg+ebx*4],ecx\n"); emit("movsx edx,word[esi]\n"); emit("add ecx,edx\n"); emit("mov [__a7],ecx\n"); emit("add esi,byte 2\n"); ret_timing(16); } static void i_unlk(void){ usereg(); emit("mov ecx,[__areg+ebx*4]\n"); emit("mov [__a7],ecx\n"); ea_load(4,ainc,7); emit("mov [__areg+ebx*4],ecx\n"); ret_timing(12); } static void i_move_from_usp(void){ privilegecheck(); /* makes our job much easier... */ usereg(); emit("mov ecx,[__asp]\n"); emit("mov [__areg+ebx*4],ecx\n"); ret_timing((cputype==68010)?6:4); } static void i_move_to_usp(void){ privilegecheck(); usereg(); emit("mov ecx,[__areg+ebx*4]\n"); emit("mov [__asp],ecx\n"); ret_timing((cputype==68010)?6:4); } static void i_trap(void){ emit("and ebx,byte 0Fh\n"); emit("lea edx,[80h+ebx*4]\n"); emit("call group_2_exception\n"); perform_cached_rebase(); ret_timing((cputype==68010)?38:34); } static void i_trapv(void){ int myline=linenum;linenum++; emit("test al,1\n"); emit("jnz short ln%d\n",myline); ret_timing(4); emit("ln%d:\n",myline); emit("mov edx,1Ch\n"); emit("call group_2_exception\n"); perform_cached_rebase(); ret_timing(4+((cputype==68010)?38:34)); } static void i_stop(void){ int myline=linenum;linenum++; privilegecheck(); emit("mov cx,[esi]\n"); emit("add esi,2\n"); cx2sr(); emit("or byte[__interrupts],1\n"); /* Forfeit all remaining cycles */ emit("sub edi,byte 4\n"); emit("js short ln%d\n",myline); emit("xor edi,edi\n"); emit("dec edi\n"); emit("ln%d:\n",myline); ret_timing(0); } static void i_extbw(void){ usereg(); emit("movsx cx,byte[__dreg+ebx*4]\n"); emit("mov [__dreg+ebx*4],cx\n"); selftest(2); flags_v0(); ret_timing(4); } static void i_extwl(void){ usereg(); emit("movsx ecx,word[__dreg+ebx*4]\n"); emit("mov [__dreg+ebx*4],ecx\n"); selftest(4); flags_v0(); ret_timing(4); } static void i_swap(void){ usereg(); emit("mov ecx,[__dreg+ebx*4]\n"); emit("rol ecx,16\n"); emit("mov [__dreg+ebx*4],ecx\n"); selftest(4); flags_v0(); ret_timing(4); } /* if main_cc==1 then it's signed */ static void i_mul(void){ int base_cycles; selective_usereg(); main_size=2; main_ea_load(); emit("mov eax,ecx\n"); /* Finally! Real MULS/MULU timing! */ if(cputype==68000){ emit("mov dl,0\n"); emit("mov bl,16\n"); emit("ln%d:\n",linenum); emit("add cx,cx\n"); if(main_cc==1){ /* MULS: count the number of 10 or 01 pairs */ emit("seto dh\n"); emit("add dl,dh\n"); }else{ /* MULU: count the number of 1s */ emit("adc dl,0\n"); } emit("dec bl\n"); emit("jnz ln%d\n",linenum);linenum++; emit("and edx,byte 127\n"); emit("sub edi,edx\n"); emit("sub edi,edx\n"); } emit("%smul word[__dreg+%d]\n", (main_cc==1)?"i":"",main_reg*4 ); emit("shl edx,16\n"); emit("and eax,0FFFFh\n"); emit("mov ecx,edx\n"); emit("or ecx,eax\n"); flags_v0(); emit("mov [__dreg+%d],ecx\n",main_reg*4); if(cputype==68010){ /* Maximum is 42 signed, 40 unsigned */ base_cycles=36; if(main_cc)base_cycles+=2; }else{ /* 38+2n, signed or unsigned, maximum is 70 */ base_cycles=38; } /* No loop mode */ ret_timing(base_cycles+main_ea_cycles()); } /* if main_cc=1 then it's signed */ static void i_div(void){ int base_cycles; int myline=linenum;linenum+=2; selective_usereg(); main_size=2; main_ea_load(); emit("test cx,cx\n"); emit("jnz short ln%d\n",myline); /* Forgot to put on our Division by Zero Suit... */ emit("mov edx,14h\n"); emit("call group_2_exception\n"); perform_cached_rebase(); base_cycles=38; if(cputype==68010)base_cycles+=4; ret_timing(base_cycles+main_ea_cycles()); emit("ln%d:\n",myline);myline++; if(main_cc){ emit("movsx ecx,cx\n"); }else{ emit("and ecx,0FFFFh\n"); } emit("mov eax,[__dreg+%d]\n",main_reg*4); if(main_cc){ emit("mov edx,eax\n"); emit("sar edx,31\n"); }else{ emit("xor edx,edx\n"); } emit("%sdiv ecx\n",main_cc?"i":""); if(main_cc){ emit("mov ecx,eax\n"); emit("sar cx,15\n"); emit("or ecx,ecx\n"); emit("je short ln%d\n",linenum); emit("inc ecx\n"); emit("jne short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("and eax,0FFFFh\n"); }else{ emit("test eax,0FFFF0000h\n"); emit("jnz short ln%d\n",myline); } emit("shl edx,16\n"); emit("mov dx,ax\n"); emit("test dx,dx\n"); flags_v0(); emit("mov [__dreg+%d],edx\n",main_reg*4); if(cputype==68010){ base_cycles=108; if(main_cc)base_cycles=122; }else{ /* Varies from 142-158 signed, 126-140 unsigned */ base_cycles=133; if(main_cc)base_cycles=150; } ret_timing(base_cycles+main_ea_cycles()); /* Overflow */ emit("ln%d:\n",myline);myline++; emit("mov ax,1\n"); /* No loop mode */ ret_timing(base_cycles+main_ea_cycles()); } static void i_neg(void){ int cycles; selective_usereg(); cycles=4; if(main_size==4)cycles=6; if(main_eamode==dreg){ emit("neg %s[__dreg+ebx*4]\n", sizename[main_size] ); flags(); c2x(); }else{ cycles*=2; main_ea_rmw_load(); emit("neg %s\n",x86cx[main_size]); flags(); c2x(); main_ea_rmw_store(); cycles+=main_ea_cycles(); } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; break; default:break; } } ret_timing(cycles); } static void i_negx(void){ int cycles; selective_usereg(); cycles=4; if(main_size==4)cycles=6; if(main_eamode==dreg){ emit("mov cl,[__xflag]\n"); emit("shr cl,1\n"); if(main_size==1)emit("mov cl,0\n"); else emit("mov ecx,0\n"); emit("sbb %s,[__dreg+ebx*4]\n",x86cx[main_size]); emit("mov edx,eax\n"); flags();c2x(); adjzero("dh"); emit("mov [__dreg+ebx*4],%s\n",x86cx[main_size]); }else{ cycles*=2; main_ea_rmw_load(); emit("push ebx\n"); emit("mov bl,[__xflag]\n"); emit("shr bl,1\n"); if(main_size==1)emit("mov bl,0\n"); else emit("mov ebx,0\n"); emit("sbb %s,%s\n",x86bx[main_size],x86cx[main_size]); emit("mov ecx,ebx\n"); emit("mov ebx,eax\n"); flags();c2x(); adjzero("bh"); emit("pop ebx\n"); main_ea_rmw_store(); cycles+=main_ea_cycles(); } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; break; default:break; } } ret_timing(cycles); } static void i_nbcd(void){ int cycles; main_size=1; selective_usereg(); main_ea_rmw_load(); /* Get the X flag into carry */ emit("mov cl,[__xflag]\n"); emit("shr cl,1\n"); /* Save the previous Z flag in CH */ emit("mov ch,ah\n"); /* Perform the BCD subtraction */ emit("mov al,0\n"); emit("sbb al,cl\n"); emit("das\n"); /* Save result in CL */ emit("mov cl,al\n"); /* Set flags - V undefined */ flags_v0(); c2x(); /* Adjust for non-changing Z (previous Z flag in CH) */ adjzero("ch"); main_ea_rmw_store(); if(main_eamode==dreg){ cycles=6; }else{ cycles=8+main_ea_cycles(); } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 6; loop_t_cycles = 12; loop_x_cycles = 10; break; default:break; } } ret_timing(cycles); } static void i_tas(void){ int cycles; main_size=1; selective_usereg(); main_ea_rmw_load(); selftest(1); flags_v0(); emit("or cl,80h\n"); main_ea_rmw_store(); if((main_eamode==dreg)||(main_eamode==areg)){ cycles=4; }else{ cycles=14+main_ea_cycles(); } /* No loop mode */ ret_timing(cycles); } static void i_not(void){ int cycles; selective_usereg(); cycles=4; if(main_size==4)cycles=6; if(main_eamode==dreg){ emit("xor %s[__dreg+ebx*4],byte -1\n", sizename[main_size] ); flags_v0(); }else{ cycles*=2; main_ea_rmw_load(); emit("xor %s,byte -1\n",x86cx[main_size]); flags_v0(); main_ea_rmw_store(); cycles+=main_ea_cycles(); } /* Calculate loop mode timings */ if(cputype==68010){ switch(main_eamode){ case aind:case ainc:case adec: loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; break; default:break; } } ret_timing(cycles); } /* main_reg=rx, main_dr is 0 or 32 (rx a/d), main_ir is 0 or 32 (ry a/d) */ static void i_exg(void){ usereg(); emit("mov ecx,[__reg+%d]\n",(main_reg*4)+main_dr); emit("mov edx,[__reg+%d+ebx*4]\n",main_ir); emit("mov [__reg+%d],edx\n",(main_reg*4)+main_dr); emit("mov [__reg+%d+ebx*4],ecx\n",main_ir); /* No loop mode */ ret_timing(6); } static void i_cmpm(void){ usereg(); ea_load(main_size,ainc,-1);/* Keep this in order */ emit("mov eax,ecx\n"); ea_load(main_size,ainc,main_reg); emit("cmp %s,%s\n",x86cx[main_size],x86ax[main_size]); flags(); /* Calculate loop mode timings */ if(cputype==68010){ if(main_size<=2){ loop_c_cycles = 2; loop_t_cycles = 8; loop_x_cycles = 6; }else{ loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 6; } } ret_timing((main_size==4)?20:12); } static void opx_dreg(char*op,char*adjust){ int cycles; usereg(); emit("mov ch,ah\n");/* Save old Z flag in CH */ emit("mov cl,[__xflag]\n"); emit("shr cl,1\n");/* X -> x86 carry */ emit("mov eax,[__dreg+%d]\n",main_reg*4); emit("%s %s,[__dreg+ebx*4]\n",op,x86ax[main_size]); if(adjust[0]){ emit("%s\n",adjust); } emit("mov [__dreg+%d],%s\n",main_reg*4,x86ax[main_size]); emit("lahf\n"); if(adjust[0]){ emit("mov al,0\n"); }else{ emit("seto al\n"); } c2x(); adjzero("ch"); if(main_size<=2){ cycles=4; if(adjust[0])cycles=6; }else{ cycles=8; if(cputype==68010)cycles=6; } /* No loop mode */ ret_timing(cycles); } static void opx_adec(char*op,char*adjust){ int cycles; usereg(); ea_load(main_size,adec,-1);/* Keep this in order */ emit("mov ebx,ecx\n"); ea_rmw_load(main_size,adec,main_reg); emit("xchg ecx,eax\n");/* flags -> ECX, dest -> EAX */ emit("mov cl,[__xflag]\n"); emit("shr cl,1\n");/* X -> x86 carry */ emit("%s %s,%s\n",op,x86ax[main_size],x86bx[main_size]); if(adjust[0]){ emit("%s\n",adjust); } emit("mov ebx,eax\n"); emit("lahf\n"); if(adjust[0]){ emit("mov al,0\n"); }else{ emit("seto al\n"); } c2x(); adjzero("ch"); emit("mov ecx,ebx\n"); emit("xor ebx,ebx\n"); ea_rmw_store(main_size,adec,main_reg); if(main_size<=2){ cycles=18; }else{ cycles=30; } /* Calculate loop mode timings */ if(cputype==68010){ if(adjust[0]){ loop_c_cycles = 6; loop_t_cycles = 12; loop_x_cycles = 10; }else{ if(main_size<=2){ loop_c_cycles = 4; loop_t_cycles = 10; loop_x_cycles = 8; }else{ loop_c_cycles = 2; loop_t_cycles = 8; loop_x_cycles = 6; } } } ret_timing(cycles); } static void i_addx_dreg(void){opx_dreg("adc","");} static void i_addx_adec(void){opx_adec("adc","");} static void i_subx_dreg(void){opx_dreg("sbb","");} static void i_subx_adec(void){opx_adec("sbb","");} static void i_abcd_dreg(void){main_size=1;opx_dreg("adc","daa");} static void i_abcd_adec(void){main_size=1;opx_adec("adc","daa");} static void i_sbcd_dreg(void){main_size=1;opx_dreg("sbb","das");} static void i_sbcd_adec(void){main_size=1;opx_adec("sbb","das");} static void i_movep_mem2reg(void){ int cycles; usereg(); emit("movsx edx,word[esi]\n"); emit("add esi,byte 2\n"); emit("add edx,[__areg+ebx*4]\n"); emit("call readmemorybyte\n"); emit("mov bh,cl\n"); emit("add edx,byte 2\n"); emit("call readmemorybyte\n"); emit("mov bl,cl\n"); if(main_size==2){ emit("mov [__dreg+%d],bx\n",main_reg*4); cycles=16; }else{ emit("add edx,byte 2\n"); emit("shl ebx,16\n"); emit("call readmemorybyte\n"); emit("mov bh,cl\n"); emit("add edx,byte 2\n"); emit("call readmemorybyte\n"); emit("mov bl,cl\n"); emit("mov [__dreg+%d],ebx\n",main_reg*4); emit("xor ebx,ebx\n"); cycles=24; } /* No loop mode */ ret_timing(cycles); } static void i_movep_reg2mem(void){ int cycles; usereg(); emit("movsx edx,word[esi]\n"); emit("add esi,byte 2\n"); emit("add edx,[__areg+ebx*4]\n"); emit("mov ebx,[__dreg+%d]\n",main_reg*4); if(main_size==4)emit("rol ebx,16\n"); emit("mov cl,bh\n"); emit("call writememorybyte\n"); emit("add edx,byte 2\n"); emit("mov cl,bl\n"); emit("call writememorybyte\n"); if(main_size==4){ emit("add edx,byte 2\n"); emit("rol ebx,16\n"); emit("mov cl,bh\n"); emit("call writememorybyte\n"); emit("add edx,byte 2\n"); emit("mov cl,bl\n"); emit("call writememorybyte\n"); cycles=24; }else{ cycles=16; } emit("xor ebx,ebx\n"); /* No loop mode */ ret_timing(cycles); } static void i_chk(void){ int cycles; int myline=linenum;linenum++; selective_usereg(); main_ea_load(); emit("cmp %s[__dreg+%d],byte 0\n", sizename[main_size],main_reg*4 ); emit("mov ax,8000h\n"); emit("jl short ln%d\n",myline); emit("cmp [__dreg+%d],%s\n", main_reg*4,x86cx[main_size] ); emit("mov ax,0\n"); emit("jg short ln%d\n",myline); cycles=10; if(cputype==68010)cycles=8; ret_timing(cycles+main_ea_cycles()); /* Out of bounds, so generate CHK exception */ emit("ln%d:",myline); emit("mov edx,18h\n"); emit("call group_2_exception\n"); perform_cached_rebase(); cycles=40; if(cputype==68010)cycles=44; /* No loop mode */ ret_timing(cycles+main_ea_cycles()); } static int created_illegal=0; static void i_illegal(void){ if(!created_illegal){emit("r_illegal:\n");created_illegal=1;} emit("sub esi,byte 2\n"); emit("mov edx,10h\n"); emit("call group_1_exception\n"); perform_cached_rebase(); ret_timing((cputype==68010)?38:34); } /* Breakpoint - notify hardware */ static void i_bkpt(void){ int myline=linenum; linenum++; emit("mov ecx,[__bkpthandler]\n"); emit("or ecx,ecx\n"); emit("jz ln%d\n",myline); airlock_exit(); emit("call ecx\n"); airlock_enter(); emit("ln%d:\n",myline); emit("mov edx,10h\n"); emit("call group_1_exception\n"); perform_cached_rebase(); ret_timing((cputype==68010)?38:34); } static void i_aline(void){ emit("sub esi,byte 2\n"); emit("mov edx,28h\n"); emit("call group_1_exception\n"); perform_cached_rebase(); /* This is just a guess */ ret_timing((cputype==68010)?38:34); } static void i_fline(void){ emit("sub esi,byte 2\n"); emit("mov edx,2Ch\n"); emit("call group_1_exception\n"); perform_cached_rebase(); /* This is just a guess */ ret_timing((cputype==68010)?38:34); } static void i_reset(void){ privilegecheck(); emit("mov ecx,[__resethandler]\n"); emit("or ecx,ecx\n"); emit("jz near invalidins\n"); airlock_exit(); emit("call ecx\n"); airlock_enter(); ret_timing((cputype==68010)?130:132); } static void i_movec_c_to_r(void){ int myline=linenum;linenum++; privilegecheck(); emit("mov bx,word[esi]\n"); emit("mov edx,ebx\n"); emit("shr ebx,12\n"); emit("and edx,0FFFh\n"); emit("jnz short ln%d\n",linenum); emit("mov cl,[__sfc]\n"); emit("and ecx,byte 7\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("cmp edx,byte 1\n"); emit("jnz short ln%d\n",linenum); emit("mov cl,[__dfc]\n"); emit("and ecx,byte 7\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("cmp edx,0800h\n"); emit("jnz short ln%d\n",linenum); emit("mov ecx,[__asp]\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("cmp edx,0801h\n"); emit("jnz short ln%d\n",linenum); emit("mov ecx,[__vbr]\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("jmp r_illegal\n"); emit("ln%d:\n",myline); emit("add esi,byte 2\n"); emit("mov dword[__reg+ebx*4],ecx\n"); ret_timing(12); } static void i_movec_r_to_c(void){ int myline=linenum;linenum++; privilegecheck(); emit("mov bx,word[esi]\n"); emit("mov edx,ebx\n"); emit("shr ebx,12\n"); emit("mov ecx,dword[__reg+ebx*4]\n"); emit("and edx,0FFFh\n"); emit("jnz short ln%d\n",linenum); emit("and cl,7\n"); emit("mov [__sfc],cl\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("cmp edx,byte 1\n"); emit("jnz short ln%d\n",linenum); emit("and cl,7\n"); emit("mov [__dfc],cl\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("cmp edx,0800h\n"); emit("jnz short ln%d\n",linenum); emit("mov [__asp],ecx\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("cmp edx,0801h\n"); emit("jnz short ln%d\n",linenum); emit("mov [__vbr],ecx\n"); emit("jmp short ln%d\n",myline); emit("ln%d:\n",linenum);linenum++; emit("jmp r_illegal\n"); emit("ln%d:\n",myline); emit("add esi,byte 2\n"); ret_timing(10); } #if 0 /* called not-quite-so-many times as i_move */ static void i_moves(void){ int cycles; int unitsize = main_size == 4 ? 2 : main_size; int myline=linenum; linenum++; selective_usereg(); emit("push esi\n"); /* save in case it's invalid */ emit("movzx ecx,word[esi]\n"); emit("add esi,byte 2\n"); ea_step_precalc(main_size,main_eamode,-1); /* edx=address */ emit("shr ecx,12\n"); emit("jc short ln%d_write\n",myline); /* read */ emit("cmp byte[__sfc],1\n"); emit("je ln%d_read_userdata\n"); emit("cmp byte[__sfc],2\n"); emit("je ln%d_read_userprogram\n"); emit("cmp byte[__sfc],5\n"); emit("je ln%d_read_superdata\n"); emit("cmp byte[__sfc],6\n"); emit("je ln%d_read_superprogram\n"); /* ** Generic address space read routine; SFC in {0,3,4,7} */ emit("cmp dword[__fc_read%s],byte 0\n",sizename[unitsize]); emit("je short ln%d_inv\n",myline); emit("push ecx\n"); emit("push edx\n"); airlock_exit(); emit("mov al,[__sfc]\n"); emit("and eax,byte 7\n"); if(use_stack) { emit("push edx\n"); emit("push eax\n"); } emit("call dword[__fc_read%s]\n"); if(use_stack) { emit("add esp,byte 8\n"); } emit("mov ecx,[esp+%d]\n",airlock_stacksize+4); switch(main_size) { case 1:emit("mov [__reg+ecx*4],al\n");break; case 2:emit("mov [__reg+ecx*4],ax\n");break; case 4:emit("mov [__reg+ecx*4+2],ax\n"); emit("mov edx,[esp+%d]\n",airlock_stacksize); emit("add edx,byte 2\n"); emit("mov al,[__sfc]\n"); emit("and eax,byte 7\n"); if(use_stack) { emit("push edx\n"); emit("push eax\n"); } emit("call dword[__fc_read%s]\n"); if(use_stack) { emit("add esp,byte 8\n"); } emit("mov ecx,[esp+%d]\n",airlock_stacksize+4); emit("mov [__reg+ecx*4],ax\n"); break; } airlock_enter(); emit("pop edx\n"); emit("pop ecx\n"); ea_step_postcalc(main_size,main_eamode,-1); /* edx=address */ emit("jmp ln%d_end\n"); ret_timing(cycles); } #endif /**************************************************************************** ** DECODE ROUTINES ****************************************************************************/ static int rproc [0x10000]; static byte unique[0x10000]; static int cease_decode; static int test(int n, int m, int op) { int t; if((n & m) != op) return 0; for(t = op & 0xF000; t < n; t++) { if((!unique[t]) && ((t & m) == (n & m))) { rproc[n] = t; return 2; } } unique[n] = (m >> 16) & 1; rproc[n] = n; t = (m ^ 0xFFFF) & 0xFFF; if(!t) { emit("; Opcode %04X\n", n); } else { emit("; Opcodes %04X - %04X\n", n, op + t); } /* align(4);*/ emit("%c%03X:\n", ((n >> 12) & 0xF) + 'K', n & 0xFFF); routine_counter++; return 1; } /* Instruction definition routine */ static void idef( int n, int mask, int op, void(*proc)(void) ) { if(cease_decode) return; cease_decode = test(n, mask, op); if(cease_decode == 1) { if(cputype == 68010) { loop_c_cycles = 10; loop_t_cycles = 10; loop_x_cycles = 16; } proc(); if(cputype == 68010) { if(loop_c_cycles > 14) { fprintf(stderr, "Bad news: instruction %04X:\n" "loop_c_cycles (%d) exceeds limit\n", n, loop_c_cycles ); exit(1); } if(loop_t_cycles > 14) { fprintf(stderr, "Bad news: instruction %04X:\n" "loop_t_cycles (%d) exceeds limit\n", n, loop_t_cycles ); exit(1); } if(loop_x_cycles > (loop_c_cycles + 6)) { fprintf(stderr, "Bad news: instruction %04X:\n" "loop_c_cycles (%d) and " "loop_x_cycles (%d) too far apart\n", n, loop_c_cycles, loop_x_cycles ); exit(1); } loop_x_cycles -= loop_c_cycles; loopinfo[n] = (((loop_c_cycles ) & 0x0E) | ((loop_t_cycles << 3) & 0x70)) | (((loop_x_cycles << 6) & 0x80) | ((loop_x_cycles >> 2) & 0x01)); } } } /* Batch idef for all addressing modes */ static void eadef_all( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = dreg; idef(n, m | 0x38, op | 0x00, proc); main_eamode = areg; idef(n, m | 0x38, op | 0x08, proc); main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = ainc; idef(n, m | 0x38, op | 0x18, proc); main_eamode = adec; idef(n, m | 0x38, op | 0x20, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); main_eamode = pcdp; idef(n, m | 0x3F, op | 0x3A, proc); main_eamode = pcxd; idef(n, m | 0x3F, op | 0x3B, proc); main_eamode = immd; idef(n, m | 0x3F, op | 0x3C, proc); } /* Batch idef for all addressing modes, excluding Address Register Direct ** mode when the operand size is 1 */ static void eadef_all_nobyteaddress( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = dreg; idef(n, m | 0x38, op | 0x00, proc); if(main_size != 1) { main_eamode = areg; idef(n, m | 0x38, op | 0x08, proc); } main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = ainc; idef(n, m | 0x38, op | 0x18, proc); main_eamode = adec; idef(n, m | 0x38, op | 0x20, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); main_eamode = pcdp; idef(n, m | 0x3F, op | 0x3A, proc); main_eamode = pcxd; idef(n, m | 0x3F, op | 0x3B, proc); main_eamode = immd; idef(n, m | 0x3F, op | 0x3C, proc); } /* Batch idef for all data addressing modes */ static void eadef_data( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = dreg; idef(n, m | 0x38, op | 0x00, proc); main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = ainc; idef(n, m | 0x38, op | 0x18, proc); main_eamode = adec; idef(n, m | 0x38, op | 0x20, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); main_eamode = pcdp; idef(n, m | 0x3F, op | 0x3A, proc); main_eamode = pcxd; idef(n, m | 0x3F, op | 0x3B, proc); main_eamode = immd; idef(n, m | 0x3F, op | 0x3C, proc); } /* Batch idef for all alterable addressing modes, excluding Address Register ** Direct mode when the operand size is 1 */ static void eadef_alterable_nobyteaddress( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = dreg; idef(n, m | 0x38, op | 0x00, proc); if(main_size != 1) { main_eamode = areg; idef(n, m | 0x38, op | 0x08, proc); } main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = ainc; idef(n, m | 0x38, op | 0x18, proc); main_eamode = adec; idef(n, m | 0x38, op | 0x20, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); } /* Batch idef for all data alterable addressing modes */ static void eadef_data_alterable( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = dreg; idef(n, m | 0x38, op | 0x00, proc); main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = ainc; idef(n, m | 0x38, op | 0x18, proc); main_eamode = adec; idef(n, m | 0x38, op | 0x20, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); } /* Batch idef for all memory alterable addressing modes */ static void eadef_memory_alterable( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = ainc; idef(n, m | 0x38, op | 0x18, proc); main_eamode = adec; idef(n, m | 0x38, op | 0x20, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); } /* Batch idef for all control addressing modes */ static void eadef_control( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); main_eamode = pcdp; idef(n, m | 0x3F, op | 0x3A, proc); main_eamode = pcxd; idef(n, m | 0x3F, op | 0x3B, proc); } /* Batch idef for all control alterable addressing modes */ static void eadef_control_alterable( int n, int m, int op, void(*proc)(void) ) { if(cease_decode) return; main_eamode = aind; idef(n, m | 0x38, op | 0x10, proc); main_eamode = adsp; idef(n, m | 0x38, op | 0x28, proc); main_eamode = axdp; idef(n, m | 0x38, op | 0x30, proc); main_eamode = absw; idef(n, m | 0x3F, op | 0x38, proc); main_eamode = absl; idef(n, m | 0x3F, op | 0x39, proc); } /* Batch eadef for MOVE instructions */ static void defmove(int majorop, int n) { if(cease_decode) return; for(main_reg = 0; main_reg < 8; main_reg++) { word w = majorop | (main_reg << 9); main_destmode = dreg; eadef_all(n, 0xFFC0, 0x000 | w, i_move); main_destmode = aind; eadef_all(n, 0xFFC0, 0x080 | w, i_move); main_destmode = ainc; eadef_all(n, 0xFFC0, 0x0C0 | w, i_move); main_destmode = adec; eadef_all(n, 0xFFC0, 0x100 | w, i_move); main_destmode = adsp; eadef_all(n, 0xFFC0, 0x140 | w, i_move); main_destmode = axdp; eadef_all(n, 0xFFC0, 0x180 | w, i_move); } main_destmode = absw; eadef_all(n, 0xFFC0, 0x1C0 | majorop, i_move); main_destmode = absl; eadef_all(n, 0xFFC0, 0x3C0 | majorop, i_move); } /***************************************************************************/ static void decode0(int n) { cease_decode = 0; for(sizedef = 0; sizedef < 3; sizedef++) { main_size = 1 << sizedef; eadef_data_alterable(n, 0xFFC0, 0x0000 | (sizedef << 6), i_ori); eadef_data_alterable(n, 0xFFC0, 0x0200 | (sizedef << 6), i_andi); eadef_data_alterable(n, 0xFFC0, 0x0400 | (sizedef << 6), i_subi); eadef_data_alterable(n, 0xFFC0, 0x0600 | (sizedef << 6), i_addi); eadef_data_alterable(n, 0xFFC0, 0x0A00 | (sizedef << 6), i_eori); eadef_data_alterable(n, 0xFFC0, 0x0C00 | (sizedef << 6), i_cmpi); /* Not quite ready for prime time yet */ /* if(cputype >= 68010) { eadef_memory_alterable(n, 0xFFC0, 0x0E00 | (sizedef << 6), i_moves); }*/ } /* ** Bit operations ** BTST (main_cc 0) works with all data addressing modes; the others ** require data alterable addressing modes */ for(main_cc = 0; main_cc < 4; main_cc++) { void (*eadef)(int n, int m, int op, void(*proc)(void)) = main_cc ? eadef_data_alterable : eadef_data; eadef(n, 0xFFC0, 0x0800 | (main_cc << 6), i_bitop_imm); for(main_reg = 0; main_reg < 8; main_reg++) { eadef(n, 0xFFC0, 0x0100 | (main_cc << 6) | (main_reg << 9), i_bitop_reg ); } } idef(n, 0xFFFF, 0x003C, i_ori_ccr ); idef(n, 0xFFFF, 0x023C, i_andi_ccr); idef(n, 0xFFFF, 0x0A3C, i_eori_ccr); idef(n, 0xFFFF, 0x007C, i_ori_sr ); idef(n, 0xFFFF, 0x027C, i_andi_sr ); idef(n, 0xFFFF, 0x0A7C, i_eori_sr ); for(main_reg=0;main_reg<8;main_reg++)for(main_size=2;main_size<=4;main_size+=2){ idef(n,0xFFF8,0x0108|((main_size&4)<<4)|(main_reg<<9),i_movep_mem2reg); idef(n,0xFFF8,0x0188|((main_size&4)<<4)|(main_reg<<9),i_movep_reg2mem); } } static void decode1(int n) { cease_decode = 0; main_size = 1; defmove(0x1000, n); } static void decode2(int n) { cease_decode = 0; main_size = 4; defmove(0x2000, n); for(main_reg = 0; main_reg < 8; main_reg++) { eadef_all(n, 0xFFC0, 0x2040 | (main_reg << 9), i_movea); } } static void decode3(int n) { cease_decode = 0; main_size = 2; defmove(0x3000, n); for(main_reg = 0; main_reg < 8; main_reg++) { eadef_all(n, 0xFFC0, 0x3040 | (main_reg << 9), i_movea); } } static void decode4(int n) { cease_decode = 0; eadef_data_alterable(n, 0xFFC0, 0x40C0, i_move_from_sr); if(cputype >= 68010) { eadef_data_alterable(n, 0xFFC0, 0x42C0, i_move_from_ccr); } eadef_data(n, 0xFFC0, 0x44C0, i_move_to_ccr); eadef_data(n, 0xFFC0, 0x46C0, i_move_to_sr ); eadef_control(n, 0xFFC0, 0x4EC0, i_jmp); eadef_control(n, 0xFFC0, 0x4E80, i_jsr); for(main_reg=0;main_reg<8;main_reg++)eadef_control(n,0xFFC0,0x41C0|(main_reg<<9),i_lea); main_size=2;for(main_reg=0;main_reg<8;main_reg++)eadef_data(n,0xFFC0,0x4100|(main_reg<<9),i_chk); eadef_control(n,0xFFC0,0x4840,i_pea); for(sizedef = 0; sizedef < 3; sizedef++) { main_size = 1 << sizedef; eadef_data_alterable(n, 0xFFC0, 0x4200 | (sizedef << 6), i_clr); eadef_data_alterable(n, 0xFFC0, 0x4A00 | (sizedef << 6), i_tst); } idef(n, 0xFFFF, 0x4E70, i_reset); idef(n, 0xFFFF, 0x4E71, i_nop); idef(n, 0xFFFF, 0x4E72, i_stop); idef(n, 0xFFFF, 0x4E73, i_rte); idef(n, 0xFFFF, 0x4E75, i_rts); idef(n, 0xFFFF, 0x4E76, i_trapv); idef(n, 0xFFFF, 0x4E77, i_rtr); if(cputype >= 68010) { idef(n, 0xFFFF, 0x4E74, i_rtd); idef(n, 0xFFFF, 0x4E7A, i_movec_c_to_r); idef(n, 0xFFFF, 0x4E7B, i_movec_r_to_c); } main_dr=0;for(sizedef=0;sizedef<2;sizedef++){main_size=1<<(sizedef+1);eadef_control_alterable(n,0xFFC0,0x4880|(main_dr<<10)|(sizedef<<6),i_movem_control);} main_dr=1;for(sizedef=0;sizedef<2;sizedef++){main_size=1<<(sizedef+1);eadef_control (n,0xFFC0,0x4880|(main_dr<<10)|(sizedef<<6),i_movem_control);} for(sizedef = 0; sizedef < 2; sizedef++) { main_size = 1 << (sizedef + 1); idef(n, 0xFFF8, 0x4C98 | (sizedef << 6), i_movem_postinc); idef(n, 0xFFF8, 0x48A0 | (sizedef << 6), i_movem_predec ); } idef(n, 0xFFF8, 0x4E50, i_link); idef(n, 0xFFF8, 0x4E58, i_unlk); idef(n, 0xFFF0, 0x4E40, i_trap); idef(n, 0xFFF8, 0x4E60, i_move_to_usp); idef(n, 0xFFF8, 0x4E68, i_move_from_usp); idef(n, 0xFFF8, 0x4840, i_swap); idef(n, 0xFFF8, 0x4880, i_extbw); idef(n, 0xFFF8, 0x48C0, i_extwl); for(sizedef = 0; sizedef < 3; sizedef++) { main_size = 1 << sizedef; eadef_data_alterable(n, 0xFFC0, 0x4000 | (sizedef << 6), i_negx); eadef_data_alterable(n, 0xFFC0, 0x4400 | (sizedef << 6), i_neg); eadef_data_alterable(n, 0xFFC0, 0x4600 | (sizedef << 6), i_not); } eadef_data_alterable(n, 0xFFC0, 0x4800, i_nbcd); eadef_data_alterable(n, 0xFFC0, 0x4AC0, i_tas); if(cputype == 68010) idef(n, 0xFFF8, 0x4848, i_bkpt); idef(n, 0xFFFF, 0x4AFA, i_illegal); idef(n, 0xFFFF, 0x4AFB, i_illegal); idef(n, 0xFFFF, 0x4AFC, i_illegal); } static void decode5(int n) { cease_decode = 0; for(sizedef = 0; sizedef < 3; sizedef++) { main_size = 1 << sizedef; for(main_qv = 0; main_qv < 8; main_qv++) { word w = (sizedef << 6) | (main_qv << 9); eadef_alterable_nobyteaddress(n, 0xFFC0, 0x5000 | w, i_addq); eadef_alterable_nobyteaddress(n, 0xFFC0, 0x5100 | w, i_subq); } } for(main_cc = 0x2; main_cc <= 0xF; main_cc++) { idef(n, 0xFFF8, 0x50C8 | (main_cc << 8), i_dbcc); } idef(n, 0xFFF8, 0x51C8, i_dbra); main_size = 1; for(main_cc = 0x0; main_cc <= 0xF; main_cc++) { eadef_data_alterable(n, 0xFFC0, 0x50C0 | (main_cc << 8), i_scc); } } static void decode6(int n){ cease_decode=0; idef(n,0x1FFFF,0x6000,i_bra_w); idef(n,0x1FFFF,0x6100,i_bsr_w); for(main_cc=0x2;main_cc<=0xF;main_cc++){ idef(n,0x1FFFF,0x6000|(main_cc<<8),i_bcc_w); } idef(n,0x0FF00,0x6000,i_bra_b); idef(n,0x0FF00,0x6100,i_bsr_b); for(main_cc=0x2;main_cc<=0xF;main_cc++){ idef(n,0x0FF00,0x6000|(main_cc<<8),i_bcc_b); } } static void decode7(int n){ cease_decode=0; for(main_reg=0;main_reg<8;main_reg++)idef(n,0xFF00,0x7000|(main_reg<<9),i_moveq); } static void decode8(int n){ cease_decode=0; for(sizedef=0;sizedef<3;sizedef++){main_size=1<> 12) & 0xF) + 'K', last & 0xFFF ); } if(rl > 1) emit("+%u", ((dword)(rl - 1)) << 24); emit("\n"); if(cputype == 68010) emit("db %d\n", loopinfo[last]); } /* Return the next parameter (or NULL if there isn't one */ static char *getparameter(int *ip, int argc, char **argv) { int i; (*ip)++; i = (*ip); if(i >= argc) { fprintf(stderr, "Invalid use of %s option\n", argv[i - 1]); return NULL; } return argv[i]; } int main(int argc, char **argv) { int i, j, last, rl, bank; char *codefilename = NULL; char default_sourcename[10]; fprintf(stderr, "STARSCREAM version " STAR_VERSION "\n"); /* Read options from the command line */ for(i = 1; i < argc; i++) { char *a = argv[i]; if(*a == '-') { a++; if(!strcmp("regcall" , a)) { use_stack = 0; } else if(!strcmp("stackcall" , a)) { use_stack = 1; } else if(!strcmp("nohog" , a)) { hog = 0; } else if(!strcmp("hog" , a)) { hog = 1; } else if(!strcmp("addressbits", a)) { int n; char *s = getparameter(&i, argc, argv); if(!s) return 1; n = atol(s); if(n < 1 || n > 32) { fprintf(stderr, "Invalid number of address " "bits: \"%s\"\n", argv[i] ); return 1; } addressbits = n; } else if(!strcmp("cputype" , a)) { int n; char *s = getparameter(&i, argc, argv); if(!s) return 1; n = atol(s); switch(n) { case 68000: case 68010: case 68020: cputype = n; break; default: fprintf(stderr, "Invalid CPU type: \"%s\"\n", argv[i] ); return 1; } } else if(!strcmp("name" , a)) { sourcename = getparameter(&i, argc, argv); if(!sourcename) return 1; } else { fprintf(stderr, "\nUnrecognized option: \"%s\"\n", argv[i] ); return 1; } } else { if(codefilename) { fprintf(stderr, "\n\"%s\": only one output filename " "is allowed\n", argv[i] ); return 1; } codefilename = argv[i]; } } if(!codefilename) { fprintf(stderr, "usage: %s outputfile [options]\n", argv[0]); fprintf(stderr, "see STARDOC.TXT for details\n"); return 1; } /* Set default options where applicable */ if(use_stack < 0) use_stack = 1; if(hog < 0) hog = 0; if(cputype < 0) cputype = 68000; if(addressbits < 0) { if(cputype <= 68010) addressbits = 24; else addressbits = 32; } if(!sourcename) { sprintf(default_sourcename, "s%d", cputype); sourcename = default_sourcename; } /* Prepare to generate the code file */ linenum = 0; fflush(stdout); fflush(stderr); codefile = fopen(codefilename, "w"); if(!codefile) { perror(codefilename); return 1; } fprintf(stderr, "Generating \"%s\" with the following options:\n", codefilename ); optiondump(stderr, " * "); prefixes(); for(i = 0; i < 0x10000; i++) rproc[i] = -1; /* Clear loop timings for 68010 */ if(cputype == 68010) { for(i = 0; i < 0x10000; i++) loopinfo[i] = 0xDB; } /* ** Decode instructions ** (this is where the vast majority of the code is emitted) */ fprintf(stderr, "Decoding instructions: "); for(bank = 0; bank <= 0xF; bank++) { int bankend = (bank + 1) << 12; void (*decoderoutine)(int n) = decodetable[bank]; fprintf(stderr, "%X", bank); fflush(stderr); for(i = bank << 12; i < bankend; i++) decoderoutine(i); } fprintf(stderr, " done\n"); /* ** Build the main jump table (all CPUs) / loop info table (68010) */ fprintf(stderr, "Building table: "); emit("section .bss\n"); emit("bits 32\n"); align(4); emit("__jmptbl resb 262144\n"); if(cputype == 68010) emit("__looptbl resb 65536\n"); emit("section .data\n"); emit("bits 32\n"); align(4); emit("__jmptblcomp:\n"); last = -2; rl = 0; for(i = 0; i < 0x10000; i++) { j = rproc[i]; if(j == last){ if(rl == 256) { tableentry(last, rl); rl = 1; } else { rl++; } } else { if(rl) tableentry(last, rl); rl = 1; last = j; } } tableentry(last, rl); align(4); /* Finish up */ suffixes(); fprintf(stderr, "done\n"); fprintf(stderr, "routine_counter = %d\n", routine_counter); fclose(codefile); return 0; } dgen-sdl-1.23/star/cpudebug.c 644 1750 1750 152454 7027317561 11253 /* ** Starscream 680x0 emulation library ** Copyright 1997, 1998, 1999 Neill Corlett ** ** Refer to STARDOC.TXT for terms of use, API reference, and directions on ** how to compile. */ #include #include #include #include #include #include "starcpu.h" #include "cpudebug.h" void (*cpudebug_get)(char*, int); void (*cpudebug_put)(const char*); static void cpudebug_gets(char *s, int n) { if(cpudebug_get) cpudebug_get(s, n); else fgets(s, n, stdin); } static void cpudebug_putc(char c) { static char buffer[100]; static unsigned l = 0; buffer[l++] = c; if((c == '\n') || (l == (sizeof(buffer) - 1))) { buffer[l] = 0; if(cpudebug_put) cpudebug_put(buffer); else fputs(buffer, stdout); l = 0; } } static void cpudebug_printf(const char *fmt, ...) { static char buffer[400]; char *s = buffer; va_list ap; va_start(ap, fmt); vsprintf(s, fmt, ap); va_end(ap); while(*s) cpudebug_putc(*s++); } #define byte unsigned char #define word unsigned short int #define dword unsigned int #define int08 signed char #define int16 signed short int #define int32 signed int int cpudebug_disabled(void){return 0;} #define ea eacalc[inst&0x3F]() /****************************** ** SNAGS / EA CONSIDERATIONS ** ******************************* - ADDX is encoded the same way as ADD->ea - SUBX is encoded the same way as SUB->ea - ABCD is encoded the same way as AND->ea - EXG is encoded the same way as AND->ea - SBCD is encoded the same way as OR->ea - EOR is encoded the same way as CMPM - ASR is encoded the same way as LSR (so are LSL and ASL, but they do the same thing) - Bcc does NOT support 32-bit offsets on the 68000. (this is a reminder, don't bother implementing 32-bit offsets!) - Look on p. 3-19 for how to calculate branch conditions (GE, LT, GT, etc.) - Bit operations are 32-bit for registers, 8-bit for memory locations. - MOVEM->memory is encoded the same way as EXT If the EA is just a register, then it's EXT, otherwise it's MOVEM. - MOVEP done the same way as the bit operations - Scc done the same way as DBcc. Assume it's Scc, unless the EA is a direct An mode (then it's a DBcc). - SWAP done the same way as PEA - TAS done the same way as ILLEGAL - LINK, NOP, RTR, RTS, TRAP, TRAPV, UNLK are encoded the same way. ******************************/ #define hex08 "%02X" #define hex16 "%04X" #define hex32 "%08X" #define hexlong "%06X" #define isregister ((inst&0x0030)==0x0000) #define isaddressr ((inst&0x0038)==0x0008) static char eabuffer[20],sdebug[80]; static dword debugpc,hexaddr; static int isize; static word inst; static word fetch(void){ debugpc+=2; isize+=2; return(s68000fetch(debugpc-2)&0xFFFF); } static dword fetchl(void){ dword t; t=(s68000fetch(debugpc)&0xFFFF); t<<=16; t|=(s68000fetch(debugpc+2)&0xFFFF); debugpc+=4; isize+=4; return t; } static int08 opsize[1024]={ 1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,2,4,0,0,0,0,0,1,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 1,2,4,2,0,0,2,4,1,2,4,1,0,0,2,4,1,2,4,1,0,0,2,4,1,2,4,2,0,0,2,4, 1,4,2,4,0,0,2,4,1,2,4,1,0,0,2,4,0,0,2,4,0,0,2,4,0,2,0,0,0,0,2,4, 1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0, 1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0, 4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0, 1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2, 1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2, 1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4, 1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4, 1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4, 1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2, 1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2, 1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4, 1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4,1,2,4,2,1,2,4,4, 1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2,1,2,4,2, 1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0,1,2,4,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /******************** EA GENERATION ********************/ /* These are the functions to generate effective addresses. Here is the syntax: eacalc[mode](); mode is the EA mode << 3 + register number The function sets addr so you can use m68read and m68write. These routines screw around with the PC, and might call fetch() a couple times to get extension words. Place the eacalc() calls strategically to get the extension words in the right order. */ /* These are the jump tables for EA calculation. drd = data reg direct Dn ard = address reg direct An ari = address reg indirect (An) ari_inc = address reg indirect, postincrement (An)+ ari_dec = address reg indirect, predecrement -(An) ari_dis = address reg indirect, displacement (d16,An) ari_ind = address reg indirect, index (d8,An,Xn) pci_dis = prog. counter indirect, displacement (d16,PC) pci_ind = prog. counter indirect, index (d8,PC,Xn) */ #define eacalc_drd(n,r) static void n(void){sprintf(eabuffer,"d%d",r);} #define eacalc_ard(n,r) static void n(void){sprintf(eabuffer,"a%d",r);} #define eacalc_ari(n,r) static void n(void){sprintf(eabuffer,"(a%d)",r);} #define eacalc_ari_inc(n,r) static void n(void){sprintf(eabuffer,"(a%d)+",r);} #define eacalc_ari_dec(n,r) static void n(void){sprintf(eabuffer,"-(a%d)",r);} #define eacalc_ari_dis(n,r) static void n(void){\ int16 briefext=fetch();\ sprintf(eabuffer,"%c$" hex16 "(a%d)",(briefext<0)?'-':'+',(briefext<0)?-briefext:briefext,r);\ } #define eacalc_ari_ind(n,r) static void n(void){\ int16 briefext=fetch();\ if(briefext<0)sprintf(eabuffer,"-$" hex08 "(a%d,%c%d.%c)",\ (int08)-briefext,r,\ briefext&0x8000?'a':'d',(briefext>>12)&7,\ briefext&0x800?'l':'w');\ else sprintf(eabuffer,"+$" hex08 "(a%d,%c%d.%c)",\ (int08)briefext,r,\ briefext&0x8000?'a':'d',(briefext>>12)&7,\ briefext&0x800?'l':'w');\ } eacalc_drd(ea_0_0,0) eacalc_drd(ea_0_1,1) eacalc_drd(ea_0_2,2) eacalc_drd(ea_0_3,3) eacalc_drd(ea_0_4,4) eacalc_drd(ea_0_5,5) eacalc_drd(ea_0_6,6) eacalc_drd(ea_0_7,7) eacalc_ard(ea_1_0,0) eacalc_ard(ea_1_1,1) eacalc_ard(ea_1_2,2) eacalc_ard(ea_1_3,3) eacalc_ard(ea_1_4,4) eacalc_ard(ea_1_5,5) eacalc_ard(ea_1_6,6) eacalc_ard(ea_1_7,7) eacalc_ari(ea_2_0,0) eacalc_ari(ea_2_1,1) eacalc_ari(ea_2_2,2) eacalc_ari(ea_2_3,3) eacalc_ari(ea_2_4,4) eacalc_ari(ea_2_5,5) eacalc_ari(ea_2_6,6) eacalc_ari(ea_2_7,7) eacalc_ari_inc(ea_3_0,0) eacalc_ari_inc(ea_3_1,1) eacalc_ari_inc(ea_3_2,2) eacalc_ari_inc(ea_3_3,3) eacalc_ari_inc(ea_3_4,4) eacalc_ari_inc(ea_3_5,5) eacalc_ari_inc(ea_3_6,6) eacalc_ari_inc(ea_3_7,7) eacalc_ari_dec(ea_4_0,0) eacalc_ari_dec(ea_4_1,1) eacalc_ari_dec(ea_4_2,2) eacalc_ari_dec(ea_4_3,3) eacalc_ari_dec(ea_4_4,4) eacalc_ari_dec(ea_4_5,5) eacalc_ari_dec(ea_4_6,6) eacalc_ari_dec(ea_4_7,7) eacalc_ari_dis(ea_5_0,0) eacalc_ari_dis(ea_5_1,1) eacalc_ari_dis(ea_5_2,2) eacalc_ari_dis(ea_5_3,3) eacalc_ari_dis(ea_5_4,4) eacalc_ari_dis(ea_5_5,5) eacalc_ari_dis(ea_5_6,6) eacalc_ari_dis(ea_5_7,7) eacalc_ari_ind(ea_6_0,0) eacalc_ari_ind(ea_6_1,1) eacalc_ari_ind(ea_6_2,2) eacalc_ari_ind(ea_6_3,3) eacalc_ari_ind(ea_6_4,4) eacalc_ari_ind(ea_6_5,5) eacalc_ari_ind(ea_6_6,6) eacalc_ari_ind(ea_6_7,7) /* These are the "special" addressing modes: abshort absolute short address abslong absolute long address immdata immediate data */ static void eacalcspecial_abshort(void){ word briefext; briefext=fetch(); sprintf(eabuffer,"($" hex16 ")",briefext); } static void eacalcspecial_abslong(void){ dword briefext; briefext=fetch(); briefext<<=16; briefext|=fetch(); sprintf(eabuffer,"($"hexlong")",briefext); } static void eacalcspecial_immdata(void){ dword briefext; switch(opsize[inst>>6]){ case 1: briefext=fetch()&0xFF; sprintf(eabuffer,"#$" hex08,briefext); break; case 2: briefext=fetch(); sprintf(eabuffer,"#$" hex16,briefext); break; default: briefext=fetch(); briefext<<=16; briefext|=fetch(); sprintf(eabuffer,"#$" hex32,briefext); break; } } static void eacalcspecial_pci_dis(void){ dword dpc = debugpc; word briefext = fetch(); sprintf(eabuffer,"$" hexlong "(pc)",((int16)(briefext))+dpc); } static void eacalcspecial_pci_ind(void){ dword dpc = debugpc; word briefext = fetch(); sprintf(eabuffer,"$" hexlong "(pc,%c%d)", ((int08)(briefext))+dpc, briefext&0x8000?'a':'d',(briefext>>12)&7); } static void eacalcspecial_unknown(void){ sprintf(eabuffer,"*** UNKNOWN EA MODE ***"); } static void (*(eacalc[64]))(void)={ ea_0_0,ea_0_1,ea_0_2,ea_0_3,ea_0_4,ea_0_5,ea_0_6,ea_0_7, ea_1_0,ea_1_1,ea_1_2,ea_1_3,ea_1_4,ea_1_5,ea_1_6,ea_1_7, ea_2_0,ea_2_1,ea_2_2,ea_2_3,ea_2_4,ea_2_5,ea_2_6,ea_2_7, ea_3_0,ea_3_1,ea_3_2,ea_3_3,ea_3_4,ea_3_5,ea_3_6,ea_3_7, ea_4_0,ea_4_1,ea_4_2,ea_4_3,ea_4_4,ea_4_5,ea_4_6,ea_4_7, ea_5_0,ea_5_1,ea_5_2,ea_5_3,ea_5_4,ea_5_5,ea_5_6,ea_5_7, ea_6_0,ea_6_1,ea_6_2,ea_6_3,ea_6_4,ea_6_5,ea_6_6,ea_6_7, eacalcspecial_abshort,eacalcspecial_abslong,eacalcspecial_pci_dis,eacalcspecial_pci_ind, eacalcspecial_immdata,eacalcspecial_unknown,eacalcspecial_unknown,eacalcspecial_unknown}; static void m68unsupported(void){ sprintf(sdebug,"*** NOT RECOGNIZED ***"); } static void m68_unrecog_x(void){ sprintf(sdebug,"unrecognized"); } /******************** BIT TEST-AND-____ ********************/ static void m68_bitopdn_x(void){ int16 d16; if((inst&0x38)==0x08){ d16=fetch(); sprintf(eabuffer,"%c$" hex16 "(a%d)",(d16<0)?'-':'+',(d16<0)?-d16:d16,inst&7); if(!(inst&0x80)){ sprintf(sdebug,"movep%s %s,d%d", ((inst&0x40)==0x40)?".l":" ", eabuffer,inst>>9 ); }else{ sprintf(sdebug,"movep%s d%d,%s", ((inst&0x40)==0x40)?".l":" ", inst>>9,eabuffer ); } }else{ ea; switch((inst>>6)&3){ case 0:sprintf(sdebug,"btst d%d,%s",inst>>9,eabuffer);break; case 1:sprintf(sdebug,"bchg d%d,%s",inst>>9,eabuffer);break; case 2:sprintf(sdebug,"bclr d%d,%s",inst>>9,eabuffer);break; case 3:sprintf(sdebug,"bset d%d,%s",inst>>9,eabuffer);break; default:break; } } } #define bittest_st(name,dump) static void name(void){\ byte shiftby=(fetch()&0xFF);\ ea;sprintf(sdebug,"%s #$"hex08",%s",dump,shiftby,eabuffer);\ } bittest_st(m68_btst_st_x,"btst") bittest_st(m68_bclr_st_x,"bclr") bittest_st(m68_bset_st_x,"bset") bittest_st(m68_bchg_st_x,"bchg") /******************** Bcc ********************/ #define conditional_branch(name,dump) static void name(void){\ int16 disp;\ int32 currentpc=debugpc;\ disp=(int08)(inst&0xFF);\ if(!disp)disp=fetch();\ sprintf(sdebug,"%s ($"hexlong")",dump,currentpc+disp);\ } conditional_branch(m68_bra_____x,"bra") conditional_branch(m68_bhi_____x,"bhi") conditional_branch(m68_bls_____x,"bls") conditional_branch(m68_bcc_____x,"bcc") conditional_branch(m68_bcs_____x,"bcs") conditional_branch(m68_bne_____x,"bne") conditional_branch(m68_beq_____x,"beq") conditional_branch(m68_bvc_____x,"bvc") conditional_branch(m68_bvs_____x,"bvs") conditional_branch(m68_bpl_____x,"bpl") conditional_branch(m68_bmi_____x,"bmi") conditional_branch(m68_bge_____x,"bge") conditional_branch(m68_blt_____x,"blt") conditional_branch(m68_bgt_____x,"bgt") conditional_branch(m68_ble_____x,"ble") /******************** Scc, DBcc ********************/ #define scc_dbcc(name,dump1,dump2)\ static void name(void){\ ea;if(isaddressr){\ int16 disp;\ disp=fetch();\ sprintf(sdebug,"%s d%d,($"hexlong")",dump2,inst&7,debugpc+disp-2);\ }else sprintf(sdebug,"%s %s",dump1,eabuffer);\ } scc_dbcc(m68_st______x,"st ","dbt ") scc_dbcc(m68_sf______x,"sf ","dbra") scc_dbcc(m68_shi_____x,"shi","dbhi") scc_dbcc(m68_sls_____x,"sls","dbls") scc_dbcc(m68_scc_____x,"scc","dbcc") scc_dbcc(m68_scs_____x,"scs","dbcs") scc_dbcc(m68_sne_____x,"sne","dbne") scc_dbcc(m68_seq_____x,"seq","dbeq") scc_dbcc(m68_svc_____x,"svc","dbvc") scc_dbcc(m68_svs_____x,"svs","dbvs") scc_dbcc(m68_spl_____x,"spl","dbpl") scc_dbcc(m68_smi_____x,"smi","dbmi") scc_dbcc(m68_sge_____x,"sge","dbge") scc_dbcc(m68_slt_____x,"slt","dblt") scc_dbcc(m68_sgt_____x,"sgt","dbgt") scc_dbcc(m68_sle_____x,"sle","dble") /******************** JMP ********************/ static void m68_jmp_____x(void){ea;sprintf(sdebug,"jmp %s",eabuffer);} /******************** JSR/BSR ********************/ static void m68_jsr_____x(void){ea;sprintf(sdebug,"jsr %s",eabuffer);} static void m68_bsr_____x(void){ int16 disp; int32 currentpc=debugpc; disp=(int08)(inst&0xFF); if(!disp)disp=fetch(); sprintf(sdebug,"%s ($"hexlong")","bsr",disp+currentpc); } /******************** TAS ********************/ /* Test-and-set / illegal */ static void m68_tas_____b(void){ if(inst==0x4AFC){ sprintf(sdebug,"illegal"); }else{ ea; sprintf(sdebug,"tas %s",eabuffer); } } /******************** LEA ********************/ static void m68_lea___n_l(void){ ea;sprintf(sdebug,"lea %s,a%d",eabuffer,(inst>>9)&7); } /******************** PEA ********************/ static void m68_pea_____l(void){ ea;if(isregister){/* SWAP Dn */ sprintf(sdebug,"swap d%d",inst&7); }else{ sprintf(sdebug,"pea %s",eabuffer); } } /******************** CLR, NEG, NEGX, NOT, TST ********************/ #define negate_ea(name,dump) static void name(void){\ ea;sprintf(sdebug,"%s %s",dump,eabuffer);\ } negate_ea(m68_neg_____b,"neg.b ") negate_ea(m68_neg_____w,"neg ") negate_ea(m68_neg_____l,"neg.l ") negate_ea(m68_negx____b,"negx.b") negate_ea(m68_negx____w,"negx ") negate_ea(m68_negx____l,"negx.l") negate_ea(m68_not_____b,"not.b ") negate_ea(m68_not_____w,"not ") negate_ea(m68_not_____l,"not.l ") negate_ea(m68_clr_____b,"clr.b ") negate_ea(m68_clr_____w,"clr ") negate_ea(m68_clr_____l,"clr.l ") negate_ea(m68_tst_____b,"tst.b ") negate_ea(m68_tst_____w,"tst ") negate_ea(m68_tst_____l,"tst.l ") /******************** SOURCE: IMMEDIATE DATA ********************* DESTINATION: EFFECTIVE ADDRESS ********************/ #define im_to_ea(name,type,hextype,fetchtype,dump,r) static void name(void){\ type src=(type)fetchtype();\ if((inst&0x3F)==0x3C){\ sprintf(sdebug,"%s #$"hextype",%s",dump,src,r);\ }else{\ ea;sprintf(sdebug,"%s #$"hextype",%s",dump,src,eabuffer);\ }\ } im_to_ea(m68_ori_____b,byte ,hex08,fetch ,"or.b ","ccr") im_to_ea(m68_ori_____w,word ,hex16,fetch ,"or ","sr" ) im_to_ea(m68_ori_____l,dword,hex32,fetchl,"or.l ","" ) im_to_ea(m68_andi____b,byte ,hex08,fetch ,"and.b","ccr") im_to_ea(m68_andi____w,word ,hex16,fetch ,"and ","sr" ) im_to_ea(m68_andi____l,dword,hex32,fetchl,"and.l","" ) im_to_ea(m68_eori____b,byte ,hex08,fetch ,"eor.b","ccr") im_to_ea(m68_eori____w,word ,hex16,fetch ,"eor ","sr" ) im_to_ea(m68_eori____l,dword,hex32,fetchl,"eor.l","" ) im_to_ea(m68_addi____b,byte ,hex08,fetch ,"add.b","" ) im_to_ea(m68_addi____w,word ,hex16,fetch ,"add ","" ) im_to_ea(m68_addi____l,dword,hex32,fetchl,"add.l","" ) im_to_ea(m68_subi____b,byte ,hex08,fetch ,"sub.b","" ) im_to_ea(m68_subi____w,word ,hex16,fetch ,"sub ","" ) im_to_ea(m68_subi____l,dword,hex32,fetchl,"sub.l","" ) im_to_ea(m68_cmpi____b,byte ,hex08,fetch ,"cmp.b","" ) im_to_ea(m68_cmpi____w,word ,hex16,fetch ,"cmp ","" ) im_to_ea(m68_cmpi____l,dword,hex32,fetchl,"cmp.l","" ) /******************** SOURCE: EFFECTIVE ADDRESS ********************* DESTINATION: DATA REGISTER ********************/ #define ea_to_dn(name,dump) static void name(void){\ ea;sprintf(sdebug,"%s %s,d%d",dump,eabuffer,(inst>>9)&7);\ } ea_to_dn(m68_or__d_n_b,"or.b ") ea_to_dn(m68_or__d_n_w,"or ") ea_to_dn(m68_or__d_n_l,"or.l ") ea_to_dn(m68_and_d_n_b,"and.b") ea_to_dn(m68_and_d_n_w,"and ") ea_to_dn(m68_and_d_n_l,"and.l") ea_to_dn(m68_add_d_n_b,"add.b") ea_to_dn(m68_add_d_n_w,"add ") ea_to_dn(m68_add_d_n_l,"add.l") ea_to_dn(m68_sub_d_n_b,"sub.b") ea_to_dn(m68_sub_d_n_w,"sub ") ea_to_dn(m68_sub_d_n_l,"sub.l") ea_to_dn(m68_cmp_d_n_b,"cmp.b") ea_to_dn(m68_cmp_d_n_w,"cmp ") ea_to_dn(m68_cmp_d_n_l,"cmp.l") /******************** SOURCE: EFFECTIVE ADDRESS ********************* DESTINATION: ADDRESS REGISTER ********************/ #define ea_to_an(name,dump) static void name(void){\ ea;sprintf(sdebug,"%s %s,a%d",dump,eabuffer,((inst>>9)&7));\ } ea_to_an(m68_adda__n_w,"add ") ea_to_an(m68_adda__n_l,"add.l") ea_to_an(m68_suba__n_w,"sub ") ea_to_an(m68_suba__n_l,"sub.l") ea_to_an(m68_cmpa__n_w,"cmp ") ea_to_an(m68_cmpa__n_l,"cmp.l") /******************** SUPPORT ROUTINE: ADDX AND SUBX ********************/ #define support_addsubx(name,dump)\ static void name(void){\ word nregx=(inst>>9)&7,nregy=inst&7;\ if(inst&0x0008)sprintf(sdebug,"%s -(a%d),-(a%d)",dump,nregy,nregx);\ else sprintf(sdebug,"%s d%d,d%d",dump,nregy,nregx);\ } support_addsubx(m68support_addx_b,"addx.b") support_addsubx(m68support_addx_w,"addx ") support_addsubx(m68support_addx_l,"addx.l") support_addsubx(m68support_subx_b,"subx.b") support_addsubx(m68support_subx_w,"subx ") support_addsubx(m68support_subx_l,"subx.l") #define support_bcd(name,dump)\ static void name(void){\ word nregx=(inst>>9)&7,nregy=inst&7;\ if(inst&0x0008)sprintf(sdebug,"%s -(a%d),-(a%d)",dump,nregy,nregx);\ else sprintf(sdebug,"%s d%d,d%d",dump,nregy,nregx);\ } support_bcd(m68support_abcd,"abcd") support_bcd(m68support_sbcd,"sbcd") /******************** SUPPORT ROUTINE: CMPM ********************/ #define support_cmpm(name,dump) static void name(void){\ sprintf(sdebug,"%s (a%d)+,(a%d)+",dump,inst&7,(inst>>9)&7);\ } support_cmpm(m68support_cmpm_b,"cmp.b") support_cmpm(m68support_cmpm_w,"cmp ") support_cmpm(m68support_cmpm_l,"cmp.l") /******************** SUPPORT ROUTINE: EXG ********************/ static void m68support_exg_same(void){ dword rx; rx=(inst&8)|((inst>>9)&7); sprintf(sdebug,"exg %c%d,%c%d", rx&8?'a':'d',rx&7,inst&8?'a':'d',inst&7); } static void m68support_exg_diff(void){ sprintf(sdebug,"exg d%d,a%d",(inst>>9)&7,inst&7); } /******************** SOURCE: DATA REGISTER ********************* DESTINATION: EFFECTIVE ADDRESS ********************* ********************* calls a support routine if EA is a register ********************/ #define dn_to_ea(name,dump,s_cond,s_routine)\ static void name(void){\ ea;if(s_cond)s_routine();\ else sprintf(sdebug,"%s d%d,%s",dump,(inst>>9)&7,eabuffer);\ } dn_to_ea(m68_add_e_n_b,"add.b",isregister,m68support_addx_b) dn_to_ea(m68_add_e_n_w,"add ",isregister,m68support_addx_w) dn_to_ea(m68_add_e_n_l,"add.l",isregister,m68support_addx_l) dn_to_ea(m68_sub_e_n_b,"sub.b",isregister,m68support_subx_b) dn_to_ea(m68_sub_e_n_w,"sub ",isregister,m68support_subx_w) dn_to_ea(m68_sub_e_n_l,"sub.l",isregister,m68support_subx_l) dn_to_ea(m68_eor_e_n_b,"eor.b",isaddressr,m68support_cmpm_b) dn_to_ea(m68_eor_e_n_w,"eor ",isaddressr,m68support_cmpm_w) dn_to_ea(m68_eor_e_n_l,"eor.l",isaddressr,m68support_cmpm_l) dn_to_ea(m68_or__e_n_b,"or.b ",isregister,m68support_sbcd) dn_to_ea(m68_or__e_n_w,"or ",isregister,m68unsupported) dn_to_ea(m68_or__e_n_l,"or.l ",isregister,m68unsupported) dn_to_ea(m68_and_e_n_b,"and.b",isregister,m68support_abcd) dn_to_ea(m68_and_e_n_w,"and ",isregister,m68support_exg_same) dn_to_ea(m68_and_e_n_l,"and.l",isaddressr,m68support_exg_diff) /******************** SOURCE: QUICK DATA ********************* DESTINATION: EFFECTIVE ADDRESS ********************/ #define qn_to_ea(name,dump1) static void name(void){\ ea;sprintf(sdebug,"%s #%d,%s",dump1,(((inst>>9)&7)==0)?8:(inst>>9)&7,eabuffer);\ } qn_to_ea(m68_addq__n_b,"add.b") qn_to_ea(m68_addq__n_w,"add ") qn_to_ea(m68_addq__n_l,"add.l") qn_to_ea(m68_subq__n_b,"sub.b") qn_to_ea(m68_subq__n_w,"sub ") qn_to_ea(m68_subq__n_l,"sub.l") /******************** SOURCE: QUICK DATA ********************* DESTINATION: DATA REGISTER ********************/ /* MOVEQ is the only instruction that uses this form */ static void m68_moveq_n_l(void){ sprintf(sdebug,"moveq #$"hex08",d%d",inst&0xFF,(inst>>9)&7); } /******************** SOURCE: EFFECTIVE ADDRESS ********************* DESTINATION: EFFECTIVE ADDRESS ********************/ /* MOVE is the only instruction that uses this form */ #define ea_to_ea(name,dump) static void name(void){\ char tmpbuf[40];\ ea;strcpy(tmpbuf,eabuffer);\ eacalc[((((inst>>3)&(7<<3)))|((inst>>9)&7))]();\ sprintf(sdebug,"%s %s,%s",dump,tmpbuf,eabuffer);\ } ea_to_ea(m68_move____b,"move.b") ea_to_ea(m68_move____w,"move ") ea_to_ea(m68_move____l,"move.l") /******************** MOVEM, EXT ********************/ static void getreglistf(word mask,char*rl){ if(mask&0x0001){*(rl++)='d';*(rl++)='0';*(rl++)='/';} if(mask&0x0002){*(rl++)='d';*(rl++)='1';*(rl++)='/';} if(mask&0x0004){*(rl++)='d';*(rl++)='2';*(rl++)='/';} if(mask&0x0008){*(rl++)='d';*(rl++)='3';*(rl++)='/';} if(mask&0x0010){*(rl++)='d';*(rl++)='4';*(rl++)='/';} if(mask&0x0020){*(rl++)='d';*(rl++)='5';*(rl++)='/';} if(mask&0x0040){*(rl++)='d';*(rl++)='6';*(rl++)='/';} if(mask&0x0080){*(rl++)='d';*(rl++)='7';*(rl++)='/';} if(mask&0x0100){*(rl++)='a';*(rl++)='0';*(rl++)='/';} if(mask&0x0200){*(rl++)='a';*(rl++)='1';*(rl++)='/';} if(mask&0x0400){*(rl++)='a';*(rl++)='2';*(rl++)='/';} if(mask&0x0800){*(rl++)='a';*(rl++)='3';*(rl++)='/';} if(mask&0x1000){*(rl++)='a';*(rl++)='4';*(rl++)='/';} if(mask&0x2000){*(rl++)='a';*(rl++)='5';*(rl++)='/';} if(mask&0x4000){*(rl++)='a';*(rl++)='6';*(rl++)='/';} if(mask&0x8000){*(rl++)='a';*(rl++)='7';*(rl++)='/';} *(--rl)=0; } static void getreglistb(word mask,char*rl){ if(mask&0x0001){*(rl++)='a';*(rl++)='7';*(rl++)='/';} if(mask&0x0002){*(rl++)='a';*(rl++)='6';*(rl++)='/';} if(mask&0x0004){*(rl++)='a';*(rl++)='5';*(rl++)='/';} if(mask&0x0008){*(rl++)='a';*(rl++)='4';*(rl++)='/';} if(mask&0x0010){*(rl++)='a';*(rl++)='3';*(rl++)='/';} if(mask&0x0020){*(rl++)='a';*(rl++)='2';*(rl++)='/';} if(mask&0x0040){*(rl++)='a';*(rl++)='1';*(rl++)='/';} if(mask&0x0080){*(rl++)='a';*(rl++)='0';*(rl++)='/';} if(mask&0x0100){*(rl++)='d';*(rl++)='7';*(rl++)='/';} if(mask&0x0200){*(rl++)='d';*(rl++)='6';*(rl++)='/';} if(mask&0x0400){*(rl++)='d';*(rl++)='5';*(rl++)='/';} if(mask&0x0800){*(rl++)='d';*(rl++)='4';*(rl++)='/';} if(mask&0x1000){*(rl++)='d';*(rl++)='3';*(rl++)='/';} if(mask&0x2000){*(rl++)='d';*(rl++)='2';*(rl++)='/';} if(mask&0x4000){*(rl++)='d';*(rl++)='1';*(rl++)='/';} if(mask&0x8000){*(rl++)='d';*(rl++)='0';*(rl++)='/';} *(--rl)=0; } #define movem_mem(name,dumpm,dumpx)\ static void name(void){\ word regmask;\ char reglist[50];\ if((inst&0x38)==0x0000){ /* ext */\ sprintf(sdebug,dumpx"d%d",inst&7);\ }else if((inst&0x38)==0x0020){ /* predecrement addressing mode */\ regmask=fetch();\ getreglistb(regmask,reglist);\ sprintf(sdebug,dumpm"%s,-(a%d)",reglist,inst&7);\ }else{\ regmask=fetch();\ ea;getreglistf(regmask,reglist);\ sprintf(sdebug,dumpm "%s,%s",reglist,eabuffer);\ }\ } movem_mem(m68_movem___w,"movem ","ext ") movem_mem(m68_movem___l,"movem.l ","ext.l ") #define movem_reg(name,dump) static void name(void){\ word regmask;\ char reglist[50];\ regmask=fetch();\ ea;getreglistf(regmask,reglist);\ sprintf(sdebug,dump "%s,%s",eabuffer,reglist);\ } movem_reg(m68_movem_r_w,"movem ") movem_reg(m68_movem_r_l,"movem.l ") /******************** INSTRUCTIONS THAT INVOLVE SR/CCR ********************/ static void m68_move2sr_w(void){ea;sprintf(sdebug,"move %s,sr",eabuffer);} static void m68_movefsr_w(void){ea;sprintf(sdebug,"move sr,%s",eabuffer);} static void m68_move2cc_w(void){ea;sprintf(sdebug,"move.b %s,ccr",eabuffer);} static void m68_movefcc_w(void){ea;sprintf(sdebug,"move.b ccr,%s",eabuffer);} static void m68_rts_____x(void){sprintf(sdebug,"rts");} /******************** SHIFTS AND ROTATES ********************/ #define regshift(name,sizedump) \ static void name(void){\ char tmpbuf[10];\ if((inst&0x20)==0)sprintf(tmpbuf,"#$"hex08",d%d",(((inst>>9)&7)==0)?8:(inst>>9)&7,inst&7);\ else sprintf(tmpbuf,"d%d,d%d",(inst>>9)&7,inst&7);\ switch(inst&0x18){\ case 0x00:sprintf(sdebug,"as%s %s",sizedump,tmpbuf);break;\ case 0x08:sprintf(sdebug,"ls%s %s",sizedump,tmpbuf);break;\ case 0x10:sprintf(sdebug,"rox%s %s",sizedump,tmpbuf);break;\ case 0x18:sprintf(sdebug,"ro%s %s",sizedump,tmpbuf);break;\ }\ } regshift(m68_shl_r_n_b,"l.b") regshift(m68_shl_r_n_w,"l ") regshift(m68_shl_r_n_l,"l.l") regshift(m68_shr_r_n_b,"r.b") regshift(m68_shr_r_n_w,"r ") regshift(m68_shr_r_n_l,"r.l") /******************** NOP ********************/ static void m68_nop_____x(void){sprintf(sdebug,"nop");} /******************** LINK / UNLINK ********************/ static void m68_link_an_w(void){ int16 briefext=fetch(); sprintf(sdebug,"link a%d,%c#$"hex16,inst&7,briefext<0?'-':'+', briefext<0?-briefext:briefext ); } static void m68_unlk_an_x(void){ sprintf(sdebug,"unlk a%d",inst&7); } static void m68_stop____x(void){sprintf(sdebug,"stop #$%04X",fetch());} static void m68_rte_____x(void){sprintf(sdebug,"rte");} static void m68_rtr_____x(void){sprintf(sdebug,"rtr");} static void m68_reset___x(void){sprintf(sdebug,"reset");} static void m68_rtd_____x(void){ int16 briefext=fetch(); sprintf(sdebug,"rtd %c#$"hex16,briefext<0?'-':'+', briefext<0?-briefext:briefext); } static void m68_divu__n_w(void){ea;sprintf(sdebug,"divu %s,d%d",eabuffer,(inst>>9)&7);} static void m68_divs__n_w(void){ea;sprintf(sdebug,"divs %s,d%d",eabuffer,(inst>>9)&7);} static void m68_mulu__n_w(void){ea;sprintf(sdebug,"mulu %s,d%d",eabuffer,(inst>>9)&7);} static void m68_muls__n_w(void){ea;sprintf(sdebug,"muls %s,d%d",eabuffer,(inst>>9)&7);} static void m68_asr_m___w(void){ea;sprintf(sdebug,"asr %s",eabuffer);} static void m68_asl_m___w(void){ea;sprintf(sdebug,"asl %s",eabuffer);} static void m68_lsr_m___w(void){ea;sprintf(sdebug,"lsr %s",eabuffer);} static void m68_lsl_m___w(void){ea;sprintf(sdebug,"lsl %s",eabuffer);} static void m68_roxr_m__w(void){ea;sprintf(sdebug,"roxr %s",eabuffer);} static void m68_roxl_m__w(void){ea;sprintf(sdebug,"roxl %s",eabuffer);} static void m68_ror_m___w(void){ea;sprintf(sdebug,"ror %s",eabuffer);} static void m68_rol_m___w(void){ea;sprintf(sdebug,"rol %s",eabuffer);} static void m68_nbcd____b(void){ea;sprintf(sdebug,"nbcd.b %s",eabuffer);} static void m68_chk___n_w(void){ea;sprintf(sdebug,"chk %s,d%d",eabuffer,(inst>>9)&7);} static void m68_trap_nn_x(void){sprintf(sdebug,"trap #%d",inst&0xF);} static void m68_move_2u_l(void){sprintf(sdebug,"move.l a%d,usp",inst&7);} static void m68_move_fu_l(void){sprintf(sdebug,"move.l usp,a%d",inst&7);} static void m68_trapv___x(void){sprintf(sdebug,"trapv");} static char*specialregister(unsigned short int code){ switch(code&0xFFF){ case 0x000:return("sfc"); case 0x001:return("dfc"); case 0x800:return("usp"); case 0x801:return("vbr"); } return("???"); } static void m68_movec_r_x(void){ unsigned short int f=fetch(); sprintf(sdebug,"movec %s,%c%d", specialregister(f), (f&0x8000)?'a':'d',(f>>12)&7 ); } static void m68_movec_c_x(void){ unsigned short int f=fetch(); sprintf(sdebug,"movec %c%d,%s", (f&0x8000)?'a':'d',(f>>12)&7, specialregister(f) ); } /******************** SPECIAL INSTRUCTION TABLE ********************/ /* This table is used for 0100111001xxxxxx instructions (4E4x-4E7x) */ static void(*(debugspecialmap[64]))(void)={ /* 0000xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x, /* 0001xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x, /* 0010xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x, /* 0011xx */ m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x,m68_trap_nn_x, /* 0100xx */ m68_link_an_w,m68_link_an_w,m68_link_an_w,m68_link_an_w, /* 0101xx */ m68_link_an_w,m68_link_an_w,m68_link_an_w,m68_link_an_w, /* 0110xx */ m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x, /* 0111xx */ m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x,m68_unlk_an_x, /* 1000xx */ m68_move_2u_l,m68_move_2u_l,m68_move_2u_l,m68_move_2u_l, /* 1001xx */ m68_move_2u_l,m68_move_2u_l,m68_move_2u_l,m68_move_2u_l, /* 1010xx */ m68_move_fu_l,m68_move_fu_l,m68_move_fu_l,m68_move_fu_l, /* 1011xx */ m68_move_fu_l,m68_move_fu_l,m68_move_fu_l,m68_move_fu_l, /* 1100xx */ m68_reset___x,m68_nop_____x,m68_stop____x,m68_rte_____x, /* 1101xx */ m68_rtd_____x,m68_rts_____x,m68_trapv___x,m68_rtr_____x, /* 1110xx */ m68_unrecog_x,m68_unrecog_x,m68_movec_r_x,m68_movec_c_x, /* 1111xx */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x}; static void m68_special_x(void){ debugspecialmap[inst&0x3F](); } /******************** INSTRUCTION TABLE ********************/ /* The big 1024-element jump table that handles all possible opcodes is in the following header file. Use this syntax to execute an instruction: cpumap[i>>6](); ("i" is the instruction word) */ static void(*(debugmap[1024]))(void)={ /* 00000000ss */ m68_ori_____b,m68_ori_____w,m68_ori_____l,m68_unrecog_x, /* 00000001ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00000010ss */ m68_andi____b,m68_andi____w,m68_andi____l,m68_unrecog_x, /* 00000011ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00000100ss */ m68_subi____b,m68_subi____w,m68_subi____l,m68_unrecog_x, /* 00000101ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00000110ss */ m68_addi____b,m68_addi____w,m68_addi____l,m68_unrecog_x, /* 00000111ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00001000ss */ m68_btst_st_x,m68_bchg_st_x,m68_bclr_st_x,m68_bset_st_x, /* 00001001ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00001010ss */ m68_eori____b,m68_eori____w,m68_eori____l,m68_unrecog_x, /* 00001011ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00001100ss */ m68_cmpi____b,m68_cmpi____w,m68_cmpi____l,m68_unrecog_x, /* 00001101ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00001110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 00001111ss */ m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x,m68_bitopdn_x, /* 00010000ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010001ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010010ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010011ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010100ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010101ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010110ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00010111ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011000ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011001ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011010ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011011ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011100ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011101ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011110ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00011111ss */ m68_move____b,m68_move____b,m68_move____b,m68_move____b, /* 00100000ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100001ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100010ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100011ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100100ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100101ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100110ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00100111ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101000ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101001ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101010ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101011ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101100ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101101ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101110ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00101111ss */ m68_move____l,m68_move____l,m68_move____l,m68_move____l, /* 00110000ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110001ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110010ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110011ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110100ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110101ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110110ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00110111ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111000ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111001ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111010ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111011ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111100ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111101ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111110ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 00111111ss */ m68_move____w,m68_move____w,m68_move____w,m68_move____w, /* 01000000ss */ m68_negx____b,m68_negx____w,m68_negx____l,m68_movefsr_w, /* 01000001ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01000010ss */ m68_clr_____b,m68_clr_____w,m68_clr_____l,m68_movefcc_w, /* 01000011ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01000100ss */ m68_neg_____b,m68_neg_____w,m68_neg_____l,m68_move2cc_w, /* 01000101ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01000110ss */ m68_not_____b,m68_not_____w,m68_not_____l,m68_move2sr_w, /* 01000111ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01001000ss */ m68_nbcd____b,m68_pea_____l,m68_movem___w,m68_movem___l, /* 01001001ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01001010ss */ m68_tst_____b,m68_tst_____w,m68_tst_____l,m68_tas_____b, /* 01001011ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01001100ss */ m68_unrecog_x,m68_unrecog_x,m68_movem_r_w,m68_movem_r_l, /* 01001101ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01001110ss */ m68_unrecog_x,m68_special_x,m68_jsr_____x,m68_jmp_____x, /* 01001111ss */ m68_unrecog_x,m68_unrecog_x,m68_chk___n_w,m68_lea___n_l, /* 01010000ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_st______x, /* 01010001ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_sf______x, /* 01010010ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_shi_____x, /* 01010011ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_sls_____x, /* 01010100ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_scc_____x, /* 01010101ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_scs_____x, /* 01010110ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_sne_____x, /* 01010111ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_seq_____x, /* 01011000ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_svc_____x, /* 01011001ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_svs_____x, /* 01011010ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_spl_____x, /* 01011011ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_smi_____x, /* 01011100ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_sge_____x, /* 01011101ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_slt_____x, /* 01011110ss */ m68_addq__n_b,m68_addq__n_w,m68_addq__n_l,m68_sgt_____x, /* 01011111ss */ m68_subq__n_b,m68_subq__n_w,m68_subq__n_l,m68_sle_____x, /* 01100000ss */ m68_bra_____x,m68_bra_____x,m68_bra_____x,m68_bra_____x, /* 01100001ss */ m68_bsr_____x,m68_bsr_____x,m68_bsr_____x,m68_bsr_____x, /* 01100010ss */ m68_bhi_____x,m68_bhi_____x,m68_bhi_____x,m68_bhi_____x, /* 01100011ss */ m68_bls_____x,m68_bls_____x,m68_bls_____x,m68_bls_____x, /* 01100100ss */ m68_bcc_____x,m68_bcc_____x,m68_bcc_____x,m68_bcc_____x, /* 01100101ss */ m68_bcs_____x,m68_bcs_____x,m68_bcs_____x,m68_bcs_____x, /* 01100110ss */ m68_bne_____x,m68_bne_____x,m68_bne_____x,m68_bne_____x, /* 01100111ss */ m68_beq_____x,m68_beq_____x,m68_beq_____x,m68_beq_____x, /* 01101000ss */ m68_bvc_____x,m68_bvc_____x,m68_bvc_____x,m68_bvc_____x, /* 01101001ss */ m68_bvs_____x,m68_bvs_____x,m68_bvs_____x,m68_bvs_____x, /* 01101010ss */ m68_bpl_____x,m68_bpl_____x,m68_bpl_____x,m68_bpl_____x, /* 01101011ss */ m68_bmi_____x,m68_bmi_____x,m68_bmi_____x,m68_bmi_____x, /* 01101100ss */ m68_bge_____x,m68_bge_____x,m68_bge_____x,m68_bge_____x, /* 01101101ss */ m68_blt_____x,m68_blt_____x,m68_blt_____x,m68_blt_____x, /* 01101110ss */ m68_bgt_____x,m68_bgt_____x,m68_bgt_____x,m68_bgt_____x, /* 01101111ss */ m68_ble_____x,m68_ble_____x,m68_ble_____x,m68_ble_____x, /* 01110000ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01110001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01110010ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01110011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01110100ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01110101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01110110ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01110111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01111000ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01111001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01111010ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01111011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01111100ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01111101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 01111110ss */ m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l,m68_moveq_n_l, /* 01111111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10000000ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10000001ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10000010ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10000011ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10000100ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10000101ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10000110ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10000111ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10001000ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10001001ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10001010ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10001011ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10001100ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10001101ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10001110ss */ m68_or__d_n_b,m68_or__d_n_w,m68_or__d_n_l,m68_divu__n_w, /* 10001111ss */ m68_or__e_n_b,m68_or__e_n_w,m68_or__e_n_l,m68_divs__n_w, /* 10010000ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10010001ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10010010ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10010011ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10010100ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10010101ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10010110ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10010111ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10011000ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10011001ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10011010ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10011011ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10011100ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10011101ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10011110ss */ m68_sub_d_n_b,m68_sub_d_n_w,m68_sub_d_n_l,m68_suba__n_w, /* 10011111ss */ m68_sub_e_n_b,m68_sub_e_n_w,m68_sub_e_n_l,m68_suba__n_l, /* 10100000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10100111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10101111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 10110000ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10110001ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10110010ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10110011ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10110100ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10110101ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10110110ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10110111ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10111000ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10111001ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10111010ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10111011ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10111100ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10111101ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 10111110ss */ m68_cmp_d_n_b,m68_cmp_d_n_w,m68_cmp_d_n_l,m68_cmpa__n_w, /* 10111111ss */ m68_eor_e_n_b,m68_eor_e_n_w,m68_eor_e_n_l,m68_cmpa__n_l, /* 11000000ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11000001ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11000010ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11000011ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11000100ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11000101ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11000110ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11000111ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11001000ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11001001ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11001010ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11001011ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11001100ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11001101ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11001110ss */ m68_and_d_n_b,m68_and_d_n_w,m68_and_d_n_l,m68_mulu__n_w, /* 11001111ss */ m68_and_e_n_b,m68_and_e_n_w,m68_and_e_n_l,m68_muls__n_w, /* 11010000ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11010001ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11010010ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11010011ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11010100ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11010101ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11010110ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11010111ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11011000ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11011001ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11011010ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11011011ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11011100ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11011101ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11011110ss */ m68_add_d_n_b,m68_add_d_n_w,m68_add_d_n_l,m68_adda__n_w, /* 11011111ss */ m68_add_e_n_b,m68_add_e_n_w,m68_add_e_n_l,m68_adda__n_l, /* 11100000ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_asr_m___w, /* 11100001ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_asl_m___w, /* 11100010ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_lsr_m___w, /* 11100011ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_lsl_m___w, /* 11100100ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_roxr_m__w, /* 11100101ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_roxl_m__w, /* 11100110ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_ror_m___w, /* 11100111ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_rol_m___w, /* 11101000ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x, /* 11101001ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x, /* 11101010ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x, /* 11101011ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x, /* 11101100ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x, /* 11101101ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x, /* 11101110ss */ m68_shr_r_n_b,m68_shr_r_n_w,m68_shr_r_n_l,m68_unrecog_x, /* 11101111ss */ m68_shl_r_n_b,m68_shl_r_n_w,m68_shl_r_n_l,m68_unrecog_x, /* 11110000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11110111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111000ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111001ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111010ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111011ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111100ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111101ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111110ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x, /* 11111111ss */ m68_unrecog_x,m68_unrecog_x,m68_unrecog_x,m68_unrecog_x}; static void cpudebug_disassemble(int n) { while(n--) { dword addr = debugpc; cpudebug_printf("%08X: ", addr); isize = 0; inst = fetch(); debugmap[inst >> 6](); while(addr < debugpc) { cpudebug_printf("%04X ", s68000fetch(addr) & 0xFFFF); addr += 2; } while(isize < 10) { cpudebug_printf(" "); isize += 2; } cpudebug_printf("%s\n", sdebug); } } static void cpudebug_hexdump(void) { byte c, tmpchar[16]; dword tmpaddr; int i, j, k; tmpaddr = hexaddr & 0xFFFFFFF0; for(i = 0; i < 8; i++) { cpudebug_printf("%08X: %c", tmpaddr, (hexaddr == tmpaddr) ? '>' : ' ' ); for(j = 0; j < 16; j += 2) { k = s68000fetch(tmpaddr) & 0xFFFF; tmpchar[j ] = k >> 8; tmpchar[j + 1] = k & 0xFF; tmpaddr += 2; cpudebug_printf("%02X%02X%c", tmpchar[j], tmpchar[j + 1], (( hexaddr == tmpaddr )&&(j!=14))?'>': (((hexaddr&0xFFFFFFFE)==(tmpaddr-2))?'<':' ') ); } cpudebug_printf(" "); for(j = 0; j < 16; j++) { c = tmpchar[j]; if((c<32)||(c>126))c='.'; cpudebug_printf("%c", c); } cpudebug_printf("\n"); } hexaddr += 0x80; } static void cpudebug_registerdump(void) { int i; cpudebug_printf( "d0=%08X d4=%08X a0=%08X a4=%08X %c%c%c%c%c\n", s68000context.dreg[0],s68000context.dreg[4], s68000context.areg[0],s68000context.areg[4], (s68000context.sr >> 4) & 1 ? 'X' : '-', (s68000context.sr >> 3) & 1 ? 'N' : '-', (s68000context.sr >> 2) & 1 ? 'Z' : '-', (s68000context.sr >> 1) & 1 ? 'V' : '-', (s68000context.sr ) & 1 ? 'C' : '-' ); cpudebug_printf( "d1=%08X d5=%08X a1=%08X a5=%08X intmask=%d\n", s68000context.dreg[1], s68000context.dreg[5], s68000context.areg[1], s68000context.areg[5], (s68000context.sr >> 8) & 7 ); cpudebug_printf( "d2=%08X d6=%08X a2=%08X a6=%08X ", s68000context.dreg[2], s68000context.dreg[6], s68000context.areg[2], s68000context.areg[6] ); for(i = 1; i <= 7; i++) { if(s68000context.interrupts[0] & (1 << i)) { cpudebug_printf("%02X", s68000context.interrupts[i]); } else { cpudebug_printf("--"); } } cpudebug_printf( "\nd3=%08X d7=%08X a3=%08X a7=%08X %csp=%08X\n", s68000context.dreg[3], s68000context.dreg[7], s68000context.areg[3], s68000context.areg[7], ((s68000context.sr)&0x2000)?'u':'s', s68000context.asp ); debugpc = s68000context.pc; cpudebug_disassemble(1); debugpc = s68000context.pc; } int cpudebug_interactive( int cpun, void (*put)(const char*), void (*get)(char*, int), void (*execstep)(void), void (*dump)(void) ) { char inputstr[80]; char *cmd, *args, *argsend; dword tmppc; hexaddr = 0; cpudebug_put = put; cpudebug_get = get; for(;;) { s68000flushInterrupts(); cpudebug_printf("cpu%d-", cpun); cpudebug_gets(inputstr, sizeof(inputstr)); cmd = inputstr; while((tolower(*cmd) < 'a') && (tolower(*cmd) > 'z')) { if(!(*cmd)) break; cmd++; } if(!(*cmd)) continue; *cmd = tolower(*cmd); args = cmd + 1; while((*args) && ((*args) < 32)) args++; switch(*cmd) { case '?': cpudebug_printf( "b [address] Run continuously, break at PC=[address]\n" "d [address] Dump memory, starting at [address]\n" "h Hardware dump\n" "i [number] Generate hardware interrupt [number]\n" "j [address] Jump directly to [address]\n" "q Quit\n" "r Show register dump and next instruction\n" "s [n] Switch to CPU [n]\n" "t [hex number] Trace through [hex number] instructions\n" "u [address] Unassemble code, starting at [address]\n" ); break; case 'b': if(*args) { tmppc = strtoul(args, &argsend, 16); if(argsend != args) { while(s68000context.pc != tmppc) if(execstep) execstep(); else s68000exec(1); cpudebug_registerdump(); } else { cpudebug_printf("Invalid address\n"); } } else { cpudebug_printf("Need an address\n"); } break; case 'u': if(*args) { tmppc = strtoul(args, &argsend, 16); if(argsend != args) debugpc = tmppc; } cpudebug_disassemble(16); break; case 'd': if(*args) { tmppc = strtoul(args,&argsend,16); if(argsend != args) hexaddr = tmppc; } cpudebug_hexdump(); break; case 'h': if(dump) dump(); break; case 'j': if(*args) { tmppc = strtoul(args, &argsend, 16); if(argsend != args) { s68000context.pc = tmppc; cpudebug_printf("PC set to %08X\n", s68000context.pc ); debugpc = s68000context.pc; cpudebug_disassemble(1); debugpc = s68000context.pc; } else { cpudebug_printf("Invalid address\n"); } } else { cpudebug_printf("Need an address\n"); } break; case 'i': if(*args) { tmppc = strtoul(args, &argsend, 10); if(argsend != args) { cpudebug_printf("Interrupt %d generated\n", tmppc); s68000interrupt(tmppc, -1); s68000flushInterrupts(); cpudebug_registerdump(); debugpc = s68000context.pc; } else { cpudebug_printf("Invalid interrupt number\n"); } } else { cpudebug_printf("Need an interrupt number\n"); } break; case 't': tmppc = 1; if(*args) { tmppc = strtoul(args, &argsend, 16); if(argsend == args) tmppc = 1; } if(tmppc > 0) { while(tmppc--) { if(execstep) execstep(); else s68000exec(1); } cpudebug_registerdump(); } break; case 'r': cpudebug_registerdump(); break; case 'q': return -1; case 's': if(*args) { tmppc = strtoul(args, &argsend, 10); if(tmppc > 0) return tmppc; else cpudebug_printf("Invalid CPU number\n"); } else return 0; break; default: /* cpudebug_printf("Unknown command\n");*/ break; } } return -1; } dgen-sdl-1.23/star/cpudebug.h 644 1750 1750 735 7027317561 11172 /* ** Starscream 680x0 emulation library ** Copyright 1997, 1998, 1999 Neill Corlett ** ** Refer to STARDOC.TXT for terms of use, API reference, and directions on ** how to compile. */ #ifndef __CPUDEBUG_H__ #define __CPUDEBUG_H__ #ifdef __cplusplus extern "C" { #endif int cpudebug_disabled(void); int cpudebug_interactive( int cpun, void (*put)(const char*), void (*get)(char*, int), void (*execstep)(void), void (*dump)(void) ); #ifdef __cplusplus } #endif #endif dgen-sdl-1.23/star/starcpu.h 644 1750 1750 13304 7317431661 11111 /* ** Starscream 680x0 emulation library ** Copyright 1997, 1998, 1999 Neill Corlett ** ** Refer to STARDOC.TXT for terms of use, API reference, and directions on ** how to compile. */ #ifndef __STARCPU_H__ #define __STARCPU_H__ #ifdef __cplusplus extern "C" { #endif /* Remember to byte-swap these regions. (read STARDOC.TXT for details) */ struct STARSCREAM_PROGRAMREGION { unsigned lowaddr; unsigned highaddr; unsigned offset; }; struct STARSCREAM_DATAREGION { unsigned lowaddr; unsigned highaddr; void *memorycall; void *userdata; }; /* Memory structures for 16-bit data path */ #define STARSCREAM_CONTEXTINFO_MEM16 \ struct STARSCREAM_PROGRAMREGION *fetch; \ struct STARSCREAM_DATAREGION *readbyte; \ struct STARSCREAM_DATAREGION *readword; \ struct STARSCREAM_DATAREGION *writebyte; \ struct STARSCREAM_DATAREGION *writeword; \ struct STARSCREAM_PROGRAMREGION *s_fetch; \ struct STARSCREAM_DATAREGION *s_readbyte; \ struct STARSCREAM_DATAREGION *s_readword; \ struct STARSCREAM_DATAREGION *s_writebyte; \ struct STARSCREAM_DATAREGION *s_writeword; \ struct STARSCREAM_PROGRAMREGION *u_fetch; \ struct STARSCREAM_DATAREGION *u_readbyte; \ struct STARSCREAM_DATAREGION *u_readword; \ struct STARSCREAM_DATAREGION *u_writebyte; \ struct STARSCREAM_DATAREGION *u_writeword; \ /* Memory structures for 16-bit data path with function code support */ #define STARSCREAM_CONTEXTINFO_MEM16FC \ unsigned (*f_readbyte) (unsigned f, unsigned a); \ unsigned (*f_readword) (unsigned f, unsigned a); \ unsigned (*f_writebyte)(unsigned f, unsigned a); \ unsigned (*f_writeword)(unsigned f, unsigned a); \ /* Memory structures for 32-bit sizable data path */ #define STARSCREAM_CONTEXTINFO_MEM32 \ struct STARSCREAM_PROGRAMREGION *fetch; \ struct STARSCREAM_DATAREGION *readbus; \ struct STARSCREAM_DATAREGION *writebus; \ struct STARSCREAM_PROGRAMREGION *s_fetch; \ struct STARSCREAM_DATAREGION *s_readbus; \ struct STARSCREAM_DATAREGION *s_writebus; \ struct STARSCREAM_PROGRAMREGION *u_fetch; \ struct STARSCREAM_DATAREGION *u_readbus; \ struct STARSCREAM_DATAREGION *u_writebus; \ unsigned (*f_readbus) (unsigned f, unsigned a); \ unsigned (*f_writebus)(unsigned f, unsigned a); \ /* Common context info for all 680x0 types */ #define STARSCREAM_CONTEXTINFO_COMMON \ void (*resethandler)(void); \ unsigned dreg[8]; \ unsigned areg[8]; \ unsigned asp; \ unsigned pc; \ unsigned odometer; \ unsigned char interrupts[8]; \ unsigned short sr; \ /* 68000-specific context info */ #define STARSCREAM_CONTEXTINFO_68000SPECIFIC \ unsigned short contextfiller00; \ /* Context info for 68010 and higher */ #define STARSCREAM_CONTEXTINFO_68010 \ unsigned char sfc; \ unsigned char dfc; \ unsigned vbr; \ void (*bkpthandler)(void); \ /* 68010-specific context info */ #define STARSCREAM_CONTEXTINFO_68010SPECIFIC \ unsigned char loopmode; \ unsigned char contextfiller10[3]; \ /* Context info for 68020 and higher */ #define STARSCREAM_CONTEXTINFO_68020 \ unsigned asp2; \ struct S68000CONTEXT { STARSCREAM_CONTEXTINFO_MEM16 STARSCREAM_CONTEXTINFO_COMMON STARSCREAM_CONTEXTINFO_68000SPECIFIC }; struct S68010CONTEXT { STARSCREAM_CONTEXTINFO_MEM16 STARSCREAM_CONTEXTINFO_MEM16FC STARSCREAM_CONTEXTINFO_COMMON STARSCREAM_CONTEXTINFO_68010 STARSCREAM_CONTEXTINFO_68010SPECIFIC }; struct S68020CONTEXT { STARSCREAM_CONTEXTINFO_MEM32 STARSCREAM_CONTEXTINFO_COMMON STARSCREAM_CONTEXTINFO_68010 STARSCREAM_CONTEXTINFO_68020 }; #define STARSCREAM_IDENTIFIERS(SNC,SN) \ \ extern struct SNC##CONTEXT SN##context; \ \ int SN##init (void); \ unsigned SN##reset (void); \ unsigned SN##exec (int n); \ int SN##interrupt (int level, int vector); \ void SN##flushInterrupts (void); \ int SN##GetContextSize (void); \ void SN##GetContext (void *context); \ void SN##SetContext (void *context); \ int SN##fetch (unsigned address); \ unsigned SN##readOdometer (void); \ unsigned SN##tripOdometer (void); \ unsigned SN##controlOdometer (int n); \ void SN##releaseTimeslice (void); \ unsigned SN##readPC (void); \ STARSCREAM_IDENTIFIERS(S68000,s68000) STARSCREAM_IDENTIFIERS(S68010,s68010) STARSCREAM_IDENTIFIERS(S68020,s68020) #ifdef __cplusplus } #endif #endif dgen-sdl-1.23/star/stardoc.txt 644 1750 1750 116262 7027317562 11507 ----------------------------------------------------------------------------- Starscream 680x0 emulation library version 0.26a Copyright 1997, 1998, 1999 Neill Corlett ----------------------------------------------------------------------------- "Pathetic flesh creatures... can't you see we're INVINCIBLE? Come, Decepticons, follow me to victory!" How to contact Neill Corlett: email: corlett@elwha.nrrc.ncsu.edu www: http://www4.ncsu.edu/~nscorlet/ Contents -------- 0. Terms of Use 1. What's New 2. Getting Started 2.1. What You Will Need 2.2. How to Compile 3. The Starscream Interface 3.1. Function Reference 3.2. Contexts 3.3. Address Spaces 3.4. Executing Code 3.5. Read and Write Handlers 3.6. The Odometer 3.7. Interrupts 3.8. Emulating More Than One CPU 3.9. RESET and BKPT Instructions 3.10. Using the Interactive Debugger 3.11. Emulating the 68010 4. Tricks of the Trade 4.1. Inter-CPU Communication 4.2. Other Helpful Tips 4.3. Pitfalls 4.4. Ways to Abuse Starscream 4.5. Emulating Other 68K-Series CPUs 5. Known Bugs 6. Credits ----------------------------------------------------------------------------- 0. Terms of Use ----------------------------------------------------------------------------- "Starscream" refers to the following files: * STAR.C * STARCPU.H * CPUDEBUG.C * CPUDEBUG.H * STARDOC.TXT * any object file or executable compiled from the above * any source code generated from STAR.C, or object file assembled from such code Starscream may be distributed freely in unmodified form, as long as this documentation is included. No money, goods, or services may be charged or solicited for Starscream, or any emulator or other program which includes Starscream, in whole or in part. Using Starscream in a shareware or commercial application is forbidden. Contact Neill Corlett (corlett@elwha.nrrc.ncsu.edu) if you'd like to license Starscream for commercial use. Any program which uses Starscream must include the following credit text, in its documentation or in the program itself: "Starscream 680x0 emulation library by Neill Corlett (corlett@elwha.nrrc.ncsu.edu)" ----------------------------------------------------------------------------- 1. What's New ----------------------------------------------------------------------------- Version 0.26a: * Egregious GetContext/SetContext bug fixed. * Minor tweaking was done to the alignment rules. Version 0.26: * First publicly redistributable version. * Added the following exceptions: Trace Format Error (68010+) * Added a Double Fault mechanism. Currently the only thing that can cause this is s68000reset(). * The memory map interface has changed to support different function codes / address spaces (see section 3.3). * Many improvements have been made to interrupt handling (see section 3.7). * The unused bits of PC are now handled and preserved properly. * Added fetch region caching. Jumps within the same program region are now faster. * Added a user-definable BKPT instruction handler (68010+). * All Illegal Instruction exceptions are now emulated. The -illegal and -noillegal options have been removed. * Some features were added to the interactive debugger (see section 3.10). * A few experimental 68020-related functions and variables have been added. Ignore them for now. Version 0.25 and earlier: Ask if interested. ----------------------------------------------------------------------------- 2. Getting Started ----------------------------------------------------------------------------- 2.1. What You Will Need ------------------------ * A 32-bit C or C++ compiler. So far, the following compilers have been proven to work: - DJGPP 2.01 - Watcom 10.6 - GCC, running under Linux - Microsoft Visual C++ * Netwide Assembler (NASM) version 0.95 or higher. NASM is freeware, with publicly available source code, and available on a multitude of x86-based platforms. It's available from Programmer's Heaven: http://www.programmersheaven.com/ * Basic knowledge about the 680x0. You don't (theoretically) need to know any 680x0 assembly, but it helps. A lot. You can get a copy of the M68000 Family Programmer's Reference Manual (in Adobe Acrobat .PDF format) from this web page: http://www.mot.com/SPS/HPESD/prod/0X0/frames/68K.html 2.2. How to Compile -------------------- Step 1 Generate the Starscream "code builder" executable by compiling STAR.C. (for example: gcc star.c -o star) Step 2 Generate the CPU source code. Run the code builder with the following command line: star source.asm [options] Replace "source.asm" with the source code filename of your choice. Options that you might need: -regcall Use register calling conventions. -stackcall Use stack-based calling conventions (default). -hog Enable Hog mode. This inlines the fetch-decode- execute loop, resulting in a decent speed increase, at the cost of about 130K of executable size. -nohog Disable Hog mode (default). -cputype Specify the CPU type, 68000 or 68010 (default=68000). Options that you should never need (but they're here anyway): -addressbits n Use n-bit addresses. The default value depends on the CPU type (currently it's just 24). "-addressbits 32" might allow some 68020/68070 code to work. No guarantees, though. -name Appends the string to all identifiers. This overrides the default of s68000 or s68010 (depending on the CPU type). Step 3 Assemble the CPU source code. Refer to the NASM documentation for how to do this. If you run out of memory, try using NASMW.EXE instead of NASM.EXE (note, however, that the NASMW.EXE executable from v0.97 is somewhat unstable). Better yet, just recompile NASM yourself. Worked for me. To generate a COFF object for DJGPP or GNUWin32, try this: nasm -f coff source.asm or to generate a Win32 object for Watcom or Visual C++: nasm -f win32 source.asm Step 4 Strip your executable when you're done! Starscream spews out symbols all over the place (over 7000 of them), and you can save a ton of space by stripping them once you're finished debugging. For GCC, this means use the -s option in the linking phase. ----------------------------------------------------------------------------- 3. The Starscream Interface ----------------------------------------------------------------------------- 3.1. Function Reference ------------------------ The following is a brief summary of the functions declared in STARCPU.H. For more information on a particular function, read the associated section. int s68000init(void); (section 3.4) Initializes Starscream. Always returns 0. int s68000reset(void); (section 3.4) Resets the current CPU. Return value: 0 Success 1 Failure: Reset vector couldn't be fetched -1 Failure: Double fault unsigned s68000exec(int n); (section 3.4) Executes n cycles' worth of instructions on the current CPU. Return value: = 0x80000000 Success = 0x80000001 Out of bounds = 0x80000002 Unsupported stack frame (68010+) = 0xFFFFFFFF Double fault < 0x80000000 Invalid instruction; the value returned is the address of the instruction int s68000interrupt(int level, int vector); (section 3.7) Generates a hardware interrupt on the current CPU, with a given priority level and vector number. The interrupt is queued for processing as soon as possible. Valid levels: 1-7 Valid vectors: 0-255 Deliberately vectored interrupt -1 Auto-vectored interrupt -2 Spurious interrupt Return value: 0 The interrupt was queued successfully. 1 The interrupt was not queued, because a previously queued interrupt exists at the same level. 2 The interrupt was not queued, because either "level" or "vector" were invalid. void s68000flushInterrupts(void); (section 3.7) Check if there are any unmasked interrupts pending, and if so, process them. int s68000GetContextSize(void); Returns the size of the context structure. Useful for verifying that the context struct is packed correctly, i.e.: ASSERT(s68000GetContextSize() == sizeof(struct S68000CONTEXT)); void s68000GetContext(void *context); (section 3.2) Copies the current context into another context structure. void s68000SetContext(void *context); (section 3.2) Copies a context structure into the current context. int s68000fetch(unsigned address); Fetches the word at the specified address, using the memoryfetch array. Returns -1 if the address is out of bounds. unsigned s68000readOdometer(void); (section 3.6) Returns the value of the odometer for the current CPU. Works anywhere, even from within memory read/write, RESET, or BKPT handlers. unsigned s68000tripOdometer(void); (section 3.6) Returns the value of the odometer for the current CPU, and resets it to zero. Works anywhere. unsigned s68000controlOdometer(int n); (section 3.6) Returns the value of the odometer for the current CPU. If n!=0, it also resets the odometer to zero. Works anywhere. void s68000releaseTimeslice(void); (section 3.5) When called from inside a memory read/write, RESET, or BKPT handler, this causes s68000exec to end prematurely. The early exit is reflected in the odometer. unsigned s68000readPC(void); Returns the current program counter. Works anywhere. 3.2. Contexts -------------- A "context" is a memory structure which holds all the information needed to emulate a single CPU. Starscream defines a 68000 context as follows: struct S68000CONTEXT { struct STARSCREAM_PROGRAMREGION *fetch; struct STARSCREAM_DATAREGION *readbyte; struct STARSCREAM_DATAREGION *readword; struct STARSCREAM_DATAREGION *writebyte; struct STARSCREAM_DATAREGION *writeword; struct STARSCREAM_PROGRAMREGION *s_fetch; struct STARSCREAM_DATAREGION *s_readbyte; struct STARSCREAM_DATAREGION *s_readword; struct STARSCREAM_DATAREGION *s_writebyte; struct STARSCREAM_DATAREGION *s_writeword; struct STARSCREAM_PROGRAMREGION *u_fetch; struct STARSCREAM_DATAREGION *u_readbyte; struct STARSCREAM_DATAREGION *u_readword; struct STARSCREAM_DATAREGION *u_writebyte; struct STARSCREAM_DATAREGION *u_writeword; void (*resethandler)(void); unsigned dreg[8]; unsigned areg[8]; unsigned asp; unsigned pc; unsigned odometer; unsigned char interrupts[8]; unsigned short sr; }; There is a built-in context, called s68000context, which contains information about the current CPU. If you're only emulating one 68000, then s68000context is the only context you need. On the other hand, if you're emulating more than one 68000, you'll need to define your own context for each one. Here is a detailed description of the contents of a S68000CONTEXT structure: * "s_fetch", "s_readbyte", "s_readword", "s_writebyte", and "s_writeword" are used to define the supervisor address space. "u_fetch", etc. are used to define the user address space. (see section 3.3) * "resethandler" points to your reset handler routine. (see section 3.9) * "pc" is the program counter. * "dreg" holds the eight data registers, d0-d7, in order. * "areg" holds the eight address registers, a0-a7, in order. In supervisor mode, areg[7] is the interrupt stack pointer. Otherwise, it's the user stack pointer. * "asp" is whatever stack register areg[7] isn't. In supervisor mode, asp is the user stack pointer. Othewise, it's the supervisor stack pointer. * "odometer" holds the number of cycles executed so far. It's incremented as necessary on calls to s68000exec or s68000flushInterrupts. * "interrupts" is an array containing information about pending interrupts. (see section 3.7) * "sr" is the status register. The lower 8 bits are the condition code register. 3.3. Address Spaces -------------------- The 68000 communicates with other devices via a number of address spaces. There are different address spaces for program code and data, as well as different address spaces for Supervisor and User modes. Most 68000-based architectures use the same address space for all these, but the distinction is there nonetheless. Starscream emulates program address spaces by translating the 68K address into a native host address, and fetching data directly from host memory (from an array of words with native byte order). A program address space is defined using an array of STARSCREAM_PROGRAMREGION structures: struct STARSCREAM_PROGRAMREGION { unsigned lowaddr; unsigned highaddr; unsigned offset; }; Each structure contains the range of addresses in a program region, and an offset which is added to the 68K address to obtain the equivalent host address. IMPORTANT NOTE: Program regions must be stored as an array of words with native byte order. Since Intel's byte order is different than Motorola's, this means every other byte must be swapped. The s68000context fields "s_fetch" and "u_fetch" should be set to point to arrays of STARSCREAM_PROGRAMREGION structures in order to define the Supervisor Program and User Program address spaces, respectively. Each array may contain any number of entries, and is terminated by an entry containing -1 for both lowaddr and highaddr, and NULL for the offset. Starscream emulates data address spaces in a completely different way. Since the 68000 has no dedicated I/O bus, device interfaces (video/sound chips, input devices, etc.) are often mapped directly into a data address space. This raises some complex issues; for example, writing to an emulated serial port address might require that an extra routine be called, in order to pass the data through a real serial port, append it to a log file, etc. To this end, Starscream defines data address spaces using an array of STARSCREAM_DATAREGION structures: struct STARSCREAM_DATAREGION { unsigned lowaddr; unsigned highaddr; void *memorycall; void *userdata; }; Each structure contains the low and high addresses in a region, as before. Rather than simply adding a constant offset to translate a 68K address into a native one, Starscream offers two different ways to handle accesses to a data region: 1. Call a user-defined handler routine whenever this region is accessed. unsigned read_handler(unsigned address); void write_handler(unsigned address, unsigned data); memorycall = pointer to user handler userdata = unused (For some important information about read and write handlers, refer to section 3.5.) 2. Handle accesses internally by reading/writing to an area of native memory. Don't trap anything. This is ideal for a simple RAM or ROM area as it requires the least processing. memorycall = NULL userdata = pointer to native memory area where reads or writes will occur NOTE: The native memory area must be byte swapped, same as program regions are. The s68000context fields "s_readbyte", "u_readbyte", "s_writebyte", etc. should be set to point to arrays of STARSCREAM_DATAREGION structures in order to define the Supervisor Data and User Data address spaces. Each array may contain any number of entries, and is terminated by an entry containing -1 for lowaddr and highaddr, and NULL for memorycall and userdata. And now, for an example of address space definition. Consider the following make-believe memory map: 000000-03FFFF: Program ROM 300000-307FFF: Main RAM 400000-407FFF: Extra RAM 800000-81FFFF: Video RAM A00000-A00007: Sound chip Assume that: * Program ROM is in an array called program_rom * Main RAM is in an array called main_ram * Extra RAM is in an array called extra_ram * Video RAM is in an array called video_ram * You've set up two routines to write to the sound chip: void soundchip_writebyte(unsigned address, unsigned data); void soundchip_writeword(unsigned address, unsigned data); The first step is to build the program address space. Program code is probably only going to be fetched from Program ROM, Main RAM, or Extra RAM. The address space would thus be defined: struct STARSCREAM_PROGRAMREGION pretend_programfetch[] = { {0x000000, 0x03FFFF, (unsigned)program_rom - 0x000000}, {0x300000, 0x307FFF, (unsigned)main_ram - 0x300000}, {0x400000, 0x407FFF, (unsigned)extra_ram - 0x400000}, {-1, -1, NULL} }; The last entry must be {-1, -1, NULL}. The next step is to build the data address space. This is accomplished with four arrays of STARSCREAM_DATAREGION structures: one for byte reads, word reads, byte writes, and word writes. For example: struct STARSCREAM_DATAREGION pretend_readbyte[] = { {0x000000, 0x03FFFF, NULL, program_rom}, {0x300000, 0x307FFF, NULL, main_ram}, {0x400000, 0x407FFF, NULL, extra_ram}, {0x800000, 0x81FFFF, NULL, video_ram}, {-1, -1, NULL, NULL} }; struct STARSCREAM_DATAREGION pretend_readword[] = { {0x000000, 0x03FFFF, NULL, program_rom}, {0x300000, 0x307FFF, NULL, main_ram}, {0x400000, 0x407FFF, NULL, extra_ram}, {0x800000, 0x81FFFF, NULL, video_ram}, {-1, -1, NULL, NULL} }; struct STARSCREAM_DATAREGION pretend_writebyte[] = { {0x300000, 0x307FFF, NULL, main_ram}, {0x400000, 0x407FFF, NULL, extra_ram}, {0x800000, 0x81FFFF, NULL, video_ram}, {0xA00000, 0xA00007, soundchip_writebyte, NULL}, {-1, -1, NULL, NULL} }; struct STARSCREAM_DATAREGION pretend_writeword[] = { {0x300000, 0x307FFF, NULL, main_ram}, {0x400000, 0x407FFF, NULL, extra_ram}, {0x800000, 0x81FFFF, NULL, video_ram}, {0xA00000, 0xA00007, soundchip_writeword, NULL}, {-1, -1, NULL, NULL} }; The last entry of each array must be {-1, -1, NULL, NULL}. The above structures take advantage of Starscream's internal handling for the Program ROM, Main RAM, Extra RAM, and Video RAM, and use the custom handler when writing to the sound chip. Now that you've defined your address spaces, you need to tie it in with the context (since each CPU can have different address spaces). This is done by setting the address space pointers (s_fetch, u_fetch, etc.) to point to your addres space definitions. s68000context.s_fetch = pretend_programfetch; s68000context.u_fetch = pretend_programfetch; s68000context.s_readbyte = pretend_readbyte; s68000context.u_readbyte = pretend_readbyte; s68000context.s_readword = pretend_readword; s68000context.u_readword = pretend_readword; s68000context.s_writebyte = pretend_writebyte; s68000context.u_writebyte = pretend_writebyte; s68000context.s_writeword = pretend_writeword; s68000context.u_writeword = pretend_writeword; In this example, the Supervisor and User address spaces are set up to point to the same definitions. For most 68000-based architectures, this is correct. If you are dynamically allocating memory for your emulated RAM or ROM areas (using malloc() or a similar function), you will have to set up the address space definitions at run time. This is left as a trivial exercise for the reader. Veteran users of the UAE 680x0 core might wonder why there is no "readlong" or "writelong". This is because the real 68000 has a 16-bit data bus, and therefore breaks up each 32-bit access into two 16-bit accesses. Using separate handlers for 32-bit accesses is cumbersome and unnecessary. For speed considerations, Starscream's internal memory read/write handlers access 32 bits at a time wherever possible (using the readword/writeword map). 3.4. Executing Code -------------------- Before you execute any code, you must call s68000init(). It only needs to be called one time. Once that's done, and you've set up the memory map, call s68000reset() to reset the CPU. If everything works, it should read the initial stack pointer from address 0x000000, and the initial program counter from 0x000004, using the Supervisor Program address space. (You can verify this by examining s68000context.areg[7] and s68000context.pc.) At this point, you can call the interactive debugger to try disassembling or stepping through code, and to make sure everything is in the right place. (see section 3.10 for details) To execute 68000 code, call s68000exec(n), where n is the number of cycles. s68000exec will return one of the following: = 0x80000000: Success. = 0x80000001: Out of range - the program "went off into the weeds". More specifically, the program jumped to an address which was not defined in the s_fetch or u_fetch array. = 0x80000002: Unsupported stack frame (68010+). This happens when an RTE instruction encounters a stack frame format that hasn't been implemented (see section 5). = 0xFFFFFFFF: Double fault. The CPU is dead and will stay dead until it gets reset again. < 0x80000000: Invalid instruction. The value returned is the address of the instruction. For 32-bit addresses, the highest bit is cut off (s68000context.pc contains the complete address, however). If you get a return code of 0x80000001, 0x80000002, or 0xFFFFFFFF, then the 68000 CPU will be in an unstable state and should be reset. The real 68000 generates an exception for illegal instructions. As of v0.26, this exception is always emulated. You will only get a return code less than 0x80000000 in an unexpected circumstance; upon encountering an invalid instruction that isn't supposed to be. For example, a RESET instruction will cause this if the user-defined RESET handler is null (see section 3.9 for details on RESET handlers). Whenever you call s68000exec, it increments the odometer (see section 3.6). 3.5. Read and Write Handlers ----------------------------- Memory read and write handlers (as described in section 3.3) are a special case, as they involve Starscream calling your code instead of the other way around. Since Starscream is not re-entrant, there are some rules which all read and write handlers must follow. 1. They must not call any of the following routines: s68000reset s68000exec s68000SetContext s68000GetContext 2. They must not attempt to read or modify s68000context directly. All data in s68000context is undefined. The primary purpose of a read handler is to return data, and the primary purpose of a write handler is to take data and store it somewhere. However, read and write handlers do have some control over the emulation process, beyond the data that they send or receive: * You can call s68000interrupt() as much as you like (see section 3.7). * You can cause s68000exec to quit early, by calling the s68000releaseTimeslice() function. This is useful if you need to transfer control over to another emulated CPU. * You can read and/or clear the odometer, with some specialized functions (see section 3.6). * You can read the program counter with s68000readPC(), but it probably won't be located exactly at the beginning of the instruction. 3.6. The Odometer ------------------ Every context contains an integer field called "odometer". Whenever you call s68000exec, the number of elapsed clock cycles is added to s68000context.odometer. Note: When calling s68000exec, the number of elapsed cycles is not necessarily the same as the number of cycles you specify. Imagine this scenario: You call s68000exec(100). The next instruction in the code stream is... movem.l ($100000).L,d0-d7/a0-a7 s68000exec would quit after that one instruction, returning the success code, 80000000h (assuming nothing else went wrong), and s68000context.odometer would be incremented by 148. You can freely change the odometer between calls to s68000exec, but not from within read/write handlers (as it's part of the context). If you need to use the odometer from a read or write handler, there are some specialized functions for that: s68000readOdometer() - Returns the value of the odometer. s68000tripOdometer() - Returns the value of the odometer, and sets it to zero in the process. s68000controlOdometer(n) - If n==0, it works just like s68000readOdometer. If n!=0, it works just like s68000tripOdometer. (We have Neil Bradley to thank for this gem...) 3.7. Interrupts ---------------- Hardware interrupts can be generated at any time, including within read/write handlers, by calling s68000interrupt(l, v) where l is the interrupt priority level, and v is the vector number. Levels 1-7 are valid; vector numbers 0-255 are valid. Vector number -1 means "auto-vectored". -2 will generate a Spurious Interrupt. The interrupt in question will be made pending until the Processor Priority Level allows it to be processed. You can tell which interrupt levels are pending, if any, by examining s68000context.interrupts[0]. Bits 1-7 correspond to interrupt level 1-7; bit 0 is set if the CPU is in a stopped state (waiting for an interrupt). The vector numbers are stored in s68000context.interrupts[n] where n is the interrupt level. s68000interrupt returns one of the following values: 0 The interrupt was added successfully. 1 The interrupt was not added, because there was already a pending interrupt at the same level. 2 The interrupt was not added, because the parameters were invalid. Pending interrupts are checked at the following times: * s68000exec checks for pending interrupts before executing any code. The cycles taken by interrupt processing are subtracted from the total "cycle budget", though s68000exec is still guaranteed to execute at least one instruction. * Interrupts generated from within a read/write, RESET, or BKPT handler will be checked when the current instruction is finished. * You can force a pending interrupt check by calling s68000flushInterrupts. This has no effect if called from within a read/write, RESET, or BKPT handler. 3.8. Emulating More Than One CPU --------------------------------- If you want to emulate multiple 68000s, you'll need to create a context and a memory map for each one (see sections 3.2 and 3.3). For example: struct S68000CONTEXT myContext[number_of_68000s]; When you use your own contexts, it's a good idea to initialize all the bytes in the new contexts to zero: memset (myContext, 0, sizeof(myContext)); To use one of your own contexts, you must follow these three steps: 1. Copy your context into s68000context: s68000SetContext(myContext); 2. Use a function which reads or modifies the context - s68000exec, s68000reset, s68000interrupt, etc. 3. Copy s68000context back into your context: s68000GetContext(myContext); Expanding on the example in section 3.2 - say you're emulating two 68000s, and you've set up two contexts for them: struct S68000CONTEXT myContext[2]; To reset both CPUs, you'd do this: for(i = 0; i < 2; i++) { s68000SetContext(&myContext[i]); s68000reset(); s68000GetContext(&myContext[i]); } An emulation loop involving both CPUs might look something like this. (Note: This is a CRUDE example.) while(!done) { /* Emulate primary 68000 */ s68000SetContext(&myContext[0]); s68000exec(100000); s68000GetContext(&myContext[0]); /* Emulate secondary 68000 */ s68000SetContext(&myContext[1]); s68000exec(100000); s68000GetContext(&myContext[1]); } The overhead of copying CPU contexts is compensated by the fact that you can emulate the CPUs in large timeslices. 3.9. RESET and BKPT Instructions --------------------------------- Starscream can call a user-defined function to emulate the RESET instruction, and to notify when a BKPT instruction is executed. The handlers must take no arguments, and return void. For example: void my_reset_handler(void) { /* Reset some hardware */ } Note: RESET and BKPT handlers must follow the same rules as memory read/write handlers (see section 3.5). To register a handler function, set the "resethandler" and/or "bkpthandler" field of the appropriate context to point to the function, i.e.: s68000context.resethandler = my_reset_handler; You can also set "resethandler" or "bkpthandler" to NULL, in which case: * A RESET instruction will cause an Invalid Instruction case. s68000exec will halt and return its address. * A BKPT instruction will behave normally, but without notification. Calling s68000readPC() during a RESET or BKPT handler will return the address directly after the RESET or BKPT instruction. So, to determine the exact BKPT opcode, you can do this: opcode = s68000fetch(s68000readPC() - 2); 3.10. Using the Interactive Debugger ------------------------------------- Included in the Starscream package is an interactive 68000 cross-debugger and built in disassembler, with an interface similar to the MS-DOS DEBUG utility. CPUDEBUG.C contains everything needed for the debugger. If you don't need it, you can leave out CPUDEBUG.C and CPUDEBUG.H altogether. Before using the debugger, make sure to set up your memory map, and call s68000init() and s68000reset(). To start the debugger, call the cpudebug_interactive routine, which is defined in CPUDEBUG.H as: int cpudebug_interactive( int cpun, void (*put)(const char*), void (*get)(char*, int), void (*execstep)(void), void (*dump)(void) ); "put", "get", "execstep", and "dump" are all optional - you can pass NULL values for any or all of them. Their purpose is explained below. If you're only emulating one CPU, use a value of 1 for "cpun", and keep calling cpudebug_interactive until the return value is -1. If you're debugging more than one CPU, assign an ID number to each (starting at 1), including any non-68000 CPUs. Switch to the context of the CPU you want to debug, and then call cpudebug_interactive with the appropriate ID number in "cpun". Then, take one of the following actions depending on the return value: -1 Quit 0 Switch to the next CPU in your list (ID + 1), wrap around if necessary, and call cpudebug_interactive again. Or, if the CPU in question is not a 680x0, then use whatever debugger is appropriate. N Switch to CPU #N. If N is invalid, don't switch. In either case, call the appropriate debugger. While you're at the debug prompt, enter "?" for a list of commands. Normally, the interactive debugger uses stdin and stdout for its input and output. If you need to use another source of input or output, you can write custom replacement functions for puts() and gets(), and pass their addresses via "put" and "get". Normally, the debugger calls s68000exec() directly to step through each instruction. If your emulator manages its own timing, you can write a custom replacement single-step function, and pass its address via "execstep". The debugger command 'h' (Hardware dump) will call the function specified by "dump", if it exists. 3.11. Emulating the 68010 -------------------------- To generate a 68010 emulator, use the "-cputype 68010" option when building your source code file. The names of all identifiers will begin with s68010 instead of s68000 (unless overridden by the -name option). When emulating the 68010, use the S68010CONTEXT structure instead of S68000CONTEXT. S68010CONTEXT has six new fields: unsigned char sfc; unsigned char dfc; unsigned vbr; void (*bkpthandler)(void); unsigned char loopmode; unsigned char contextfiller10[3]; "vbr", "sfc", and "dfc" are control registers. "bkpthandler" is a user-defined routine for BKPT notification (see section 3.8). "loopmode" is used internally for loop mode timing. (Did I mention the loop mode timing is insanely accurate?) "contextfiller10" is there just to maintain alignment. An invalid MOVEC register code will cause s68010exec to return with an invalid instruction error, pointing to the MOVEC instruction (not the code itself). NOTE: The interactive debugger currently does not support the 68010. ----------------------------------------------------------------------------- 4. Tricks of the Trade ----------------------------------------------------------------------------- 4.1. Inter-CPU Communication ----------------------------- Many arcade and console game systems which use multiple CPUs use a sort of "mailbox" technique to allow the main CPU to send messages to the sub CPU (sound effect numbers, etc.) When one of your 68000s writes to another CPU's mailbox, it's generally a good idea to transfer control over to the other CPU temporarily. This can be achieved by calling s68000releaseTimeslice() from your I/O handler. This will cause s68000exec to exit, even if it's not finished. (Always check the odometer to see how many cycles were really executed!) 4.2. Other Helpful Tips ------------------------ When defining your memory map(s): * Take advantage of the built-in RAM and ROM handling as much as possible. They involve much less "red tape" than using your own handlers. * The addresses don't have to be in order. You can rearrange them so that the most commonly-accessed areas are at the beginning. This will shave a few cycles off each access. * If you have two areas of fetchable RAM or ROM that are right next to each other, consider coalescing them into one area. This will make the memory map simpler and facilitate fetch region caching. It will also allow the 680x0 code to wander from one area into the next. Starscream only checks boundaries after JMP, JSR, RTS, RTR, RTD, RTE, and exceptions. When executing code: * Instead of calling s68000exec with a fixed number of cycles, keep track of how many cycles overflowed from the last call to s68000exec, and subtract them: #define TIMESLICE 100000 s68000context.odometer = 0; while(!done) { if (s68000context.odometer < TIMESLICE) { s68000exec(TIMESLICE - s68000context.odometer); } s68000context.odometer -= TIMESLICE; } * Use big timeslices. The fewer calls you make to s68000exec, the better. 4.3. Pitfalls -------------- * Make sure to include "starcpu.h" in any of your C modules that use Starscream. Also remember that starcpu.h is subject to change in new versions. (Hint hint.) * Remember to call s68000init before executing any code. s68000init doesn't automatically call s68000reset, so you must call s68000reset also. * Remember to set up your memory map before calling s68000reset. The memory map is required in order to read the initial SSP/PC from the vector table. * When you store a context via s68000SetContext, remember to read it back via s68000GetContext. * The interactive debugger can only read memory areas that are defined in your STARSCREAM_PROGRAMREGION array. Everything else will appear as FFFF. The upshot of this is that a memory dump is guaranteed not to trigger any I/O hardware. * Simplify your STARSCREAM_PROGRAMREGION map as much as possible, in case the emulated code decides to wander from one area to another. * Remember the rules for read/write handlers (section 3.5), and remember that they also apply to RESET and BKPT handlers (section 3.9). * When you use your own contexts, make sure to explicitly set "resethandler" and "bkpthandler" to NULL if you're not using them. (This is why it's a good idea to initialize every byte of a new context to zero.) 4.4. Ways to Abuse Starscream ------------------------------ For the adventurous... * Upon encountering an unrecognized opcode, s68000exec will return the address of the opcode, instead of the success code, 0x80000000. If you need to emulate an instruction that's not implemented yet, you can take advantage of this behavior and implement it in your own code. Outside of s68000exec, the context can be modified freely. You can use the s68000fetch routine to fetch the unrecognized opcode and anything after it (see section 3.1 for the declaration of s68000fetch). * Using 32-bit addresses (-addressbits 32) saves one cycle for every memory access, and simplifies the PC re-basing process. This is safe only for software that is "32-bit clean", however. * Make a stand-alone 68000 disassembler out of CPUDEBUG.C. ;) 4.5. Emulating Other 68K-Series CPUs ------------------------------------- Note: None of these are officially supported. 68008 Try "-cputype 68000 -addressbits 20" or "-cputype 68000 -addressbits 22", depending on the chip package. You'll have to lower the clock speed to get more accurate timing (try dividing it in half), and you might have to compensate for the 8-bit data bus. 68EC000 "-cputype 68000" should work. If it's running in 8-bit mode, try dividing the clock speed in half. SCC68070 Try "-cputype 68000 -addressbits 32". Not sure about timing issues. 6833X (CPU32) Try "-cputype 68010". Timing might be a little slow. A few instructions aren't supported. 68020 and higher Try "-cputype 68010 -addressbits 32". This is a bit of a stretch, though, since the 68020 supports many new address modes and instructions. Failing that, wait until official 68020 support is added. ;) ----------------------------------------------------------------------------- 5. Known Bugs ----------------------------------------------------------------------------- * Address and Bus Errors are not implemented. For arcade game emulation, this is probably OK, but if you're emulating a home computer system, this could be cause for concern. * The MOVES instruction (68010+) is not implemented. * Stack frame format 8 (68010+) is not supported. Starscream will never generate such a stack frame itself; however, if this format is encountered during a RTE, s68010exec() will return with an "Unsupported stack frame" error. * There are a few timing inaccuracies: 68000: DIVS and DIVU: +/- 5% 68010: MULS and MULU are inaccurate, but I'm not sure by how much. * Flags which Motorola documents as "Undefined" are, in fact, undefined. I could probably look up how they're calculated, and implement them, but the need has not arisen (yet). ----------------------------------------------------------------------------- 6. Credits ----------------------------------------------------------------------------- Thanks to: * Heinz Seltmann, for letting me borrow his M68000 Microprocessor User's Manual (Ninth Edition) for way too long. * Neil Bradley, Mike Cuddy, James Boulton, Richard Bush, and Dave (of DTMNT/ DGen fame) for various tips and ideas. * Thierry Lescot, who gave me the idea to distribute Starscream in the first place. dgen-sdl-1.23/musa/Makefile.in 644 1750 1750 20452 7320415000 11301 # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # DGen/SDL v1.20+ # Automakefile for Musashi # hack it so that musa doesn't get affected by memcpy defines SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_alias = @build_alias@ build_triplet = @build@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ AWK = @AWK@ CC = @CC@ CHOP_ = @CHOP_@ CPP = @CPP@ CPUDIRS = @CPUDIRS@ CXX = @CXX@ CXXCPP = @CXXCPP@ EXTRAOBJS = @EXTRAOBJS@ INTERFACE = @INTERFACE@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ MUSA = @MUSA@ MZ80 = @MZ80@ NASM = @NASM@ NASM_FMT = @NASM_FMT@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STAR = @STAR@ VERSION = @VERSION@ CFLAGS = @CFLAGS@ -Umemcpy noinst_PROGRAMS = m68kmake noinst_LIBRARIES = libmusa68.a m68kmake_SOURCES = m68kmake.c EXTRA_libmusa68_a_SOURCES = m68k_in.c m68kmake.c m68kops.h libmusa68_a_SOURCES = m68kcpu.c m68kcpu.h m68k.h m68kconf.h libmusa68_a_LIBADD = m68kops.o m68kopac.o m68kopdm.o m68kopnz.o libmusa68_a_DEPENDENCIES = m68kmake m68kops.o m68kopac.o m68kopdm.o m68kopnz.o DISTCLEANFILES = m68kops.c m68kopac.c m68kopdm.c m68kopnz.c m68kmake mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ libmusa68_a_OBJECTS = m68kcpu.o AR = ar PROGRAMS = $(noinst_PROGRAMS) m68kmake_OBJECTS = m68kmake.o m68kmake_LDADD = $(LDADD) m68kmake_DEPENDENCIES = m68kmake_LDFLAGS = COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(libmusa68_a_SOURCES) $(EXTRA_libmusa68_a_SOURCES) $(m68kmake_SOURCES) OBJECTS = $(libmusa68_a_OBJECTS) $(m68kmake_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps musa/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status mostlyclean-noinstLIBRARIES: clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: libmusa68.a: $(libmusa68_a_OBJECTS) $(libmusa68_a_DEPENDENCIES) -rm -f libmusa68.a $(AR) cru libmusa68.a $(libmusa68_a_OBJECTS) $(libmusa68_a_LIBADD) $(RANLIB) libmusa68.a mostlyclean-noinstPROGRAMS: clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) distclean-noinstPROGRAMS: maintainer-clean-noinstPROGRAMS: m68kmake: $(m68kmake_OBJECTS) $(m68kmake_DEPENDENCIES) @rm -f m68kmake $(LINK) $(m68kmake_LDFLAGS) $(m68kmake_OBJECTS) $(m68kmake_LDADD) $(LIBS) tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = musa distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done m68kmake.o: m68kmake.c info-am: info: info-am dvi-am: dvi: dvi-am check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am install-exec-am: install-exec: install-exec-am install-data-am: install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am uninstall-am: uninstall: uninstall-am all-am: Makefile $(LIBRARIES) $(PROGRAMS) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ mostlyclean-noinstPROGRAMS mostlyclean-tags \ mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-noinstLIBRARIES clean-compile clean-noinstPROGRAMS \ clean-tags clean-generic mostlyclean-am clean: clean-am distclean-am: distclean-noinstLIBRARIES distclean-compile \ distclean-noinstPROGRAMS distclean-tags \ distclean-generic clean-am distclean: distclean-am maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean-compile \ maintainer-clean-noinstPROGRAMS maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-am .PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile mostlyclean-noinstPROGRAMS \ distclean-noinstPROGRAMS clean-noinstPROGRAMS \ maintainer-clean-noinstPROGRAMS tags mostlyclean-tags distclean-tags \ clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ check-am installcheck-am installcheck install-exec-am install-exec \ install-data-am install-data install-am install uninstall-am uninstall \ all-redirect all-am all installdirs mostlyclean-generic \ distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean distclean maintainer-clean m68kops.c: m68kmake ./m68kmake m68kopac.c: m68kmake ./m68kmake m68kopdm.c: m68kmake ./m68kmake m68kopnz.c: m68kmake ./m68kmake m68kops.h: m68kmake ./m68kmake # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: dgen-sdl-1.23/musa/Makefile.am 644 1750 1750 1326 7044434136 11265 # DGen/SDL v1.20+ # Automakefile for Musashi # hack it so that musa doesn't get affected by memcpy defines CFLAGS = @CFLAGS@ -Umemcpy noinst_PROGRAMS = m68kmake noinst_LIBRARIES = libmusa68.a m68kmake_SOURCES = m68kmake.c m68kops.c: m68kmake ./m68kmake m68kopac.c: m68kmake ./m68kmake m68kopdm.c: m68kmake ./m68kmake m68kopnz.c: m68kmake ./m68kmake m68kops.h: m68kmake ./m68kmake EXTRA_libmusa68_a_SOURCES = m68k_in.c m68kmake.c m68kops.h libmusa68_a_SOURCES = m68kcpu.c m68kcpu.h m68k.h m68kconf.h libmusa68_a_LIBADD = m68kops.o m68kopac.o m68kopdm.o m68kopnz.o libmusa68_a_DEPENDENCIES = m68kmake m68kops.o m68kopac.o m68kopdm.o m68kopnz.o DISTCLEANFILES = m68kops.c m68kopac.c m68kopdm.c m68kopnz.c m68kmake dgen-sdl-1.23/musa/m68kcpu.c 644 1750 1750 63523 7044427651 10725 /* ======================================================================== */ /* ========================= LICENSING & COPYRIGHT ======================== */ /* ======================================================================== */ static const char* copyright_notice = "MUSASHI\n" "Version 2.0a (1999-02-21)\n" "A portable Motorola M680x0 processor emulation engine.\n" "Copyright 1999 Karl Stenerud. All rights reserved.\n" "\n" "This code may be freely used for non-commercial purpooses as long as this\n" "copyright notice remains unaltered in the source code and any binary files\n" "containing this code in compiled form.\n" "\n" "Any commercial ventures wishing to use this code must contact the author\n" "(Karl Stenerud) to negotiate commercial licensing terms.\n" "\n" "The latest version of this code can be obtained at:\n" "http://milliways.scas.bcit.bc.ca/~karl/musashi\n" ; /* ======================================================================== */ /* ================================= NOTES ================================ */ /* ======================================================================== */ /* ======================================================================== */ /* ================================ INCLUDES ============================== */ /* ======================================================================== */ #include #include #include #include "m68kcpu.h" #include "m68kops.h" /* ======================================================================== */ /* =============================== PROTOTYPES ============================= */ /* ======================================================================== */ /* Build the opcode handler table */ void m68ki_build_opcode_table(void); /* ======================================================================== */ /* ================================= DATA ================================= */ /* ======================================================================== */ static uint m68k_emulation_initialized = 0; /* flag if emulation has been initialized */ void (*m68k_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ int m68k_clks_left = 0; /* Number of clocks remaining */ uint m68k_tracing = 0; #ifdef M68K_LOG uint m68k_pc_offset = 2; char* m68k_cpu_names[5] = { "Invalid CPU", "M68000", "M68010", "Invalid CPU", "M68020" }; #endif /* M68K_LOG */ /* Mask which bits of the SR ar eimplemented */ uint m68k_sr_implemented_bits[5] = { 0x0000, /* invalid */ 0xa71f, /* 68000: T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ 0xa71f, /* 68010: T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ 0x0000, /* invalid */ 0xf71f, /* 68020: T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ }; /* The CPU core */ m68k_cpu_core m68k_cpu = {0}; /* Pointers to speed up address register indirect with index calculation */ uint* m68k_cpu_dar[2] = {CPU_D, CPU_A}; /* Pointers to speed up movem instructions */ uint* m68k_movem_pi_table[16] = { CPU_D, CPU_D+1, CPU_D+2, CPU_D+3, CPU_D+4, CPU_D+5, CPU_D+6, CPU_D+7, CPU_A, CPU_A+1, CPU_A+2, CPU_A+3, CPU_A+4, CPU_A+5, CPU_A+6, CPU_A+7 }; uint* m68k_movem_pd_table[16] = { CPU_A+7, CPU_A+6, CPU_A+5, CPU_A+4, CPU_A+3, CPU_A+2, CPU_A+1, CPU_A, CPU_D+7, CPU_D+6, CPU_D+5, CPU_D+4, CPU_D+3, CPU_D+2, CPU_D+1, CPU_D, }; /* Used when checking for pending interrupts */ uint8 m68k_int_masks[] = {0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x80}; /* Used by shift & rotate instructions */ uint8 m68k_shift_8_table[65] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; uint16 m68k_shift_16_table[65] = { 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; uint m68k_shift_32_table[65] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; /* Number of clock cycles to use for exception processing. * I used 4 for any vectors that are undocumented for processing times. */ uint8 m68k_exception_cycle_table[256] = { 40, /* 0: Reset - should never be called */ 40, /* 1: Reset - should never be called */ 50, /* 2: Bus Error (unused in emulation) */ 50, /* 3: Address Error (unused in emulation) */ 34, /* 4: Illegal Instruction */ 38, /* 5: Divide by Zero -- ASG: changed from 42 */ 40, /* 6: CHK -- ASG: chanaged from 44 */ 34, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 34, /* 9: Trace */ 4, /* 10: 1010 */ 4, /* 11: 1111 */ 4, /* 12: RESERVED */ 4, /* 13: Coprocessor Protocol Violation (unused in emulation) */ 4, /* 14: Format Error (unused in emulation) */ 44, /* 15: Uninitialized Interrupt */ 4, /* 16: RESERVED */ 4, /* 17: RESERVED */ 4, /* 18: RESERVED */ 4, /* 19: RESERVED */ 4, /* 20: RESERVED */ 4, /* 21: RESERVED */ 4, /* 22: RESERVED */ 4, /* 23: RESERVED */ 44, /* 24: Spurious Interrupt */ 44, /* 25: Level 1 Interrupt Autovector */ 44, /* 26: Level 2 Interrupt Autovector */ 44, /* 27: Level 3 Interrupt Autovector */ 44, /* 28: Level 4 Interrupt Autovector */ 44, /* 29: Level 5 Interrupt Autovector */ 44, /* 30: Level 6 Interrupt Autovector */ 44, /* 31: Level 7 Interrupt Autovector */ 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */ 34, /* 33: TRAP #1 */ 34, /* 34: TRAP #2 */ 34, /* 35: TRAP #3 */ 34, /* 36: TRAP #4 */ 34, /* 37: TRAP #5 */ 34, /* 38: TRAP #6 */ 34, /* 39: TRAP #7 */ 34, /* 40: TRAP #8 */ 34, /* 41: TRAP #9 */ 34, /* 42: TRAP #10 */ 34, /* 43: TRAP #11 */ 34, /* 44: TRAP #12 */ 34, /* 45: TRAP #13 */ 34, /* 46: TRAP #14 */ 34, /* 47: TRAP #15 */ 4, /* 48: FP Branch or Set on Unknown Condition (unused in emulation) */ 4, /* 49: FP Inexact Result (unused in emulation) */ 4, /* 50: FP Divide by Zero (unused in emulation) */ 4, /* 51: FP Underflow (unused in emulation) */ 4, /* 52: FP Operand Error (unused in emulation) */ 4, /* 53: FP Overflow (unused in emulation) */ 4, /* 54: FP Signaling NAN (unused in emulation) */ 4, /* 55: FP Unimplemented Data Type (unused in emulation) */ 4, /* 56: MMU Configuration Error (unused in emulation) */ 4, /* 57: MMU Illegal Operation Error (unused in emulation) */ 4, /* 58: MMU Access Level Violation Error (unused in emulation) */ 4, /* 59: RESERVED */ 4, /* 60: RESERVED */ 4, /* 61: RESERVED */ 4, /* 62: RESERVED */ 4, /* 63: RESERVED */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 64- 79: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 80- 95: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 96-111: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 112-127: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 128-143: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 144-159: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 160-175: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 176-191: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 192-207: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 208-223: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 224-239: User Defined */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 240-255: User Defined */ }; /* ======================================================================== */ /* =============================== CALLBACKS ============================== */ /* ======================================================================== */ /* Default callbacks used if the callback hasn't been set yet, or if the * callback is set to NULL */ /* Interrupt acknowledge */ static int default_int_ack_callback_data; static int default_int_ack_callback(int int_level) { default_int_ack_callback_data = int_level; return M68K_INT_ACK_AUTOVECTOR; } /* Breakpoint acknowledge */ static int default_bkpt_ack_callback_data; static void default_bkpt_ack_callback(int data) { default_bkpt_ack_callback_data = data; } /* Called when a reset instruction is executed */ static void default_reset_instr_callback(void) { } /* Called when the program counter changed by a large value */ static int default_pc_changed_callback_data; static void default_pc_changed_callback(int new_pc) { default_pc_changed_callback_data = new_pc; } /* Called every time there's bus activity (read/write to/from memory */ static int default_set_fc_callback_data; static void default_set_fc_callback(int new_fc) { default_set_fc_callback_data = new_fc; } /* Called every instruction cycle prior to execution */ static void default_instr_hook_callback(void) { } /* ======================================================================== */ /* ================================= API ================================== */ /* ======================================================================== */ /* Peek at the internals of the M68K */ int m68k_peek_dr(int reg_num) { return (reg_num < 8) ? CPU_D[reg_num] : 0; } int m68k_peek_ar(int reg_num) { return (reg_num < 8) ? CPU_A[reg_num] : 0; } unsigned int m68k_peek_pc(void) { return ADDRESS_68K(CPU_PC); } unsigned int m68k_peek_ppc(void) { return ADDRESS_68K(CPU_PPC); } int m68k_peek_sr(void) { return m68ki_get_sr(); } int m68k_peek_ir(void) { return CPU_IR; } int m68k_peek_t1_flag(void) { return CPU_T1 != 0; } int m68k_peek_t0_flag(void) { return CPU_T0 != 0; } int m68k_peek_s_flag(void) { return CPU_S != 0; } int m68k_peek_m_flag(void) { return CPU_M != 0; } int m68k_peek_int_mask(void) { return CPU_INT_MASK; } int m68k_peek_x_flag(void) { return CPU_X != 0; } int m68k_peek_n_flag(void) { return CPU_N != 0; } int m68k_peek_z_flag(void) { return CPU_NOT_Z == 0; } int m68k_peek_v_flag(void) { return CPU_V != 0; } int m68k_peek_c_flag(void) { return CPU_C != 0; } int m68k_peek_usp(void) { return CPU_S ? CPU_USP : CPU_A[7]; } int m68k_peek_isp(void) { return CPU_S && !CPU_M ? CPU_A[7] : CPU_ISP; } int m68k_peek_msp(void) { return CPU_S && CPU_M ? CPU_A[7] : CPU_MSP; } /* Poke data into the M68K */ void m68k_poke_dr(int reg_num, int value) { if(reg_num < 8) CPU_D[reg_num] = MASK_OUT_ABOVE_32(value); } void m68k_poke_ar(int reg_num, int value) { if(reg_num < 8) CPU_A[reg_num] = MASK_OUT_ABOVE_32(value); } void m68k_poke_pc(unsigned int value) { m68ki_set_pc(ADDRESS_68K(value)); } void m68k_poke_sr(int value) { m68ki_set_sr(MASK_OUT_ABOVE_16(value)); } void m68k_poke_ir(int value) { CPU_IR = MASK_OUT_ABOVE_16(value); } void m68k_poke_t1_flag(int value) { CPU_T1 = (value != 0); } void m68k_poke_t0_flag(int value) { if(CPU_MODE & CPU_MODE_020_PLUS) CPU_T0 = (value != 0); } void m68k_poke_s_flag(int value) { m68ki_set_s_flag(value); } void m68k_poke_m_flag(int value) { if(CPU_MODE & CPU_MODE_020_PLUS) m68ki_set_m_flag(value); } void m68k_poke_int_mask(int value) { CPU_INT_MASK = value & 7; } void m68k_poke_x_flag(int value) { CPU_X = (value != 0); } void m68k_poke_n_flag(int value) { CPU_N = (value != 0); } void m68k_poke_z_flag(int value) { CPU_NOT_Z = (value == 0); } void m68k_poke_v_flag(int value) { CPU_V = (value != 0); } void m68k_poke_c_flag(int value) { CPU_C = (value != 0); } void m68k_poke_usp(int value) { if(CPU_S) CPU_USP = MASK_OUT_ABOVE_32(value); else CPU_A[7] = MASK_OUT_ABOVE_32(value); } void m68k_poke_isp(int value) { if(CPU_S && !CPU_M) CPU_A[7] = MASK_OUT_ABOVE_32(value); else CPU_ISP = MASK_OUT_ABOVE_32(value); } void m68k_poke_msp(int value) { if(CPU_MODE & CPU_MODE_020_PLUS) { if(CPU_S && CPU_M) CPU_A[7] = MASK_OUT_ABOVE_32(value); else CPU_MSP = MASK_OUT_ABOVE_32(value); } } /* Set the callbacks */ void m68k_set_int_ack_callback(int (*callback)(int int_level)) { CPU_INT_ACK_CALLBACK = callback ? callback : default_int_ack_callback; } void m68k_set_bkpt_ack_callback(void (*callback)(int data)) { CPU_BKPT_ACK_CALLBACK = callback ? callback : default_bkpt_ack_callback; } void m68k_set_reset_instr_callback(void (*callback)(void)) { CPU_RESET_INSTR_CALLBACK = callback ? callback : default_reset_instr_callback; } void m68k_set_pc_changed_callback(void (*callback)(int new_pc)) { CPU_PC_CHANGED_CALLBACK = callback ? callback : default_pc_changed_callback; } void m68k_set_fc_callback(void (*callback)(int new_fc)) { CPU_SET_FC_CALLBACK = callback ? callback : default_set_fc_callback; } void m68k_set_instr_hook_callback(void (*callback)(void)) { CPU_INSTR_HOOK_CALLBACK = callback ? callback : default_instr_hook_callback; } void m68k_set_cpu_mode(int cpu_mode) { switch(cpu_mode) { case M68K_CPU_MODE_68000: case M68K_CPU_MODE_68010: case M68K_CPU_MODE_68020: CPU_MODE = cpu_mode; return; default: CPU_MODE = M68K_DEFAULT_CPU_MODE; } } /* Execute some instructions until we use up num_clks clock cycles */ /* ASG: removed per-instruction interrupt checks */ int m68k_execute(int num_clks) { #if M68K_HALT if(!CPU_HALTED) { #endif /* M68K_HALT */ /* Make sure we're not stopped */ if(!CPU_STOPPED) { /* Set our pool of clock cycles available */ m68k_clks_left = num_clks; /* ASG: update cycles */ m68k_clks_left -= CPU_INT_CYCLES; CPU_INT_CYCLES = 0; /* Main loop. Keep going until we run out of clock cycles */ do { /* Set tracing accodring to T1. (T0 is done inside instruction) */ m68ki_set_trace(); /* auto-disable (see m68kcpu.h) */ /* Call external hook to peek at CPU */ m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */ /* MAME */ /* CPU_PPC = CPU_PC; CALL_MAME_DEBUG; #if A68000_COREDEBUG Asgard68000MiniTrace(&CPU_D[0], &CPU_A[0], m68k_peek_pc(), m68k_peek_sr(), m68k_clks_left); #endif */ /* MAME */ /* Read an instruction and call its handler */ CPU_IR = m68ki_read_instruction(); m68k_instruction_jump_table[CPU_IR](); /* Trace m68k_exception, if necessary */ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ continue; } while(m68k_clks_left > 0); /* set previous PC to current PC for the next entry into the loop */ CPU_PPC = CPU_PC; /* ASG: update cycles */ m68k_clks_left -= CPU_INT_CYCLES; CPU_INT_CYCLES = 0; #if A68000_COREDEBUG Asgard68000MiniTrace(&CPU_D[0], &CPU_A[0], m68k_peek_pc(), m68k_peek_sr(), m68k_clks_left); #endif /* return how many clocks we used */ return num_clks - m68k_clks_left; } #if M68K_HALT } #endif /* M68K_HALT */ /* We get here if the CPU is stopped */ m68k_clks_left = 0; #if A68000_COREDEBUG Asgard68000MiniTrace(&CPU_D[0], &CPU_A[0], m68k_peek_pc(), m68k_peek_sr(), m68k_clks_left); #endif return num_clks; } /* ASG: rewrote so that the int_line is a mask of the IPL0/IPL1/IPL2 bits */ void m68k_assert_irq(int int_line) { /* OR in the bits of the interrupt */ int old_state = CPU_INT_STATE; CPU_INT_STATE = 0; /* ASG: remove me to do proper mask setting */ CPU_INT_STATE |= int_line & 7; /* if it's NMI, we're edge triggered */ if (CPU_INT_STATE == 7) { if (old_state != 7) m68ki_service_interrupt(1 << 7); } /* other interrupts just reflect the current state */ else m68ki_check_interrupts(); } /* ASG: rewrote so that the int_line is a mask of the IPL0/IPL1/IPL2 bits */ void m68k_clear_irq(int int_line) { /* AND in the bits of the interrupt */ CPU_INT_STATE &= ~int_line & 7; CPU_INT_STATE = 0; /* ASG: remove me to do proper mask setting */ /* check for interrupts again */ m68ki_check_interrupts(); } /* Reset the M68K */ void m68k_pulse_reset(void *param) { CPU_HALTED = 0; CPU_STOPPED = 0; CPU_INT_STATE = 0; /* ASG: changed from CPU_INTS_PENDING */ CPU_T1 = CPU_T0 = 0; m68ki_clear_trace(); CPU_S = 1; CPU_M = 0; CPU_INT_MASK = 7; /* ASG: removed a bunch of this initialization.... CPU_X = CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 1; CPU_USP = 0; CPU_MSP = 0; CPU_IR = 0; CPU_D[0] = CPU_D[1] = CPU_D[2] = CPU_D[3] = CPU_D[4] = CPU_D[5] = CPU_D[6] = CPU_D[7] = CPU_A[0] = CPU_A[1] = CPU_A[2] = CPU_A[3] = CPU_A[4] = CPU_A[5] = CPU_A[6] = CPU_A[7] = 0;*/ CPU_VBR = 0; /* CPU_SFC = 0; CPU_DFC = 0;*/ CPU_A[7] = /*CPU_ISP =*/ m68ki_read_32(0); m68ki_set_pc(m68ki_read_32(4)); m68k_clks_left = 0; if (CPU_MODE == 0) CPU_MODE = M68K_DEFAULT_CPU_MODE; /* KW 990319 */ /* The first call to this function initializes the opcode handler jump table */ if(m68k_emulation_initialized) return; else { m68ki_build_opcode_table(); /* if(CPU_MODE == 0) CPU_MODE = M68K_DEFAULT_CPU_MODE;*/ m68k_set_int_ack_callback(NULL); m68k_set_bkpt_ack_callback(NULL); m68k_set_reset_instr_callback(NULL); m68k_set_pc_changed_callback(NULL); m68k_set_fc_callback(NULL); m68k_set_instr_hook_callback(NULL); m68k_emulation_initialized = 1; } } /* Halt the CPU */ void m68k_pulse_halt(void) { CPU_HALTED = 1; } /* Get and set the current CPU context */ /* This is to allow for multiple CPUs */ unsigned m68k_get_context(void* dst) { if( dst ) { m68k_cpu_context *cpu = dst; cpu->mode = CPU_MODE; cpu->sr = m68ki_get_sr(); cpu->pc = CPU_PC; memcpy(cpu->d, CPU_D, sizeof(CPU_D)); memcpy(cpu->a, CPU_A, sizeof(CPU_A)); cpu->usp = CPU_USP; cpu->isp = CPU_ISP; cpu->msp = CPU_MSP; cpu->vbr = CPU_VBR; cpu->sfc = CPU_SFC; cpu->dfc = CPU_DFC; cpu->stopped = CPU_STOPPED; cpu->halted = CPU_HALTED; cpu->int_state = CPU_INT_STATE; /* ASG: changed from CPU_INTS_PENDING */ cpu->int_cycles = CPU_INT_CYCLES; /* ASG */ cpu->int_ack_callback = CPU_INT_ACK_CALLBACK; cpu->bkpt_ack_callback = CPU_BKPT_ACK_CALLBACK; cpu->reset_instr_callback = CPU_RESET_INSTR_CALLBACK; cpu->pc_changed_callback = CPU_PC_CHANGED_CALLBACK; cpu->set_fc_callback = CPU_SET_FC_CALLBACK; cpu->instr_hook_callback = CPU_INSTR_HOOK_CALLBACK; } return sizeof(m68k_cpu_context); } void m68k_set_context(void* src) { if( src ) { m68k_cpu_context *cpu = src; CPU_MODE = cpu->mode; m68ki_set_sr_no_int(cpu->sr); /* This stays on top to prevent side-effects */ m68ki_set_pc(cpu->pc); memcpy(CPU_D, cpu->d, sizeof(CPU_D)); memcpy(CPU_A, cpu->a, sizeof(CPU_D)); CPU_USP = cpu->usp; CPU_ISP = cpu->isp; CPU_MSP = cpu->msp; CPU_VBR = cpu->vbr; CPU_SFC = cpu->sfc; CPU_DFC = cpu->dfc; CPU_STOPPED = cpu->stopped; CPU_HALTED = cpu->halted; CPU_INT_STATE = cpu->int_state; /* ASG: changed from CPU_INTS_PENDING */ CPU_INT_CYCLES = cpu->int_cycles; /* ASG */ CPU_INT_ACK_CALLBACK = cpu->int_ack_callback; CPU_BKPT_ACK_CALLBACK = cpu->bkpt_ack_callback; CPU_RESET_INSTR_CALLBACK = cpu->reset_instr_callback; CPU_PC_CHANGED_CALLBACK = cpu->pc_changed_callback; CPU_SET_FC_CALLBACK = cpu->set_fc_callback; CPU_INSTR_HOOK_CALLBACK = cpu->instr_hook_callback; /* ASG: check for interrupts */ m68ki_check_interrupts(); } } /* Check if the instruction is a valid one */ int m68k_is_valid_instruction(int instruction, int cpu_mode) { if(m68k_instruction_jump_table[MASK_OUT_ABOVE_16(instruction)] == m68000_illegal) return 0; if(!(cpu_mode & CPU_MODE_010_PLUS)) { if((instruction & 0xfff8) == 0x4848) /* bkpt */ return 0; if((instruction & 0xffc0) == 0x42c0) /* move from ccr */ return 0; if((instruction & 0xfffe) == 0x4e7a) /* movec */ return 0; if((instruction & 0xff00) == 0x0e00) /* moves */ return 0; if((instruction & 0xffff) == 0x4e74) /* rtd */ return 0; } if(!(cpu_mode & CPU_MODE_020_PLUS)) { if((instruction & 0xf0ff) == 0x60ff) /* bcc.l */ return 0; if((instruction & 0xf8c0) == 0xe8c0) /* bfxxx */ return 0; if((instruction & 0xffc0) == 0x06c0) /* callm */ return 0; if((instruction & 0xf9c0) == 0x08c0) /* cas */ return 0; if((instruction & 0xf9ff) == 0x08fc) /* cas2 */ return 0; if((instruction & 0xf1c0) == 0x4100) /* chk.l */ return 0; if((instruction & 0xf9c0) == 0x00c0) /* chk2, cmp2 */ return 0; if((instruction & 0xff3f) == 0x0c3a) /* cmpi (pcdi) */ return 0; if((instruction & 0xff3f) == 0x0c3b) /* cmpi (pcix) */ return 0; if((instruction & 0xffc0) == 0x4c40) /* divl */ return 0; if((instruction & 0xfff8) == 0x49c0) /* extb */ return 0; if((instruction & 0xfff8) == 0x4808) /* link.l */ return 0; if((instruction & 0xffc0) == 0x4c00) /* mull */ return 0; if((instruction & 0xf1f0) == 0x8140) /* pack */ return 0; if((instruction & 0xfff0) == 0x06c0) /* rtm */ return 0; if((instruction & 0xf0f8) == 0x50f8) /* trapcc */ return 0; if((instruction & 0xff38) == 0x4a08) /* tst (a) */ return 0; if((instruction & 0xff3f) == 0x4a3a) /* tst (pcdi) */ return 0; if((instruction & 0xff3f) == 0x4a3b) /* tst (pcix) */ return 0; if((instruction & 0xff3f) == 0x4a3c) /* tst (imm) */ return 0; if((instruction & 0xf1f0) == 0x8180) /* unpk */ return 0; } return 1; } /* ======================================================================== */ /* ============================== END OF FILE ============================= */ /* ======================================================================== */ dgen-sdl-1.23/musa/m68kcpu.h 644 1750 1750 115450 7027317557 10753 #ifndef M68KCPU__HEADER #define M68KCPU__HEADER #include "m68k.h" #include /* ======================================================================== */ /* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ /* ======================================================================== */ /* Check if we have certain storage sizes */ #if UCHAR_MAX == 0xff #define M68K_HAS_8_BIT_SIZE 1 #else #define M68K_HAS_8_BIT_SIZE 0 #endif /* UCHAR_MAX == 0xff */ #if USHRT_MAX == 0xffff #define M68K_HAS_16_BIT_SIZE 1 #else #define M68K_HAS_16_BIT_SIZE 0 #endif /* USHRT_MAX == 0xffff */ #if ULONG_MAX == 0xffffffff #define M68K_HAS_32_BIT_SIZE 1 #else #define M68K_HAS_32_BIT_SIZE 0 #endif /* ULONG_MAX == 0xffffffff */ #if UINT_MAX > 0xffffffff #define M68K_OVER_32_BIT 1 #else #define M68K_OVER_32_BIT 0 #endif /* UINT_MAX > 0xffffffff */ /* Data types used in this emulation core */ #undef int8 #undef int16 #undef int32 #undef uint #undef uint8 #undef uint16 #undef uint #define int8 signed char /* ASG: changed from char to signed char */ #define uint8 unsigned char #define int16 short #define uint16 unsigned short #define int32 long /* int and unsigned int must be at least 32 bits wide */ #define uint unsigned int /* Allow for architectures that don't have 8-bit sizes */ #if M68K_HAS_8_BIT_SIZE #define MAKE_INT_8(A) (int8)((A)&0xff) #else #undef int8 #define int8 int #undef uint8 #define uint8 unsigned int INLINE int MAKE_INT_8(int value) { /* Will this work for 1's complement machines? */ return (value & 0x80) ? value | ~0xff : value & 0xff; } #endif /* M68K_HAS_8_BIT_SIZE */ /* Allow for architectures that don't have 16-bit sizes */ #if M68K_HAS_16_BIT_SIZE #define MAKE_INT_16(A) (int16)((A)&0xffff) #else #undef int16 #define int16 int #undef uint16 #define uint16 unsigned int INLINE int MAKE_INT_16(int value) { /* Will this work for 1's complement machines? */ return (value & 0x8000) ? value | ~0xffff : value & 0xffff; } #endif /* M68K_HAS_16_BIT_SIZE */ /* Allow for architectures that don't have 32-bit sizes */ #if M68K_HAS_32_BIT_SIZE #if M68K_OVER_32_BIT #define MAKE_INT_32(A) (int32)((A)&0xffffffff) #else #define MAKE_INT_32(A) (int32)(A) #endif /* M68K_OVER_32_BIT */ #else #undef int32 #define int32 int INLINE int MAKE_INT_32(int value) { /* Will this work for 1's complement machines? */ return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; } #endif /* M68K_HAS_32_BIT_SIZE */ /* ======================================================================== */ /* ============================ GENERAL DEFINES =========================== */ /* ======================================================================== */ /* Exception Vectors handled by emulation */ #define EXCEPTION_ILLEGAL_INSTRUCTION 4 #define EXCEPTION_ZERO_DIVIDE 5 #define EXCEPTION_CHK 6 #define EXCEPTION_TRAPV 7 #define EXCEPTION_PRIVILEGE_VIOLATION 8 #define EXCEPTION_TRACE 9 #define EXCEPTION_1010 10 #define EXCEPTION_1111 11 #define EXCEPTION_FORMAT_ERROR 14 #define EXCEPTION_UNINITIALIZED_INTERRUPT 15 #define EXCEPTION_SPURIOUS_INTERRUPT 24 #define EXCEPTION_INTERRUPT_AUTOVECTOR 24 #define EXCEPTION_TRAP_BASE 32 /* Function codes set by CPU during data/address bus activity */ #define FUNCTION_CODE_USER_DATA 1 #define FUNCTION_CODE_USER_PROGRAM 2 #define FUNCTION_CODE_SUPERVISOR_DATA 5 #define FUNCTION_CODE_SUPERVISOR_PROGRAM 6 #define FUNCTION_CODE_CPU_SPACE 7 /* CPU modes for deciding what to emulate */ #define CPU_MODE_000 M68K_CPU_MODE_68000 #define CPU_MODE_010 M68K_CPU_MODE_68010 #define CPU_MODE_020 M68K_CPU_MODE_68020 #define CPU_MODE_ALL (CPU_MODE_000 | CPU_MODE_010 | CPU_MODE_020) #define CPU_MODE_010_PLUS (CPU_MODE_010 | CPU_MODE_020) #define CPU_MODE_010_LESS (CPU_MODE_000 | CPU_MODE_010) #define CPU_MODE_020_PLUS CPU_MODE_020 #define CPU_MODE_020_LESS (CPU_MODE_000 | CPU_MODE_010 | CPU_MODE_020) /* ======================================================================== */ /* ================================ MACROS ================================ */ /* ======================================================================== */ /* Bit Isolation Macros */ #define BIT_0(A) ((A) & 0x00000001) #define BIT_1(A) ((A) & 0x00000002) #define BIT_2(A) ((A) & 0x00000004) #define BIT_3(A) ((A) & 0x00000008) #define BIT_4(A) ((A) & 0x00000010) #define BIT_5(A) ((A) & 0x00000020) #define BIT_6(A) ((A) & 0x00000040) #define BIT_7(A) ((A) & 0x00000080) #define BIT_8(A) ((A) & 0x00000100) #define BIT_9(A) ((A) & 0x00000200) #define BIT_A(A) ((A) & 0x00000400) #define BIT_B(A) ((A) & 0x00000800) #define BIT_C(A) ((A) & 0x00001000) #define BIT_D(A) ((A) & 0x00002000) #define BIT_E(A) ((A) & 0x00004000) #define BIT_F(A) ((A) & 0x00008000) #define BIT_10(A) ((A) & 0x00010000) #define BIT_11(A) ((A) & 0x00020000) #define BIT_12(A) ((A) & 0x00040000) #define BIT_13(A) ((A) & 0x00080000) #define BIT_14(A) ((A) & 0x00100000) #define BIT_15(A) ((A) & 0x00200000) #define BIT_16(A) ((A) & 0x00400000) #define BIT_17(A) ((A) & 0x00800000) #define BIT_18(A) ((A) & 0x01000000) #define BIT_19(A) ((A) & 0x02000000) #define BIT_1A(A) ((A) & 0x04000000) #define BIT_1B(A) ((A) & 0x08000000) #define BIT_1C(A) ((A) & 0x10000000) #define BIT_1D(A) ((A) & 0x20000000) #define BIT_1E(A) ((A) & 0x40000000) #define BIT_1F(A) ((A) & 0x80000000) /* Get the most significant bit for specific sizes */ #define GET_MSB_8(A) ((A) & 0x80) #define GET_MSB_9(A) ((A) & 0x100) #define GET_MSB_16(A) ((A) & 0x8000) #define GET_MSB_17(A) ((A) & 0x10000) #define GET_MSB_32(A) ((A) & 0x80000000) /* Isolate nibbles */ #define LOW_NIBBLE(A) ((A) & 0x0f) #define HIGH_NIBBLE(A) ((A) & 0xf0) /* These are used to isolate 8, 16, and 32 bit sizes */ #define MASK_OUT_ABOVE_8(A) ((A) & 0xff) #define MASK_OUT_ABOVE_16(A) ((A) & 0xffff) #define MASK_OUT_BELOW_8(A) ((A) & ~0xff) #define MASK_OUT_BELOW_16(A) ((A) & ~0xffff) /* No need for useless masking if we're 32-bit */ #if M68K_OVER_32_BIT #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff) #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff) #else #define MASK_OUT_ABOVE_32(A) (A) #define MASK_OUT_BELOW_32(A) 0 #endif /* M68K_OVER_32_BIT */ /* Simulate address lines of 68k family */ #define ADDRESS_68K(A) (CPU_MODE & CPU_MODE_020_PLUS ? A : (A)&0xffffff) /* Instruction extension word information for indexed addressing modes */ #define EXT_INDEX_LONG(A) BIT_B(A) #define EXT_INDEX_AR(A) BIT_F(A) #define EXT_INDEX_REGISTER(A) (((A)>>12)&7) #define EXT_INDEX_SCALE(A) (((A)>>9)&3) #define EXT_BRIEF_FORMAT(A) !BIT_8(A) #define EXT_IX_SUPPRESSED(A) BIT_6(A) #define EXT_BR_SUPPRESSED(A) BIT_7(A) #define EXT_BD_PRESENT(A) BIT_5(A) #define EXT_BD_LONG(A) BIT_4(A) #define EXT_NO_MEMORY_INDIRECT(A) !((A)&7) #define EXT_OD_PRESENT(A) BIT_1(A) #define EXT_OD_LONG(A) BIT_0(A) #define EXT_POSTINDEX(A) BIT_2(A) /* Shift & Rotate Macros. * 32-bit shifts defined in architecture-dependant section. */ #define LSL(A, C) ((A) << (C)) #define LSR(A, C) ((A) >> (C)) /* Some > 32-bit optimizations */ #if M68K_OVER_32_BIT /* Shift left and right */ #define LSR_32(A, C) ((A) >> (C)) #define LSL_32(A, C) ((A) << (C)) #else /* We have to do this because the morons at ANSI decided that shifts * by >= data size are undefined. */ #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) #endif /* M68K_OVER_32_BIT */ #define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C))) #define ROL_9(A, C) LSL(A, C) | LSR(A, 9-(C)) #define ROL_16(A, C) MASK_OUT_ABOVE_16(LSL(A, C) | LSR(A, 16-(C))) #define ROL_17(A, C) LSL(A, C) | LSR(A, 17-(C)) #define ROL_32(A, C) MASK_OUT_ABOVE_32(LSL_32(A, C) | LSR_32(A, 32-(C))) #define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C))) #define ROR_8(A, C) MASK_OUT_ABOVE_8(LSR(A, C) | LSL(A, 8-(C))) #define ROR_9(A, C) LSR(A, C) | LSL(A, 9-(C)) #define ROR_16(A, C) MASK_OUT_ABOVE_16(LSR(A, C) | LSL(A, 16-(C))) #define ROR_17(A, C) LSR(A, C) | LSL(A, 17-(C)) #define ROR_32(A, C) MASK_OUT_ABOVE_32(LSR_32(A, C) | LSL_32(A, 32-(C))) #define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C))) /* Access the CPU registers */ #define CPU_MODE m68k_cpu.mode #define CPU_D m68k_cpu.dr #define CPU_A m68k_cpu.ar #define CPU_PPC m68k_cpu.ppc #define CPU_PC m68k_cpu.pc #define CPU_SP m68k_cpu.sp #define CPU_USP m68k_cpu.sp[0] #define CPU_ISP m68k_cpu.sp[1] #define CPU_MSP m68k_cpu.sp[3] #define CPU_VBR m68k_cpu.vbr #define CPU_SFC m68k_cpu.sfc #define CPU_DFC m68k_cpu.dfc #define CPU_IR m68k_cpu.ir #define CPU_T1 m68k_cpu.t1_flag #define CPU_T0 m68k_cpu.t0_flag #define CPU_S m68k_cpu.s_flag #define CPU_M m68k_cpu.m_flag #define CPU_X m68k_cpu.x_flag #define CPU_N m68k_cpu.n_flag #define CPU_NOT_Z m68k_cpu.not_z_flag #define CPU_V m68k_cpu.v_flag #define CPU_C m68k_cpu.c_flag #define CPU_INT_MASK m68k_cpu.int_mask #define CPU_INT_STATE m68k_cpu.int_state /* ASG: changed from CPU_INTS_PENDING */ #define CPU_STOPPED m68k_cpu.stopped #define CPU_HALTED m68k_cpu.halted #define CPU_INT_CYCLES m68k_cpu.int_cycles /* ASG */ #define CPU_INT_ACK_CALLBACK m68k_cpu.int_ack_callback #define CPU_BKPT_ACK_CALLBACK m68k_cpu.bkpt_ack_callback #define CPU_RESET_INSTR_CALLBACK m68k_cpu.reset_instr_callback #define CPU_PC_CHANGED_CALLBACK m68k_cpu.pc_changed_callback #define CPU_SET_FC_CALLBACK m68k_cpu.set_fc_callback #define CPU_INSTR_HOOK_CALLBACK m68k_cpu.instr_hook_callback /* * The general instruction format follows this pattern: * .... XXX. .... .YYY * where XXX is register X and YYY is register Y */ /* Data Register Isolation */ #define DX (CPU_D[(CPU_IR >> 9) & 7]) #define DY (CPU_D[CPU_IR & 7]) /* Address Register Isolation */ #define AX (CPU_A[(CPU_IR >> 9) & 7]) #define AY (CPU_A[CPU_IR & 7]) /* Effective Address Calculations */ #define EA_AI AY /* address register indirect */ #define EA_PI_8 (AY++) /* postincrement (size = byte) */ #define EA_PI7_8 ((CPU_A[7]+=2)-2) /* postincrement (size = byte & AR = 7) */ #define EA_PI_16 ((AY+=2)-2) /* postincrement (size = word) */ #define EA_PI_32 ((AY+=4)-4) /* postincrement (size = long) */ #define EA_PD_8 (--AY) /* predecrement (size = byte) */ #define EA_PD7_8 (CPU_A[7]-=2) /* predecrement (size = byte & AR = 7) */ #define EA_PD_16 (AY-=2) /* predecrement (size = word) */ #define EA_PD_32 (AY-=4) /* predecrement (size = long) */ #define EA_DI (AY+MAKE_INT_16(m68ki_read_imm_16())) /* displacement */ #define EA_IX m68ki_get_ea_ix() /* indirect + index */ #define EA_AW MAKE_INT_16(m68ki_read_imm_16()) /* absolute word */ #define EA_AL m68ki_read_imm_32() /* absolute long */ #define EA_PCIX m68ki_get_ea_pcix() /* pc indirect + index */ /* Add and Subtract Flag Calculation Macros */ #define VFLAG_ADD_8(S, D, R) GET_MSB_8((S & D & ~R) | (~S & ~D & R)) #define VFLAG_ADD_16(S, D, R) GET_MSB_16((S & D & ~R) | (~S & ~D & R)) #define VFLAG_ADD_32(S, D, R) GET_MSB_32((S & D & ~R) | (~S & ~D & R)) #define CFLAG_ADD_8(S, D, R) GET_MSB_8((S & D) | (~R & D) | (S & ~R)) #define CFLAG_ADD_16(S, D, R) GET_MSB_16((S & D) | (~R & D) | (S & ~R)) #define CFLAG_ADD_32(S, D, R) GET_MSB_32((S & D) | (~R & D) | (S & ~R)) #define VFLAG_SUB_8(S, D, R) GET_MSB_8((~S & D & ~R) | (S & ~D & R)) #define VFLAG_SUB_16(S, D, R) GET_MSB_16((~S & D & ~R) | (S & ~D & R)) #define VFLAG_SUB_32(S, D, R) GET_MSB_32((~S & D & ~R) | (S & ~D & R)) #define CFLAG_SUB_8(S, D, R) GET_MSB_8((S & ~D) | (R & ~D) | (S & R)) #define CFLAG_SUB_16(S, D, R) GET_MSB_16((S & ~D) | (R & ~D) | (S & R)) #define CFLAG_SUB_32(S, D, R) GET_MSB_32((S & ~D) | (R & ~D) | (S & R)) /* Conditions */ #define CONDITION_HI (CPU_C == 0 && CPU_NOT_Z != 0) #define CONDITION_NOT_HI (CPU_C != 0 || CPU_NOT_Z == 0) #define CONDITION_LS (CPU_C != 0 || CPU_NOT_Z == 0) #define CONDITION_NOT_LS (CPU_C == 0 && CPU_NOT_Z != 0) #define CONDITION_CC (CPU_C == 0) #define CONDITION_NOT_CC (CPU_C != 0) #define CONDITION_CS (CPU_C != 0) #define CONDITION_NOT_CS (CPU_C == 0) #define CONDITION_NE (CPU_NOT_Z != 0) #define CONDITION_NOT_NE (CPU_NOT_Z == 0) #define CONDITION_EQ (CPU_NOT_Z == 0) #define CONDITION_NOT_EQ (CPU_NOT_Z != 0) #define CONDITION_VC (CPU_V == 0) #define CONDITION_NOT_VC (CPU_V != 0) #define CONDITION_VS (CPU_V != 0) #define CONDITION_NOT_VS (CPU_V == 0) #define CONDITION_PL (CPU_N == 0) #define CONDITION_NOT_PL (CPU_N != 0) #define CONDITION_MI (CPU_N != 0) #define CONDITION_NOT_MI (CPU_N == 0) #define CONDITION_GE ((CPU_N == 0) == (CPU_V == 0)) #define CONDITION_NOT_GE ((CPU_N == 0) != (CPU_V == 0)) #define CONDITION_LT ((CPU_N == 0) != (CPU_V == 0)) #define CONDITION_NOT_LT ((CPU_N == 0) == (CPU_V == 0)) #define CONDITION_GT (CPU_NOT_Z != 0 && (CPU_N == 0) == (CPU_V == 0)) #define CONDITION_NOT_GT (CPU_NOT_Z == 0 || (CPU_N == 0) != (CPU_V == 0)) #define CONDITION_LE (CPU_NOT_Z == 0 || (CPU_N == 0) != (CPU_V == 0)) #define CONDITION_NOT_LE (CPU_NOT_Z != 0 && (CPU_N == 0) == (CPU_V == 0)) /* Use up clock cycles. * NOTE: clock cycles used in here are 99.9% correct for a 68000, not for the * higher processors. */ #define USE_CLKS(A) m68k_clks_left -= (A) /* Push/pull data to/from the stack */ #define m68ki_push_16(A) m68ki_write_16(CPU_A[7]-=2, A) #define m68ki_push_32(A) m68ki_write_32(CPU_A[7]-=4, A) #define m68ki_pull_16() m68ki_read_16((CPU_A[7]+=2) - 2) #define m68ki_pull_32() m68ki_read_32((CPU_A[7]+=4) - 4) /* branch byte and word are for branches, while long is for jumps. * So far it's been safe to not call set_pc() for branch word. */ #define m68ki_branch_byte(A) CPU_PC += MAKE_INT_8(A) #define m68ki_branch_word(A) CPU_PC += MAKE_INT_16(A) #define m68ki_branch_long(A) m68ki_set_pc(A) /* Get the condition code register */ #define m68ki_get_ccr() (((CPU_X != 0) << 4) | \ ((CPU_N != 0) << 3) | \ ((CPU_NOT_Z == 0) << 2) | \ ((CPU_V != 0) << 1) | \ (CPU_C != 0)) /* Get the status register */ #define m68ki_get_sr() (((CPU_T1 != 0) << 15) | \ ((CPU_T0 != 0) << 14) | \ ((CPU_S != 0) << 13) | \ ((CPU_M != 0) << 12) | \ (CPU_INT_MASK << 8) | \ ((CPU_X != 0) << 4) | \ ((CPU_N != 0) << 3) | \ ((CPU_NOT_Z == 0) << 2) | \ ((CPU_V != 0) << 1) | \ (CPU_C != 0)) /* ======================================================================== */ /* ========================= CONFIGURATION DEFINES ======================== */ /* ======================================================================== */ /* Act on values in m68kconf.h */ #if M68K_INT_ACK #define m68ki_int_ack(A) CPU_INT_ACK_CALLBACK(A) #else /* Default action is to used autovector mode, which is most common */ #define m68ki_int_ack(A) M68K_INT_ACK_AUTOVECTOR #endif /* M68K_INT_ACK */ #if M68K_BKPT_ACK #define m68ki_bkpt_ack(A) CPU_BKPT_ACK_CALLBACK(A) #else #define m68ki_bkpt_ack(A) #endif /* M68K_BKPT_ACK */ #if M68K_OUTPUT_RESET #define m68ki_output_reset() CPU_RESET_INSTR_CALLBACK() #else #define m68ki_output_reset() #endif /* M68K_OUTPUT_RESET */ #if M68K_PC_CHANGED #define m68ki_pc_changed(A) CPU_PC_CHANGED_CALLBACK(A) #else #define m68ki_pc_changed(A) #endif /* M68K_PC_CHANGED */ #if M68K_SET_FC #define m68ki_set_fc(A) CPU_SET_FC_CALLBACK(A) #else #define m68ki_set_fc(A) #endif /* M68K_SET_FC */ #if M68K_INSTR_HOOK #define m68ki_instr_hook() CPU_INSTR_HOOK_CALLBACK() #else #define m68ki_instr_hook() #endif /* M68K_INSTR_HOOK */ #if M68K_TRACE /* Initiates trace checking before each instruction (t1) */ #define m68ki_set_trace() m68k_tracing = CPU_T1 /* adds t0 to trace checking if we encounter change of flow */ #define m68ki_add_trace() m68k_tracing |= CPU_T0 /* Clear all tracing */ #define m68ki_clear_trace() m68k_tracing = 0 /* Cause a trace exception if we are tracing */ #define m68ki_exception_if_trace() if(m68k_tracing) m68ki_exception(EXCEPTION_TRACE) #else #define m68ki_set_trace() #define m68ki_add_trace() #define m68ki_clear_trace() #define m68ki_exception_if_trace() #endif /* M68K_TRACE */ #ifdef M68K_LOG extern char* m68k_disassemble_quick(uint pc); extern uint m68k_pc_offset; extern char* m68k_cpu_names[]; #define M68K_DO_LOG(A) if(M68K_LOG) fprintf A #if M68K_LOG_EMULATED_INSTRUCTIONS #define M68K_DO_LOG_EMU(A) if(M68K_LOG) fprintf A #else #define M68K_DO_LOG_EMU(A) #endif #else #define M68K_DO_LOG(A) #define M68K_DO_LOG_EMU(A) #endif /* ======================================================================== */ /* =============================== PROTOTYPES ============================= */ /* ======================================================================== */ typedef struct { uint mode; /* CPU Operation Mode: 68000, 68010, or 68020 */ uint dr[8]; /* Data Registers */ uint ar[8]; /* Address Registers */ uint ppc; /* Previous program counter */ uint pc; /* Program Counter */ uint sp[4]; /* User, Interrupt, and Master Stack Pointers */ uint vbr; /* Vector Base Register (68010+) */ uint sfc; /* Source Function Code Register (m68010+) */ uint dfc; /* Destination Function Code Register (m68010+) */ uint ir; /* Instruction Register */ uint t1_flag; /* Trace 1 */ uint t0_flag; /* Trace 0 */ uint s_flag; /* Supervisor */ uint m_flag; /* Master/Interrupt state */ uint x_flag; /* Extend */ uint n_flag; /* Negative */ uint not_z_flag; /* Zero, inverted for speedups */ uint v_flag; /* Overflow */ uint c_flag; /* Carry */ uint int_mask; /* I0-I2 */ uint int_state; /* Current interrupt state -- ASG: changed from ints_pending */ uint stopped; /* Stopped state */ uint halted; /* Halted state */ uint int_cycles; /* ASG: extra cycles from generated interrupts */ /* Callbacks to host */ int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */ void (*bkpt_ack_callback)(int data); /* Breakpoint Acknowledge */ void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ void (*pc_changed_callback)(int new_pc); /* Called when the PC changes by a large amount */ void (*set_fc_callback)(int new_fc); /* Called when the CPU function code changes */ void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */ } m68k_cpu_core; extern int m68k_clks_left; extern uint m68k_tracing; extern uint m68k_sr_implemented_bits[]; extern m68k_cpu_core m68k_cpu; extern uint* m68k_cpu_dar[]; extern uint* m68k_movem_pi_table[]; extern uint* m68k_movem_pd_table[]; extern uint8 m68k_int_masks[]; extern uint8 m68k_shift_8_table[]; extern uint16 m68k_shift_16_table[]; extern uint m68k_shift_32_table[]; extern uint8 m68k_exception_cycle_table[]; /* Read data from anywhere */ INLINE uint m68ki_read_8 (uint address); INLINE uint m68ki_read_16 (uint address); INLINE uint m68ki_read_32 (uint address); /* Write to memory */ INLINE void m68ki_write_8 (uint address, uint value); INLINE void m68ki_write_16(uint address, uint value); INLINE void m68ki_write_32(uint address, uint value); /* Read data immediately after the program counter */ INLINE uint m68ki_read_imm_8(void); INLINE uint m68ki_read_imm_16(void); INLINE uint m68ki_read_imm_32(void); /* Reads the next word after the program counter */ INLINE uint m68ki_read_instruction(void); /* Read data with specific function code */ INLINE uint m68ki_read_8_fc (uint address, uint fc); INLINE uint m68ki_read_16_fc (uint address, uint fc); INLINE uint m68ki_read_32_fc (uint address, uint fc); /* Write data with specific function code */ INLINE void m68ki_write_8_fc (uint address, uint fc, uint value); INLINE void m68ki_write_16_fc(uint address, uint fc, uint value); INLINE void m68ki_write_32_fc(uint address, uint fc, uint value); INLINE uint m68ki_get_ea_ix(void); /* Get ea for address register indirect + index */ INLINE uint m68ki_get_ea_pcix(void); /* Get ea for program counter indirect + index */ INLINE uint m68ki_get_ea_ix_dst(void); /* Get ea ix for destination of move instruction */ INLINE void m68ki_set_s_flag(int value); /* Set the S flag */ INLINE void m68ki_set_m_flag(int value); /* Set the M flag */ INLINE void m68ki_set_sm_flag(int s_value, int m_value); /* Set the S and M flags */ INLINE void m68ki_set_ccr(uint value); /* set the condition code register */ INLINE void m68ki_set_sr(uint value); /* set the status register */ INLINE void m68ki_set_sr_no_int(uint value); /* ASG: set the status register, but don't check interrupts */ INLINE void m68ki_set_pc(uint address); /* set the program counter */ INLINE void m68ki_service_interrupt(uint pending_mask); /* service a pending interrupt -- ASG: added parameter */ INLINE void m68ki_exception(uint vector); /* process an exception */ INLINE void m68ki_interrupt(uint vector); /* process an interrupt */ INLINE void m68ki_check_interrupts(void); /* ASG: check for interrupts */ /* ======================================================================== */ /* =========================== UTILITY FUNCTIONS ========================== */ /* ======================================================================== */ /* Set the function code and read memory from anywhere. */ INLINE uint m68ki_read_8(uint address) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); return m68k_read_memory_8(ADDRESS_68K(address)); } INLINE uint m68ki_read_16(uint address) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); return m68k_read_memory_16(ADDRESS_68K(address)); } INLINE uint m68ki_read_32(uint address) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); return m68k_read_memory_32(ADDRESS_68K(address)); } /* Set the function code and write memory to anywhere. */ INLINE void m68ki_write_8(uint address, uint value) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); m68k_write_memory_8(ADDRESS_68K(address), value); } INLINE void m68ki_write_16(uint address, uint value) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); m68k_write_memory_16(ADDRESS_68K(address), value); } INLINE void m68ki_write_32(uint address, uint value) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); m68k_write_memory_32(ADDRESS_68K(address), value); } /* Set the function code and read memory immediately following the PC. */ INLINE uint m68ki_read_imm_8(void) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); CPU_PC += 2; return m68k_read_immediate_8(ADDRESS_68K(CPU_PC-1)); } INLINE uint m68ki_read_imm_16(void) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); CPU_PC += 2; return m68k_read_immediate_16(ADDRESS_68K(CPU_PC-2)); } INLINE uint m68ki_read_imm_32(void) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_DATA : FUNCTION_CODE_USER_DATA); CPU_PC += 4; return m68k_read_immediate_32(ADDRESS_68K(CPU_PC-4)); } /* Set the function code and read an instruction immediately following the PC. */ INLINE uint m68ki_read_instruction(void) { m68ki_set_fc(CPU_S ? FUNCTION_CODE_SUPERVISOR_PROGRAM : FUNCTION_CODE_USER_PROGRAM); CPU_PC += 2; return m68k_read_instruction(ADDRESS_68K(CPU_PC-2)); } /* Read/Write data with a specific function code (used by MOVES) */ INLINE uint m68ki_read_8_fc(uint address, uint fc) { m68ki_set_fc(fc&7); return m68k_read_memory_8(ADDRESS_68K(address)); } INLINE uint m68ki_read_16_fc(uint address, uint fc) { m68ki_set_fc(fc&7); return m68k_read_memory_16(ADDRESS_68K(address)); } INLINE uint m68ki_read_32_fc(uint address, uint fc) { m68ki_set_fc(fc&7); return m68k_read_memory_32(ADDRESS_68K(address)); } INLINE void m68ki_write_8_fc(uint address, uint fc, uint value) { m68ki_set_fc(fc&7); m68k_write_memory_8(ADDRESS_68K(address), value); } INLINE void m68ki_write_16_fc(uint address, uint fc, uint value) { m68ki_set_fc(fc&7); m68k_write_memory_16(ADDRESS_68K(address), value); } INLINE void m68ki_write_32_fc(uint address, uint fc, uint value) { m68ki_set_fc(fc&7); m68k_write_memory_32(ADDRESS_68K(address), value); } /* Decode address register indirect with index */ INLINE uint m68ki_get_ea_ix(void) { uint extension = m68ki_read_imm_16(); uint ea_index = m68k_cpu_dar[EXT_INDEX_AR(extension)!=0][EXT_INDEX_REGISTER(extension)]; uint base = AY; uint outer = 0; /* Sign-extend the index value if needed */ if(!EXT_INDEX_LONG(extension)) ea_index = MAKE_INT_16(ea_index); /* If we're running 010 or less, there's no scale or full extension word mode */ if(CPU_MODE & CPU_MODE_010_LESS) return base + ea_index + MAKE_INT_8(extension); /* Scale the index value */ ea_index <<= EXT_INDEX_SCALE(extension); /* If we're using brief extension mode, we are done */ if(EXT_BRIEF_FORMAT(extension)) return base + ea_index + MAKE_INT_8(extension); /* Decode the long extension format */ if(EXT_IX_SUPPRESSED(extension)) ea_index = 0; if(EXT_BR_SUPPRESSED(extension)) base = 0; if(EXT_BD_PRESENT(extension)) base += EXT_BD_LONG(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); if(EXT_NO_MEMORY_INDIRECT(extension)) return base + ea_index; if(EXT_OD_PRESENT(extension)) outer = EXT_OD_LONG(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); if(EXT_POSTINDEX(extension)) return m68ki_read_32(base) + ea_index + outer; return m68ki_read_32(base + ea_index) + outer; } /* Decode address register indirect with index for MOVE destination */ INLINE uint m68ki_get_ea_ix_dst(void) { uint extension = m68ki_read_imm_16(); uint ea_index = m68k_cpu_dar[EXT_INDEX_AR(extension)!=0][EXT_INDEX_REGISTER(extension)]; uint base = AX; /* This is the only thing different from m68ki_get_ea_ix() */ uint outer = 0; /* Sign-extend the index value if needed */ if(!EXT_INDEX_LONG(extension)) ea_index = MAKE_INT_16(ea_index); /* If we're running 010 or less, there's no scale or full extension word mode */ if(CPU_MODE & CPU_MODE_010_LESS) return base + ea_index + MAKE_INT_8(extension); /* Scale the index value */ ea_index <<= EXT_INDEX_SCALE(extension); /* If we're using brief extension mode, we are done */ if(EXT_BRIEF_FORMAT(extension)) return base + ea_index + MAKE_INT_8(extension); /* Decode the long extension format */ if(EXT_IX_SUPPRESSED(extension)) ea_index = 0; if(EXT_BR_SUPPRESSED(extension)) base = 0; if(EXT_BD_PRESENT(extension)) base += EXT_BD_LONG(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); if(EXT_NO_MEMORY_INDIRECT(extension)) return base + ea_index; if(EXT_OD_PRESENT(extension)) outer = EXT_OD_LONG(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); if(EXT_POSTINDEX(extension)) return m68ki_read_32(base) + ea_index + outer; return m68ki_read_32(base + ea_index) + outer; } /* Decode program counter indirect with index */ INLINE uint m68ki_get_ea_pcix(void) { uint base = (CPU_PC+=2) - 2; uint extension = m68ki_read_16(base); uint ea_index = m68k_cpu_dar[EXT_INDEX_AR(extension)!=0][EXT_INDEX_REGISTER(extension)]; uint outer = 0; /* Sign-extend the index value if needed */ if(!EXT_INDEX_LONG(extension)) ea_index = MAKE_INT_16(ea_index); /* If we're running 010 or less, there's no scale or full extension word mode */ if(CPU_MODE & CPU_MODE_010_LESS) return base + ea_index + MAKE_INT_8(extension); /* Scale the index value */ ea_index <<= EXT_INDEX_SCALE(extension); /* If we're using brief extension mode, we are done */ if(EXT_BRIEF_FORMAT(extension)) return base + ea_index + MAKE_INT_8(extension); /* Decode the long extension format */ if(EXT_IX_SUPPRESSED(extension)) ea_index = 0; if(EXT_BR_SUPPRESSED(extension)) base = 0; if(EXT_BD_PRESENT(extension)) base += EXT_BD_LONG(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); if(EXT_NO_MEMORY_INDIRECT(extension)) return base + ea_index; if(EXT_OD_PRESENT(extension)) outer = EXT_OD_LONG(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16()); if(EXT_POSTINDEX(extension)) return m68ki_read_32(base) + ea_index + outer; return m68ki_read_32(base + ea_index) + outer; } /* Set the S flag and change the active stack pointer. */ INLINE void m68ki_set_s_flag(int value) { /* ASG: Only do the rest if we're changing */ value = (value != 0); if (CPU_S != value) { /* Backup the old stack pointer */ CPU_SP[CPU_S | (CPU_M & (CPU_S<<1))] = CPU_A[7]; /* Set the S flag */ CPU_S = value; /* Set the new stack pointer */ CPU_A[7] = CPU_SP[CPU_S | (CPU_M & (CPU_S<<1))]; } } /* Set the M flag and change the active stack pointer. */ INLINE void m68ki_set_m_flag(int value) { /* ASG: Only do the rest if we're changing */ value = (value != 0 && CPU_MODE & CPU_MODE_020_PLUS)<<1; if (CPU_M != value) { /* Backup the old stack pointer */ CPU_SP[CPU_S | (CPU_M & (CPU_S<<1))] = CPU_A[7]; /* Set the M flag */ CPU_M = value; /* Set the new stack pointer */ CPU_A[7] = CPU_SP[CPU_S | (CPU_M & (CPU_S<<1))]; } } /* Set the S and M flags and change the active stack pointer. */ INLINE void m68ki_set_sm_flag(int s_value, int m_value) { /* ASG: Only do the rest if we're changing */ s_value = (s_value != 0); m_value = (m_value != 0 && CPU_MODE & CPU_MODE_020_PLUS)<<1; if (CPU_S != s_value || CPU_M != m_value) { /* Backup the old stack pointer */ CPU_SP[CPU_S | (CPU_M & (CPU_S<<1))] = CPU_A[7]; /* Set the S and M flags */ CPU_S = s_value != 0; CPU_M = (m_value != 0 && CPU_MODE & CPU_MODE_020_PLUS)<<1; /* Set the new stack pointer */ CPU_A[7] = CPU_SP[CPU_S | (CPU_M & (CPU_S<<1))]; } } /* Set the condition code register */ INLINE void m68ki_set_ccr(uint value) { CPU_X = BIT_4(value); CPU_N = BIT_3(value); CPU_NOT_Z = !BIT_2(value); CPU_V = BIT_1(value); CPU_C = BIT_0(value); } /* Set the status register */ INLINE void m68ki_set_sr(uint value) { /* ASG: detect changes to the INT_MASK */ int old_mask = CPU_INT_MASK; /* Mask out the "unimplemented" bits */ value &= m68k_sr_implemented_bits[CPU_MODE]; /* Now set the status register */ CPU_T1 = BIT_F(value); CPU_T0 = BIT_E(value); CPU_INT_MASK = (value >> 8) & 7; CPU_X = BIT_4(value); CPU_N = BIT_3(value); CPU_NOT_Z = !BIT_2(value); CPU_V = BIT_1(value); CPU_C = BIT_0(value); m68ki_set_sm_flag(BIT_D(value), BIT_C(value)); /* ASG: detect changes to the INT_MASK */ if (CPU_INT_MASK != old_mask) m68ki_check_interrupts(); } /* Set the status register */ INLINE void m68ki_set_sr_no_int(uint value) { /* Mask out the "unimplemented" bits */ value &= m68k_sr_implemented_bits[CPU_MODE]; /* Now set the status register */ CPU_T1 = BIT_F(value); CPU_T0 = BIT_E(value); CPU_INT_MASK = (value >> 8) & 7; CPU_X = BIT_4(value); CPU_N = BIT_3(value); CPU_NOT_Z = !BIT_2(value); CPU_V = BIT_1(value); CPU_C = BIT_0(value); m68ki_set_sm_flag(BIT_D(value), BIT_C(value)); } /* I set the PC this way to let host programs be nicer. * This is mainly for programs running from separate ram banks. * If the host program knows where the PC is, it can offer faster * ram access times for data to be retrieved immediately following * the PC. */ INLINE void m68ki_set_pc(uint address) { /* Set the program counter */ CPU_PC = address; /* Inform the host program */ /* MAME */ // change_pc24(ADDRESS_68K(address)); /* m68ki_pc_changed(ADDRESS_68K(address)); */ } /* Process an exception */ INLINE void m68ki_exception(uint vector) { /* Save the old status register */ uint old_sr = m68ki_get_sr(); /* Use up some clock cycles */ USE_CLKS(m68k_exception_cycle_table[vector]); /* Turn off stopped state and trace flag, clear pending traces */ CPU_STOPPED = 0; CPU_T1 = CPU_T0 = 0; m68ki_clear_trace(); /* Enter supervisor mode */ m68ki_set_s_flag(1); /* Push a stack frame */ if(CPU_MODE & CPU_MODE_010_PLUS) m68ki_push_16(vector<<2); /* This is format 0 */ m68ki_push_32(CPU_PPC); /* save previous PC, ie. PC that contains an offending instruction */ m68ki_push_16(old_sr); /* Generate a new program counter from the vector */ m68ki_set_pc(m68ki_read_32((vector<<2)+CPU_VBR)); } /* Process an interrupt (or trap) */ INLINE void m68ki_interrupt(uint vector) { /* Save the old status register */ uint old_sr = m68ki_get_sr(); /* Use up some clock cycles */ /* ASG: just keep them pending */ /* USE_CLKS(m68k_exception_cycle_table[vector]);*/ CPU_INT_CYCLES += m68k_exception_cycle_table[vector]; /* Turn off stopped state and trace flag, clear pending traces */ CPU_STOPPED = 0; CPU_T1 = CPU_T0 = 0; m68ki_clear_trace(); /* Enter supervisor mode */ m68ki_set_s_flag(1); /* Push a stack frame */ if(CPU_MODE & CPU_MODE_010_PLUS) m68ki_push_16(vector<<2); /* This is format 0 */ m68ki_push_32(CPU_PC); m68ki_push_16(old_sr); /* Generate a new program counter from the vector */ m68ki_set_pc(m68ki_read_32((vector<<2)+CPU_VBR)); } /* Service an interrupt request */ INLINE void m68ki_service_interrupt(uint pending_mask) /* ASG: added parameter here */ { uint int_level = 7; uint vector; /* Start at level 7 and then go down */ for(;!(pending_mask & (1< extern FILE* some_file_handle #define M68K_LOG some_file_handle #define M68K_LOG_EMULATED_INSTRUCTIONS 1 */ /* Set to your compiler's static inline keyword. If your compiler doesn't * have inline, just set this to static. * If you define INLINE in the makefile, it will override this value. */ #ifndef INLINE //#define INLINE static __inline__ #define INLINE static #endif /* ======================================================================== */ /* ============================== MAME STUFF ============================== */ /* ======================================================================== */ /* Uncomment this to enable mame stuff */ /* */ //#include "m68kmame.h" /* ======================================================================== */ /* ============================== END OF FILE ============================= */ /* ======================================================================== */ #endif /* M68KCONF__HEADER */ dgen-sdl-1.23/musa/m68k_in.c 644 1750 1750 527724 7027317557 10737 void m68000_1010(void) { m68ki_exception(EXCEPTION_1010); M68K_DO_LOG_EMU((M68K_LOG, "%s at %08x: called 1010 instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); } void m68000_1111(void) { m68ki_exception(EXCEPTION_1111); M68K_DO_LOG_EMU((M68K_LOG, "%s at %08x: called 1111 instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); } void m68000_abcd_rr(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + (CPU_X != 0); if (res > 9) res += 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); if ((CPU_X = CPU_C = res > 0x99) != 0) res -= 0xa0; *d_dst = MASK_OUT_BELOW_8(*d_dst) | MASK_OUT_ABOVE_8(res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(6); } void m68000_abcd_mm_ax7(void) { uint src = m68ki_read_8(--AY); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + (CPU_X != 0); if (res > 9) res += 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); if ((CPU_X = CPU_C = res > 0x99) != 0) res -= 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_abcd_mm_ay7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + (CPU_X != 0); if (res > 9) res += 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); if ((CPU_X = CPU_C = res > 0x99) != 0) res -= 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_abcd_mm_axy7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + (CPU_X != 0); if (res > 9) res += 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); if ((CPU_X = CPU_C = res > 0x99) != 0) res -= 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_abcd_mm(void) { uint src = m68ki_read_8(--AY); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + (CPU_X != 0); if (res > 9) res += 6; res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); if ((CPU_X = CPU_C = res > 0x99) != 0) res -= 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_add_er_d_8(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(src + dst); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(4); } void m68000_add_er_8(void) { uint *d_dst = &DX; uint src = m68ki_read_8(m68ki_get_ea_8()); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(src + dst); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(4); } void m68000_add_er_d_16(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(src + dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(4); } void m68000_add_er_a_16(void) { uint *d_dst = &DX; uint src = AY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(src + dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(4); } void m68000_add_er_16(void) { uint *d_dst = &DX; uint src = m68ki_read_16(m68ki_get_ea_16()); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(src + dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(4); } void m68000_add_er_d_32(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(src + dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(8); } void m68000_add_er_a_32(void) { uint *d_dst = &DX; uint src = AY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(src + dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(8); } void m68000_add_er_32(void) { uint *d_dst = &DX; uint src = m68ki_read_32(m68ki_get_ea_32()); uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(src + dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(6); } void m68000_add_re_8(void) { uint ea = m68ki_get_ea_8(); uint src = DX; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(8); } void m68000_add_re_16(void) { uint ea = m68ki_get_ea_16(); uint src = DX; uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(src + dst); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(8); } void m68000_add_re_32(void) { uint ea = m68ki_get_ea_32(); uint src = DX; uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(src + dst); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(12); } void m68000_adda_d_16(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst + MAKE_INT_16(DY)); USE_CLKS(8); } void m68000_adda_a_16(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst + MAKE_INT_16(AY)); USE_CLKS(8); } void m68000_adda_16(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst + MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16()))); USE_CLKS(8); } void m68000_adda_d_32(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst + DY); USE_CLKS(8); } void m68000_adda_a_32(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst + AY); USE_CLKS(8); } void m68000_adda_32(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst + m68ki_read_32(m68ki_get_ea_32())); USE_CLKS(6); } void m68000_addi_d_8(void) { uint *d_dst = &DY; uint src = m68ki_read_imm_8(); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(src + dst); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(8); } void m68000_addi_8(void) { uint src = m68ki_read_imm_8(); uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(12); } void m68000_addi_d_16(void) { uint *d_dst = &DY; uint src = m68ki_read_imm_16(); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(src + dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(8); } void m68000_addi_16(void) { uint src = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(src + dst); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(12); } void m68000_addi_d_32(void) { uint *d_dst = &DY; uint src = m68ki_read_imm_32(); uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(src + dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(16); } void m68000_addi_32(void) { uint src = m68ki_read_imm_32(); uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(src + dst); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(20); } void m68000_addq_d_8(void) { uint *d_dst = &DY; uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(src + dst); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(4); } void m68000_addq_8(void) { uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(8); } void m68000_addq_d_16(void) { uint *d_dst = &DY; uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(src + dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(4); } void m68000_addq_a_16(void) { uint *a_dst = &AY; *a_dst = MASK_OUT_ABOVE_32(*a_dst + (((CPU_IR >> 9) - 1) & 7) + 1); USE_CLKS(4); } void m68000_addq_16(void) { uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(src + dst); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(8); } void m68000_addq_d_32(void) { uint *d_dst = &DY; uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(src + dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(8); } void m68000_addq_a_32(void) { uint *a_dst = &AY; *a_dst = MASK_OUT_ABOVE_32(*a_dst + (((CPU_IR >> 9) - 1) & 7) + 1); USE_CLKS(8); } void m68000_addq_32(void) { uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(src + dst); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(12); } void m68000_addx_rr_8(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(src + dst + (CPU_X != 0)); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(4); } void m68000_addx_rr_16(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(src + dst + (CPU_X != 0)); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(4); } void m68000_addx_rr_32(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(src + dst + (CPU_X != 0)); CPU_N = GET_MSB_32(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(8); } void m68000_addx_mm_8_ax7(void) { uint src = m68ki_read_8(--AY); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst + (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(18); } void m68000_addx_mm_8_ay7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst + (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(18); } void m68000_addx_mm_8_axy7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst + (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(18); } void m68000_addx_mm_8(void) { uint src = m68ki_read_8(--AY); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(src + dst + (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_8(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_8(src, dst, res); USE_CLKS(18); } void m68000_addx_mm_16(void) { uint src = m68ki_read_16(AY -= 2); uint ea = (AX -= 2); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(src + dst + (CPU_X != 0)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_16(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_16(src, dst, res); USE_CLKS(18); } void m68000_addx_mm_32(void) { uint src = m68ki_read_32(AY -= 4); uint ea = (AX -= 4); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(src + dst + (CPU_X != 0)); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = VFLAG_ADD_32(src, dst, res); CPU_X = CPU_C = CFLAG_ADD_32(src, dst, res); USE_CLKS(30); } void m68000_and_er_d_8(void) { uint res = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_and_er_8(void) { uint res = MASK_OUT_ABOVE_8(DX &= (m68ki_read_8(m68ki_get_ea_8()) | 0xffffff00)); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_and_er_d_16(void) { uint res = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_and_er_16(void) { uint res = MASK_OUT_ABOVE_16(DX &= (m68ki_read_16(m68ki_get_ea_16()) | 0xffff0000)); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_and_er_d_32(void) { uint res = DX &= DY; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_and_er_32(void) { uint res = DX &= m68ki_read_32(m68ki_get_ea_32()); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(6); } void m68000_and_re_8(void) { uint ea = m68ki_get_ea_8(); uint res = MASK_OUT_ABOVE_8(DX & m68ki_read_8(ea)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_and_re_16(void) { uint ea = m68ki_get_ea_16(); uint res = MASK_OUT_ABOVE_16(DX & m68ki_read_16(ea)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_and_re_32(void) { uint ea = m68ki_get_ea_32(); uint res = DX & m68ki_read_32(ea); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_andi_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY &= (m68ki_read_imm_8() | 0xffffff00)); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_andi_8(void) { uint tmp = m68ki_read_imm_8(); uint ea = m68ki_get_ea_8(); uint res = tmp & m68ki_read_8(ea); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_andi_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY &= (m68ki_read_imm_16() | 0xffff0000)); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_andi_16(void) { uint tmp = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint res = tmp & m68ki_read_16(ea); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_andi_d_32(void) { uint res = DY &= (m68ki_read_imm_32()); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(14); } void m68000_andi_32(void) { uint tmp = m68ki_read_imm_32(); uint ea = m68ki_get_ea_32(); uint res = tmp & m68ki_read_32(ea); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(20); } void m68000_andi_to_ccr(void) { m68ki_set_ccr(m68ki_get_ccr() & m68ki_read_imm_16()); USE_CLKS(20); } void m68000_andi_to_sr(void) { uint and_val = m68ki_read_imm_16(); if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_set_sr(m68ki_get_sr() & and_val); USE_CLKS(20); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_asr_s_8(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = src >> shift; if (GET_MSB_8(src)) res |= m68k_shift_8_table[shift]; *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; CPU_X = CPU_C = shift > 7 ? CPU_N : (src >> (shift - 1)) & 1; USE_CLKS((shift << 1) + 6); } void m68000_asr_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = src >> shift; if (GET_MSB_16(src)) res |= m68k_shift_16_table[shift]; *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; CPU_X = CPU_C = (src >> (shift - 1)) & 1; USE_CLKS((shift << 1) + 6); } void m68000_asr_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = src >> shift; if (GET_MSB_32(src)) res |= m68k_shift_32_table[shift]; *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; CPU_X = CPU_C = (src >> (shift - 1)) & 1; USE_CLKS((shift << 1) + 8); } void m68000_asr_r_8(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = src >> shift; USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift < 8) { if (GET_MSB_8(src)) res |= m68k_shift_8_table[shift]; *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_C = CPU_X = (src >> (shift - 1)) & 1; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; return; } if (GET_MSB_8(src)) { *d_dst |= 0xff; CPU_C = CPU_X = 1; CPU_N = 1; CPU_NOT_Z = 1; CPU_V = 0; return; } *d_dst &= 0xffffff00; CPU_C = CPU_X = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_asr_r_16(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = src >> shift; USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift < 16) { if (GET_MSB_16(src)) res |= m68k_shift_16_table[shift]; *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_C = CPU_X = (src >> (shift - 1)) & 1; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; return; } if (GET_MSB_16(src)) { *d_dst |= 0xffff; CPU_C = CPU_X = 1; CPU_N = 1; CPU_NOT_Z = 1; CPU_V = 0; return; } *d_dst &= 0xffff0000; CPU_C = CPU_X = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_asr_r_32(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = src >> shift; USE_CLKS((shift << 1) + 8); if (shift != 0) { if (shift < 32) { if (GET_MSB_32(src)) res |= m68k_shift_32_table[shift]; *d_dst = res; CPU_C = CPU_X = (src >> (shift - 1)) & 1; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; return; } if (GET_MSB_32(src)) { *d_dst = 0xffffffff; CPU_C = CPU_X = 1; CPU_N = 1; CPU_NOT_Z = 1; CPU_V = 0; return; } *d_dst = 0; CPU_C = CPU_X = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_asr_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint res = src >> 1; if (GET_MSB_16(src)) res |= 0x8000; m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; CPU_C = CPU_X = src & 1; USE_CLKS(8); } void m68000_asl_s_8(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = MASK_OUT_ABOVE_8(src << shift); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_X = CPU_C = (src >> (8 - shift)) & 1; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; src &= m68k_shift_8_table[shift + 1]; CPU_V = !(src == 0 || (src == m68k_shift_8_table[shift + 1] && shift < 8)); USE_CLKS((shift << 1) + 6); } void m68000_asl_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = MASK_OUT_ABOVE_16(src << shift); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = (src >> (16 - shift)) & 1; src &= m68k_shift_16_table[shift + 1]; CPU_V = !(src == 0 || src == m68k_shift_16_table[shift + 1]); USE_CLKS((shift << 1) + 6); } void m68000_asl_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = *d_dst; uint res = MASK_OUT_ABOVE_32(src << shift); *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = (src >> (32 - shift)) & 1; src &= m68k_shift_32_table[shift + 1]; CPU_V = !(src == 0 || src == m68k_shift_32_table[shift + 1]); USE_CLKS((shift << 1) + 8); } void m68000_asl_r_8(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = MASK_OUT_ABOVE_8(src << shift); USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift < 8) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_X = CPU_C = (src >> (8 - shift)) & 1; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; src &= m68k_shift_8_table[shift + 1]; CPU_V = !(src == 0 || src == m68k_shift_8_table[shift + 1]); return; } *d_dst &= 0xffffff00; CPU_X = CPU_C = (shift == 8 ? src & 1 : 0); CPU_N = 0; CPU_NOT_Z = 0; CPU_V = !(src == 0); return; } CPU_C = 0; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_asl_r_16(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = MASK_OUT_ABOVE_16(src << shift); USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift < 16) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_X = CPU_C = (src >> (16 - shift)) & 1; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; src &= m68k_shift_16_table[shift + 1]; CPU_V = !(src == 0 || src == m68k_shift_16_table[shift + 1]); return; } *d_dst &= 0xffff0000; CPU_X = CPU_C = (shift == 16 ? src & 1 : 0); CPU_N = 0; CPU_NOT_Z = 0; CPU_V = !(src == 0); return; } CPU_C = 0; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_asl_r_32(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = *d_dst; uint res = MASK_OUT_ABOVE_32(src << shift); USE_CLKS((shift << 1) + 8); if (shift != 0) { if (shift < 32) { *d_dst = res; CPU_X = CPU_C = (src >> (32 - shift)) & 1; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; src &= m68k_shift_32_table[shift + 1]; CPU_V = !(src == 0 || src == m68k_shift_32_table[shift + 1]); return; } *d_dst = 0; CPU_X = CPU_C = (shift == 32 ? src & 1 : 0); CPU_N = 0; CPU_NOT_Z = 0; CPU_V = !(src == 0); return; } CPU_C = 0; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_asl_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(src << 1); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = GET_MSB_16(src); src &= 0xc000; CPU_V = !(src == 0 || src == 0xc000); USE_CLKS(8); } void m68000_bhi_8(void) { if (CONDITION_HI) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bhi_16(void) { if (CONDITION_HI) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bhi_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_HI) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bls_8(void) { if (CONDITION_LS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bls_16(void) { if (CONDITION_LS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bls_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bcc_8(void) { if (CONDITION_CC) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bcc_16(void) { if (CONDITION_CC) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bcc_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CC) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bcs_8(void) { if (CONDITION_CS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bcs_16(void) { if (CONDITION_CS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bcs_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bne_8(void) { if (CONDITION_NE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bne_16(void) { if (CONDITION_NE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bne_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_NE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_beq_8(void) { if (CONDITION_EQ) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_beq_16(void) { if (CONDITION_EQ) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_beq_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_EQ) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bvc_8(void) { if (CONDITION_VC) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bvc_16(void) { if (CONDITION_VC) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bvc_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VC) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bvs_8(void) { if (CONDITION_VS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bvs_16(void) { if (CONDITION_VS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bvs_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bpl_8(void) { if (CONDITION_PL) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bpl_16(void) { if (CONDITION_PL) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bpl_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_PL) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bmi_8(void) { if (CONDITION_MI) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bmi_16(void) { if (CONDITION_MI) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bmi_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_MI) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bge_8(void) { if (CONDITION_GE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bge_16(void) { if (CONDITION_GE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bge_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_blt_8(void) { if (CONDITION_LT) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_blt_16(void) { if (CONDITION_LT) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_blt_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LT) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bgt_8(void) { if (CONDITION_GT) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_bgt_16(void) { if (CONDITION_GT) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_bgt_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GT) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_ble_8(void) { if (CONDITION_LE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); return; } USE_CLKS(8); } void m68000_ble_16(void) { if (CONDITION_LE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(12); } void m68020_ble_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LE) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } CPU_PC += 2; USE_CLKS(6); return; } m68000_illegal(); } void m68000_bchg_r_d(void) { uint *d_dst = &DY; uint mask = 1 << (DX & 0x1f); CPU_NOT_Z = *d_dst & mask; *d_dst ^= mask; USE_CLKS(8); } void m68000_bchg_r(void) { uint ea = m68ki_get_ea_8(); uint src = m68ki_read_8(ea); uint mask = 1 << (DX & 7); CPU_NOT_Z = src & mask; m68ki_write_8(ea, src ^ mask); USE_CLKS(8); } void m68000_bchg_s_d(void) { uint *d_dst = &DY; uint mask = 1 << (m68ki_read_imm_8() & 0x1f); CPU_NOT_Z = *d_dst & mask; *d_dst ^= mask; USE_CLKS(12); } void m68000_bchg_s(void) { uint mask = 1 << (m68ki_read_imm_8() & 7); uint ea = m68ki_get_ea_8(); uint src = m68ki_read_8(ea); CPU_NOT_Z = src & mask; m68ki_write_8(ea, src ^ mask); USE_CLKS(12); } void m68000_bclr_r_d(void) { uint *d_dst = &DY; uint mask = 1 << (DX & 0x1f); CPU_NOT_Z = *d_dst & mask; *d_dst &= ~mask; USE_CLKS(10); } void m68000_bclr_r(void) { uint ea = m68ki_get_ea_8(); uint src = m68ki_read_8(ea); uint mask = 1 << (DX & 7); CPU_NOT_Z = src & mask; m68ki_write_8(ea, src & ~mask); USE_CLKS(8); } void m68000_bclr_s_d(void) { uint *d_dst = &DY; uint mask = 1 << (m68ki_read_imm_8() & 0x1f); CPU_NOT_Z = *d_dst & mask; *d_dst &= ~mask; USE_CLKS(14); } void m68000_bclr_s(void) { uint mask = 1 << (m68ki_read_imm_8() & 7); uint ea = m68ki_get_ea_8(); uint src = m68ki_read_8(ea); CPU_NOT_Z = src & mask; m68ki_write_8(ea, src & ~mask); USE_CLKS(12); } void m68020_bfchg_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); DY ^= mask; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(12); } void m68020_bfchg(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); m68ki_write_32(base, (m68ki_read_32(base) ^ (mask >> offset))); if ((width + offset) > 32) m68ki_write_8(base + 4, (m68ki_read_8(base + 4) ^ (mask << (8 - offset)))); CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(20); } void m68020_bfclr_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); DY &= ~mask; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(12); } void m68020_bfclr(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); m68ki_write_32(base, (m68ki_read_32(base) & ~(mask >> offset))); if ((width + offset) > 32) m68ki_write_8(base + 4, (m68ki_read_8(base + 4) & ~(mask << (8 - offset)))); CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(20); } void m68020_bfexts_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); if ((CPU_N = (data >> (width - 1)) & 1)) data |= MASK_OUT_ABOVE_32(0xffffffff << width); CPU_NOT_Z = data; CPU_D[(word2 >> 12) & 7] = data; USE_CLKS(8); } void m68020_bfexts(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); if ((CPU_N = (data >> (width - 1)) & 1)) data |= MASK_OUT_ABOVE_32(0xffffffff << width); CPU_NOT_Z = data; CPU_D[(word2 >> 12) & 7] = data; USE_CLKS(15); } void m68020_bfextu_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); CPU_D[(word2 >> 12) & 7] = data; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(8); } void m68020_bfextu(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); CPU_D[(word2 >> 12) & 7] = data; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(15); } void m68020_bfffo_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); uint mask = 1 << (width - 1); for (; mask && !(data & mask); mask >>= 1, offset++) ; CPU_D[(word2 >> 12) & 7] = offset; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(18); } void m68020_bfffo(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); uint mask = 1 << (width - 1); for (; mask && !(data & mask); mask >>= 1, full_offset++) ; CPU_D[(word2 >> 12) & 7] = full_offset; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(28); } void m68020_bfins_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint insert = MASK_OUT_ABOVE_32(CPU_D[(word2 >> 12) & 7] << (32 - width)); uint orig_insert = insert >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); insert = ROR_32(insert, offset); mask = ~ROR_32(mask, offset); DY &= mask; DY |= insert; CPU_N = orig_insert >> (width - 1); CPU_NOT_Z = orig_insert; USE_CLKS(10); } void m68020_bfins(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint insert = MASK_OUT_ABOVE_32(CPU_D[(word2 >> 12) & 7] << (32 - width)); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); m68ki_write_32(base, (m68ki_read_32(base) & ~(mask >> offset)) | (insert >> offset)); if ((width + offset) > 32) m68ki_write_8(base + 4, (m68ki_read_8(base + 4) & ~(mask << (8 - offset))) | MASK_OUT_ABOVE_8(insert << (8 - offset))); CPU_N = GET_MSB_32(insert); CPU_NOT_Z = insert; USE_CLKS(17); } void m68020_bfset_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); DY |= mask; CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(12); } void m68020_bfset(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); uint mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); m68ki_write_32(base, (m68ki_read_32(base) | (mask >> offset))); if ((width + offset) > 32) m68ki_write_8(base + 4, (m68ki_read_8(base + 4) | (mask << (8 - offset)))); CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(20); } void m68020_bftst_d(void) { uint word2 = m68ki_read_imm_16(); uint offset = (BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : word2 >> 6) & 31; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ROL_32(DY, offset) >> (32 - width); /* if offset + width > 32, wraps around in register */ CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(6); } void m68020_bftst(void) { uint word2 = m68ki_read_imm_16(); uint full_offset = BIT_B(word2) ? MAKE_INT_32(CPU_D[(word2 >> 6) & 7]) : (word2 >> 6) & 31; uint base = m68ki_get_ea_8() + (full_offset >> 3); uint offset = full_offset & 7; uint width = (((BIT_5(word2) ? CPU_D[word2 & 7] : word2) - 1) & 31) + 1; uint data = ((m68ki_read_32(base) << offset) | ((offset + width > 32) ? m68ki_read_8(base + 4) >> (8 - offset) : 0)) >> (32 - width); CPU_N = (data >> (width - 1)) & 1; CPU_NOT_Z = data; USE_CLKS(13); } void m68010_bkpt(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { m68ki_bkpt_ack(CPU_MODE & CPU_MODE_020_PLUS ? CPU_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ USE_CLKS(11); } m68000_illegal(); } void m68000_bra_8(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(10); } void m68000_bra_16(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); } void m68020_bra_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_32(CPU_PC)); USE_CLKS(6); return; } m68000_illegal(); } void m68000_bset_r_d(void) { uint *d_dst = &DY; uint mask = 1 << (DX & 0x1f); CPU_NOT_Z = *d_dst & mask; *d_dst |= mask; USE_CLKS(8); } void m68000_bset_r(void) { uint ea = m68ki_get_ea_8(); uint src = m68ki_read_8(ea); uint mask = 1 << (DX & 7); CPU_NOT_Z = src & mask; m68ki_write_8(ea, src | mask); USE_CLKS(8); } void m68000_bset_s_d(void) { uint *d_dst = &DY; uint mask = 1 << (m68ki_read_imm_8() & 0x1f); CPU_NOT_Z = *d_dst & mask; *d_dst |= mask; USE_CLKS(12); } void m68000_bset_s(void) { uint mask = 1 << (m68ki_read_imm_8() & 7); uint ea = m68ki_get_ea_8(); uint src = m68ki_read_8(ea); CPU_NOT_Z = src & mask; m68ki_write_8(ea, src | mask); USE_CLKS(12); } void m68000_bsr_8(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_push_32(CPU_PC); m68ki_branch_byte(MASK_OUT_ABOVE_8(CPU_IR)); USE_CLKS(18); } void m68000_bsr_16(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_push_32(CPU_PC + 2); m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(18); } void m68020_bsr_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_push_32(CPU_PC + 2); m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(7); return; } m68000_illegal(); } void m68000_btst_r_d(void) { CPU_NOT_Z = DY & (1 << (DX & 0x1f)); USE_CLKS(6); } void m68000_btst_r(void) { CPU_NOT_Z = m68ki_read_8(m68ki_get_ea_8()) & (1 << (DX & 7)); USE_CLKS(4); } void m68000_btst_s_d(void) { CPU_NOT_Z = DY & (1 << (m68ki_read_imm_8() & 0x1f)); USE_CLKS(10); } void m68000_btst_s(void) { uint bit = m68ki_read_imm_8() & 7; CPU_NOT_Z = m68ki_read_8(m68ki_get_ea_8()) & (1 << bit); USE_CLKS(8); } void m68020_callm(void) { if (CPU_MODE & CPU_MODE_020) { uint ea = m68ki_get_ea_32(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_PC += 2; M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); USE_CLKS(30); return; } m68000_illegal(); } void m68020_cas_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint *d_src = &CPU_D[word2 & 7]; uint res = MASK_OUT_ABOVE_8(dst - *d_src); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(*d_src, dst, res); CPU_C = CFLAG_SUB_8(*d_src, dst, res); if (CPU_NOT_Z) *d_src = MASK_OUT_BELOW_8(*d_src) | dst; else m68ki_write_8(ea, CPU_D[(word2 >> 6) & 7]); USE_CLKS(15); return; } m68000_illegal(); } void m68020_cas_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint *d_src = &CPU_D[word2 & 7]; uint res = MASK_OUT_ABOVE_16(dst - *d_src); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(*d_src, dst, res); CPU_C = CFLAG_SUB_16(*d_src, dst, res); if (CPU_NOT_Z) *d_src = MASK_OUT_BELOW_16(*d_src) | dst; else m68ki_write_16(ea, CPU_D[(word2 >> 6) & 7]); USE_CLKS(15); return; } m68000_illegal(); } void m68020_cas_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint *d_src = &CPU_D[word2 & 7]; uint res = MASK_OUT_ABOVE_32(dst - *d_src); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(*d_src, dst, res); CPU_C = CFLAG_SUB_32(*d_src, dst, res); if (CPU_NOT_Z) *d_src = dst; else m68ki_write_32(ea, CPU_D[(word2 >> 6) & 7]); USE_CLKS(15); return; } m68000_illegal(); } void m68020_cas2_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_32(); uint *r_src1 = &CPU_D[(word2 >> 16) & 7]; uint ea1 = m68k_cpu_dar[word2 >> 31][(word2 >> 28) & 7]; uint dst1 = m68ki_read_16(ea1); uint res1 = MASK_OUT_ABOVE_16(dst1 - *r_src1); uint *r_src2 = &CPU_D[word2 & 7]; uint ea2 = m68k_cpu_dar[word2 >> 15][(word2 >> 12) & 7]; uint dst2 = m68ki_read_16(ea2); uint res2; m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_N = GET_MSB_16(res1); CPU_NOT_Z = res1; CPU_V = VFLAG_SUB_16(*r_src1, dst1, res1); CPU_C = CFLAG_SUB_16(*r_src1, dst1, res1); if (!CPU_NOT_Z) { res2 = MASK_OUT_ABOVE_16(dst2 - *r_src2); CPU_N = GET_MSB_16(res2); CPU_NOT_Z = res2; CPU_V = VFLAG_SUB_16(*r_src2, dst2, res2); CPU_C = CFLAG_SUB_16(*r_src2, dst2, res2); if (!CPU_NOT_Z) { m68ki_write_16(ea1, CPU_D[(word2 >> 22) & 7]); m68ki_write_16(ea2, CPU_D[(word2 >> 6) & 7]); USE_CLKS(22); return; } } *r_src1 = BIT_1F(word2) ? MAKE_INT_16(dst1) : MASK_OUT_ABOVE_16(*r_src1) | dst1; *r_src2 = BIT_F(word2) ? MAKE_INT_16(dst2) : MASK_OUT_ABOVE_16(*r_src2) | dst2; USE_CLKS(25); return; } m68000_illegal(); } void m68020_cas2_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_32(); uint *r_src1 = &CPU_D[(word2 >> 16) & 7]; uint ea1 = m68k_cpu_dar[word2 >> 31][(word2 >> 28) & 7]; uint dst1 = m68ki_read_32(ea1); uint res1 = MASK_OUT_ABOVE_32(dst1 - *r_src1); uint *r_src2 = &CPU_D[word2 & 7]; uint ea2 = m68k_cpu_dar[word2 >> 15][(word2 >> 12) & 7]; uint dst2 = m68ki_read_32(ea2); uint res2; m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_N = GET_MSB_32(res1); CPU_NOT_Z = res1; CPU_V = VFLAG_SUB_32(*r_src1, dst1, res1); CPU_C = CFLAG_SUB_32(*r_src1, dst1, res1); if (!CPU_NOT_Z) { res2 = MASK_OUT_ABOVE_32(dst2 - *r_src2); CPU_N = GET_MSB_32(res2); CPU_NOT_Z = res2; CPU_V = VFLAG_SUB_32(*r_src2, dst2, res2); CPU_C = CFLAG_SUB_32(*r_src2, dst2, res2); if (!CPU_NOT_Z) { m68ki_write_32(ea1, CPU_D[(word2 >> 22) & 7]); m68ki_write_32(ea2, CPU_D[(word2 >> 6) & 7]); USE_CLKS(22); return; } } *r_src1 = dst1; *r_src2 = dst2; USE_CLKS(25); return; } m68000_illegal(); } void m68000_chk_d_16(void) { int src = MAKE_INT_16(DX); int bound = MAKE_INT_16(DY); if (src >= 0 && src <= bound) { USE_CLKS(10); return; } CPU_N = src < 0; m68ki_interrupt(EXCEPTION_CHK); } void m68000_chk_16(void) { int src = MAKE_INT_16(DX); int bound = MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16())); if (src >= 0 && src <= bound) { USE_CLKS(10); return; } CPU_N = src < 0; m68ki_interrupt(EXCEPTION_CHK); } void m68020_chk_d_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { int src = DX; int bound = DY; if (src >= 0 && src <= bound) { USE_CLKS(8); return; } CPU_N = src < 0; m68ki_interrupt(EXCEPTION_CHK); return; } m68000_illegal(); } void m68020_chk_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { int src = DX; int bound = m68ki_read_32(m68ki_get_ea_32()); if (src >= 0 && src <= bound) { USE_CLKS(8); return; } CPU_N = src < 0; m68ki_interrupt(EXCEPTION_CHK); return; } m68000_illegal(); } void m68020_chk2_cmp2_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint src = m68k_cpu_dar[word2 >> 15][(word2 >> 12) & 7]; uint ea = m68ki_get_ea_8(); uint lower_bound = m68ki_read_8(ea); uint upper_bound = m68ki_read_8(ea + 1); if (BIT_F(word2)) { lower_bound = MAKE_INT_8(lower_bound); upper_bound = MAKE_INT_8(upper_bound); } else src = MASK_OUT_ABOVE_8(src); CPU_NOT_Z = !(src == lower_bound || src == upper_bound); CPU_C = src < lower_bound || src > upper_bound; if (CPU_C && BIT_B(word2)) /* chk2 */ m68ki_interrupt(EXCEPTION_CHK); USE_CLKS(18); return; } m68000_illegal(); } void m68020_chk2_cmp2_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint src = m68k_cpu_dar[word2 >> 15][(word2 >> 12) & 7]; uint ea = m68ki_get_ea_16(); uint lower_bound = m68ki_read_16(ea); uint upper_bound = m68ki_read_16(ea + 2); if (BIT_F(word2)) { lower_bound = MAKE_INT_16(lower_bound); upper_bound = MAKE_INT_16(upper_bound); } else src = MASK_OUT_ABOVE_16(src); CPU_NOT_Z = !(src == lower_bound || src == upper_bound); CPU_C = src < lower_bound || src > upper_bound; if (CPU_C && BIT_B(word2)) /* chk2 */ m68ki_interrupt(EXCEPTION_CHK); USE_CLKS(18); return; } m68000_illegal(); } void m68020_chk2_cmp2_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint src = m68k_cpu_dar[word2 >> 15][(word2 >> 12) & 7]; uint ea = m68ki_get_ea_32(); uint lower_bound = m68ki_read_32(ea); uint upper_bound = m68ki_read_32(ea + 4); CPU_NOT_Z = !(src == lower_bound || src == upper_bound); CPU_C = src < lower_bound || src > upper_bound; if (CPU_C && BIT_B(word2)) /* chk2 */ m68ki_interrupt(EXCEPTION_CHK); USE_CLKS(18); return; } m68000_illegal(); } void m68000_clr_d_8(void) { DY &= 0xffffff00; CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 0; USE_CLKS(4); } void m68000_clr_8(void) { m68ki_write_8(m68ki_get_ea_8(), 0); CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 0; USE_CLKS(8); } void m68000_clr_d_16(void) { DY &= 0xffff0000; CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 0; USE_CLKS(4); } void m68000_clr_16(void) { m68ki_write_16(m68ki_get_ea_16(), 0); CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 0; USE_CLKS(8); } void m68000_clr_d_32(void) { DY = 0; CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 0; USE_CLKS(6); } void m68000_clr_32(void) { m68ki_write_32(m68ki_get_ea_32(), 0); CPU_N = CPU_V = CPU_C = 0; CPU_NOT_Z = 0; USE_CLKS(12); } void m68000_cmp_d_8(void) { uint src = DY; uint dst = DX; uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(4); } void m68000_cmp_8(void) { uint src = m68ki_read_8(m68ki_get_ea_8()); uint dst = DX; uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(4); } void m68000_cmp_d_16(void) { uint src = DY; uint dst = DX; uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_cmp_a_16(void) { uint src = AY; uint dst = DX; uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_cmp_16(void) { uint src = m68ki_read_16(m68ki_get_ea_16()); uint dst = DX; uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_cmp_d_32(void) { uint src = DY; uint dst = DX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmp_a_32(void) { uint src = AY; uint dst = DX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmp_32(void) { uint src = m68ki_read_32(m68ki_get_ea_32()); uint dst = DX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpa_d_16(void) { uint src = MAKE_INT_16(DY); uint dst = AX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpa_a_16(void) { uint src = MAKE_INT_16(AY); uint dst = AX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpa_16(void) { uint src = MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16())); uint dst = AX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpa_d_32(void) { uint src = DY; uint dst = AX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpa_a_32(void) { uint src = AY; uint dst = AX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpa_32(void) { uint src = m68ki_read_32(m68ki_get_ea_32()); uint dst = AX; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_cmpi_d_8(void) { uint src = m68ki_read_imm_8(); uint dst = DY; uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(8); } void m68000_cmpi_8(void) { uint src = m68ki_read_imm_8(); uint dst = m68ki_read_8(m68ki_get_ea_8()); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(8); } void m68020_cmpi_pcdi_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_imm_8(); uint old_pc = (CPU_PC += 2) - 2; uint ea = old_pc + MAKE_INT_16(m68ki_read_16(old_pc)); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(8); return; } m68000_illegal(); } void m68020_cmpi_pcix_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_imm_8(); uint dst = m68ki_read_8(EA_PCIX); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(8); return; } m68000_illegal(); } void m68000_cmpi_d_16(void) { uint src = m68ki_read_imm_16(); uint dst = DY; uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(8); } void m68000_cmpi_16(void) { uint src = m68ki_read_imm_16(); uint dst = m68ki_read_16(m68ki_get_ea_16()); uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(8); } void m68020_cmpi_pcdi_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_imm_16(); uint old_pc = (CPU_PC += 2) - 2; uint ea = old_pc + MAKE_INT_16(m68ki_read_16(old_pc)); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(8); return; } m68000_illegal(); } void m68020_cmpi_pcix_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_imm_16(); uint dst = m68ki_read_16(EA_PCIX); uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(8); return; } m68000_illegal(); } void m68000_cmpi_d_32(void) { uint src = m68ki_read_imm_32(); uint dst = DY; uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(14); } void m68000_cmpi_32(void) { uint src = m68ki_read_imm_32(); uint dst = m68ki_read_32(m68ki_get_ea_32()); uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(12); } void m68020_cmpi_pcdi_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_imm_32(); uint old_pc = (CPU_PC += 2) - 2; uint ea = old_pc + MAKE_INT_16(m68ki_read_16(old_pc)); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(8); return; } m68000_illegal(); } void m68020_cmpi_pcix_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_imm_32(); uint dst = m68ki_read_32(EA_PCIX); uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(8); return; } m68000_illegal(); } void m68000_cmpm_8_ax7(void) { uint src = m68ki_read_8(AY++); uint dst = m68ki_read_8((CPU_A[7] += 2) - 2); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(12); } void m68000_cmpm_8_ay7(void) { uint src = m68ki_read_8((CPU_A[7] += 2) - 2); uint dst = m68ki_read_8(AX++); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(12); } void m68000_cmpm_8_axy7(void) { uint src = m68ki_read_8((CPU_A[7] += 2) - 2); uint dst = m68ki_read_8((CPU_A[7] += 2) - 2); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(12); } void m68000_cmpm_8(void) { uint src = m68ki_read_8(AY++); uint dst = m68ki_read_8(AX++); uint res = MASK_OUT_ABOVE_8(dst - src); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_8(src, dst, res); CPU_C = CFLAG_SUB_8(src, dst, res); USE_CLKS(12); } void m68000_cmpm_16(void) { uint src = m68ki_read_16((AY += 2) - 2); uint dst = m68ki_read_16((AX += 2) - 2); uint res = MASK_OUT_ABOVE_16(dst - src); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_16(src, dst, res); CPU_C = CFLAG_SUB_16(src, dst, res); USE_CLKS(12); } void m68000_cmpm_32(void) { uint src = m68ki_read_32((AY += 4) - 4); uint dst = m68ki_read_32((AX += 4) - 4); uint res = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = VFLAG_SUB_32(src, dst, res); CPU_C = CFLAG_SUB_32(src, dst, res); USE_CLKS(20); } void m68020_cpbcc(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); return; } m68000_1111(); } void m68020_cpdbcc(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); return; } m68000_1111(); } void m68020_cpgen(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); return; } m68000_1111(); } void m68020_cpscc(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); return; } m68000_1111(); } void m68020_cptrapcc(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); return; } m68000_1111(); } void m68000_dbt(void) { CPU_PC += 2; USE_CLKS(12); } void m68000_dbf(void) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); } void m68000_dbhi(void) { if (CONDITION_NOT_HI) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbls(void) { if (CONDITION_NOT_LS) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbcc(void) { if (CONDITION_NOT_CC) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbcs(void) { if (CONDITION_NOT_CS) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbne(void) { if (CONDITION_NOT_NE) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbeq(void) { if (CONDITION_NOT_EQ) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbvc(void) { if (CONDITION_NOT_VC) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbvs(void) { if (CONDITION_NOT_VS) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbpl(void) { if (CONDITION_NOT_PL) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbmi(void) { if (CONDITION_NOT_MI) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbge(void) { if (CONDITION_NOT_GE) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dblt(void) { if (CONDITION_NOT_LT) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dbgt(void) { if (CONDITION_NOT_GT) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_dble(void) { if (CONDITION_NOT_LE) { uint *d_reg = &DY; uint res = MASK_OUT_ABOVE_16(*d_reg - 1); *d_reg = MASK_OUT_BELOW_16(*d_reg) | res; if (res != 0xffff) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_word(m68ki_read_16(CPU_PC)); USE_CLKS(10); return; } CPU_PC += 2; USE_CLKS(14); return; } CPU_PC += 2; USE_CLKS(12); } void m68000_divs_d_16(void) { uint *d_dst = &DX; int src = MAKE_INT_16(DY); CPU_C = 0; if (src != 0) { int quotient = MAKE_INT_32(*d_dst) / src; int remainder = MAKE_INT_32(*d_dst) % src; if (quotient == MAKE_INT_16(quotient)) { CPU_NOT_Z = quotient; CPU_N = GET_MSB_16(quotient); CPU_V = 0; *d_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); USE_CLKS(158); return; } CPU_V = 1; USE_CLKS(158); return; } m68ki_interrupt(EXCEPTION_ZERO_DIVIDE); } void m68000_divs_16(void) { uint *d_dst = &DX; int src = MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16())); CPU_C = 0; if (src != 0) { int quotient = MAKE_INT_32(*d_dst) / src; int remainder = MAKE_INT_32(*d_dst) % src; if (quotient == MAKE_INT_16(quotient)) { CPU_NOT_Z = quotient; CPU_N = GET_MSB_16(quotient); CPU_V = 0; *d_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); USE_CLKS(158); return; } CPU_V = 1; USE_CLKS(158); return; } m68ki_interrupt(EXCEPTION_ZERO_DIVIDE); } void m68000_divu_d_16(void) { uint *d_dst = &DX; uint src = MASK_OUT_ABOVE_16(DY); CPU_C = 0; if (src != 0) { uint quotient = *d_dst / src; uint remainder = *d_dst % src; if (MAKE_INT_32(quotient) == MAKE_INT_16(quotient)) { CPU_NOT_Z = quotient; CPU_N = GET_MSB_16(quotient); CPU_V = 0; *d_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); USE_CLKS(140); return; } CPU_V = 1; USE_CLKS(140); return; } m68ki_interrupt(EXCEPTION_ZERO_DIVIDE); } void m68000_divu_16(void) { uint *d_dst = &DX; uint src = m68ki_read_16(m68ki_get_ea_16()); CPU_C = 0; if (src != 0) { uint quotient = *d_dst / src; uint remainder = *d_dst % src; if (MAKE_INT_32(quotient) == MAKE_INT_16(quotient)) { CPU_NOT_Z = quotient; CPU_N = GET_MSB_16(quotient); CPU_V = 0; *d_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); USE_CLKS(140); return; } CPU_V = 1; USE_CLKS(140); return; } m68ki_interrupt(EXCEPTION_ZERO_DIVIDE); } void m68020_divl_d_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint divisor = DY; uint dividend_hi = CPU_D[word2 & 7]; uint dividend_lo = CPU_D[(word2 >> 12) & 7]; uint quotient = 0; uint remainder = 0; uint dividend_neg = 0; uint divisor_neg = 0; int i; if (divisor != 0) { /* quad / long : long quotient, long remainder */ if (BIT_A(word2)) { /* if dividing the upper long does not clear it, we're overflowing. */ if (dividend_hi / divisor) { CPU_V = 1; USE_CLKS(78); return; } if (BIT_B(word2)) /* signed */ { if (GET_MSB_32(dividend_hi)) { dividend_neg = 1; dividend_hi = MASK_OUT_ABOVE_32((-dividend_hi) - (dividend_lo != 0)); dividend_lo = MASK_OUT_ABOVE_32(-dividend_lo); } if (GET_MSB_32(divisor)) { divisor_neg = 1; divisor = MASK_OUT_ABOVE_32(-divisor); } } for (i = 31; i >= 0; i--) { quotient <<= 1; remainder = (remainder << 1) + ((dividend_hi >> i) & 1); if (remainder >= divisor) { remainder -= divisor; quotient++; } } for (i = 31; i >= 0; i--) { quotient <<= 1; remainder = (remainder << 1) + ((dividend_lo >> i) & 1); if (remainder >= divisor) { remainder -= divisor; quotient++; } } if (BIT_B(word2)) /* signed */ { if (dividend_neg) { remainder = MASK_OUT_ABOVE_32(-remainder); quotient = MASK_OUT_ABOVE_32(-quotient); } if (divisor_neg) quotient = MASK_OUT_ABOVE_32(-quotient); } CPU_D[word2 & 7] = remainder; CPU_D[(word2 >> 12) & 7] = quotient; CPU_N = GET_MSB_32(quotient); CPU_NOT_Z = quotient; CPU_V = 0; USE_CLKS(78); return; } /* long / long: long quotient, maybe long remainder */ CPU_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); CPU_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); CPU_N = GET_MSB_32(quotient); CPU_NOT_Z = quotient; CPU_V = 0; USE_CLKS(78); return; } m68ki_interrupt(EXCEPTION_ZERO_DIVIDE); return; } m68000_illegal(); } void m68020_divl_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint divisor = m68ki_read_32(m68ki_get_ea_32()); uint dividend_hi = CPU_D[word2 & 7]; uint dividend_lo = CPU_D[(word2 >> 12) & 7]; uint quotient = 0; uint remainder = 0; uint dividend_neg = 0; uint divisor_neg = 0; int i; if (divisor != 0) { /* quad / long : long quotient, long remainder */ if (BIT_A(word2)) { /* if dividing the upper long does not clear it, we're overflowing. */ if (dividend_hi / divisor) { CPU_V = 1; USE_CLKS(78); return; } if (BIT_B(word2)) /* signed */ { if (GET_MSB_32(dividend_hi)) { dividend_neg = 1; dividend_hi = MASK_OUT_ABOVE_32((-dividend_hi) - (dividend_lo != 0)); dividend_lo = MASK_OUT_ABOVE_32(-dividend_lo); } if (GET_MSB_32(divisor)) { divisor_neg = 1; divisor = MASK_OUT_ABOVE_32(-divisor); } } for (i = 31; i >= 0; i--) { quotient <<= 1; remainder = (remainder << 1) + ((dividend_hi >> i) & 1); if (remainder >= divisor) { remainder -= divisor; quotient++; } } for (i = 31; i >= 0; i--) { quotient <<= 1; remainder = (remainder << 1) + ((dividend_lo >> i) & 1); if (remainder >= divisor) { remainder -= divisor; quotient++; } } if (BIT_B(word2)) /* signed */ { if (dividend_neg) { remainder = MASK_OUT_ABOVE_32(-remainder); quotient = MASK_OUT_ABOVE_32(-quotient); } if (divisor_neg) quotient = MASK_OUT_ABOVE_32(-quotient); } CPU_D[word2 & 7] = remainder; CPU_D[(word2 >> 12) & 7] = quotient; CPU_N = GET_MSB_32(quotient); CPU_NOT_Z = quotient; CPU_V = 0; USE_CLKS(78); return; } /* long / long: long quotient, maybe long remainder */ CPU_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); CPU_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); CPU_N = GET_MSB_32(quotient); CPU_NOT_Z = quotient; CPU_V = 0; USE_CLKS(78); return; } m68ki_interrupt(EXCEPTION_ZERO_DIVIDE); return; } m68000_illegal(); } void m68000_eor_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_eor_8(void) { uint ea = m68ki_get_ea_8(); uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_eor_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_eor_16(void) { uint ea = m68ki_get_ea_16(); uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_eor_d_32(void) { uint res = DY ^= DX; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_eor_32(void) { uint ea = m68ki_get_ea_32(); uint res = DX ^ m68ki_read_32(ea); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_eori_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY ^= m68ki_read_imm_8()); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_eori_8(void) { uint tmp = m68ki_read_imm_8(); uint ea = m68ki_get_ea_8(); uint res = tmp ^ m68ki_read_8(ea); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_eori_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY ^= m68ki_read_imm_16()); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_eori_16(void) { uint tmp = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint res = tmp ^ m68ki_read_16(ea); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_eori_d_32(void) { uint res = DY ^= m68ki_read_imm_32(); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(16); } void m68000_eori_32(void) { uint tmp = m68ki_read_imm_32(); uint ea = m68ki_get_ea_32(); uint res = tmp ^ m68ki_read_32(ea); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(20); } void m68000_eori_to_ccr(void) { m68ki_set_ccr(m68ki_get_ccr() ^ m68ki_read_imm_16()); USE_CLKS(20); } void m68000_eori_to_sr(void) { uint eor_val = m68ki_read_imm_16(); if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_set_sr(m68ki_get_sr() ^ eor_val); USE_CLKS(20); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_exg_dd(void) { uint *reg_a = &DX; uint *reg_b = &DY; uint tmp = *reg_a; *reg_a = *reg_b; *reg_b = tmp; USE_CLKS(6); } void m68000_exg_aa(void) { uint *reg_a = &AX; uint *reg_b = &AY; uint tmp = *reg_a; *reg_a = *reg_b; *reg_b = tmp; USE_CLKS(6); } void m68000_exg_da(void) { uint *reg_a = &DX; uint *reg_b = &AY; uint tmp = *reg_a; *reg_a = *reg_b; *reg_b = tmp; USE_CLKS(6); } void m68000_ext_16(void) { uint *d_dst = &DY; *d_dst = MASK_OUT_BELOW_16(*d_dst) | MASK_OUT_ABOVE_8(*d_dst) | (GET_MSB_8(*d_dst) ? 0xff00 : 0); CPU_N = GET_MSB_16(*d_dst); CPU_NOT_Z = MASK_OUT_ABOVE_16(*d_dst); CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_ext_32(void) { uint *d_dst = &DY; *d_dst = MASK_OUT_ABOVE_16(*d_dst) | (GET_MSB_16(*d_dst) ? 0xffff0000 : 0); CPU_N = GET_MSB_32(*d_dst); CPU_NOT_Z = *d_dst; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68020_extb(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint *d_dst = &DY; *d_dst = MASK_OUT_ABOVE_8(*d_dst) | (GET_MSB_8(*d_dst) ? 0xffffff00 : 0); CPU_N = GET_MSB_32(*d_dst); CPU_NOT_Z = *d_dst; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68000_illegal(void) { m68ki_exception(EXCEPTION_ILLEGAL_INSTRUCTION); M68K_DO_LOG((M68K_LOG, "%s at %08x: illegal instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PPC), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PPC)))); #ifdef M68K_LOG /* I use this to get the proper offset when disassembling the offending instruction */ m68k_pc_offset = 2; #endif } void m68000_jmp(void) { m68ki_branch_long(m68ki_get_ea_32()); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(0); } void m68000_jsr(void) { uint ea = m68ki_get_ea_32(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_push_32(CPU_PC); m68ki_branch_long(ea); USE_CLKS(0); } void m68000_lea(void) { AX = m68ki_get_ea_32(); USE_CLKS(0); } void m68000_link_16_a7(void) { CPU_A[7] -= 4; m68ki_write_32(CPU_A[7], CPU_A[7]); CPU_A[7] = MASK_OUT_ABOVE_32(CPU_A[7] + MAKE_INT_16(m68ki_read_imm_16())); USE_CLKS(16); } void m68000_link_16(void) { uint *a_dst = &AY; m68ki_push_32(*a_dst); *a_dst = CPU_A[7]; CPU_A[7] = MASK_OUT_ABOVE_32(CPU_A[7] + MAKE_INT_16(m68ki_read_imm_16())); USE_CLKS(16); } void m68020_link_32_a7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { CPU_A[7] -= 4; m68ki_write_32(CPU_A[7], CPU_A[7]); CPU_A[7] = MASK_OUT_ABOVE_32(CPU_A[7] + m68ki_read_imm_32()); USE_CLKS(16); return; } m68000_illegal(); } void m68020_link_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint *a_dst = &AY; m68ki_push_32(*a_dst); *a_dst = CPU_A[7]; CPU_A[7] = MASK_OUT_ABOVE_32(CPU_A[7] + m68ki_read_imm_32()); USE_CLKS(16); return; } m68000_illegal(); } void m68000_lsr_s_8(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = src >> shift; *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = 0; CPU_NOT_Z = res; CPU_X = CPU_C = shift > 8 ? 0 : (src >> (shift - 1)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_lsr_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = src >> shift; *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = 0; CPU_NOT_Z = res; CPU_X = CPU_C = (src >> (shift - 1)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_lsr_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = *d_dst; uint res = src >> shift; *d_dst = res; CPU_N = 0; CPU_NOT_Z = res; CPU_X = CPU_C = (src >> (shift - 1)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 8); } void m68000_lsr_r_8(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = src >> shift; USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift <= 8) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_X = CPU_C = (src >> (shift - 1)) & 1; CPU_N = 0; CPU_NOT_Z = res; CPU_V = 0; return; } *d_dst &= 0xffffff00; CPU_X = CPU_C = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_lsr_r_16(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = src >> shift; USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift <= 16) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_X = CPU_C = (src >> (shift - 1)) & 1; CPU_N = 0; CPU_NOT_Z = res; CPU_V = 0; return; } *d_dst &= 0xffff0000; CPU_X = CPU_C = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_lsr_r_32(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = *d_dst; uint res = src >> shift; USE_CLKS((shift << 1) + 8); if (shift != 0) { if (shift < 32) { *d_dst = res; CPU_X = CPU_C = (src >> (shift - 1)) & 1; CPU_N = 0; CPU_NOT_Z = res; CPU_V = 0; return; } *d_dst = 0; CPU_X = CPU_C = (shift == 32 ? GET_MSB_32(src) : 0); CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_lsr_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint res = src >> 1; m68ki_write_16(ea, res); CPU_N = 0; CPU_NOT_Z = res; CPU_C = CPU_X = src & 1; CPU_V = 0; USE_CLKS(8); } void m68000_lsl_s_8(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = MASK_OUT_ABOVE_8(src << shift); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = shift > 8 ? 0 : (src >> (8 - shift)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_lsl_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = MASK_OUT_ABOVE_16(src << shift); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = (src >> (16 - shift)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_lsl_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = *d_dst; uint res = MASK_OUT_ABOVE_32(src << shift); *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = (src >> (32 - shift)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 8); } void m68000_lsl_r_8(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = MASK_OUT_ABOVE_8(src << shift); USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift <= 8) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_X = CPU_C = (src >> (8 - shift)) & 1; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; return; } *d_dst &= 0xffffff00; CPU_X = CPU_C = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_lsl_r_16(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = MASK_OUT_ABOVE_16(src << shift); USE_CLKS((shift << 1) + 6); if (shift != 0) { if (shift <= 16) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_X = CPU_C = (src >> (16 - shift)) & 1; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; return; } *d_dst &= 0xffff0000; CPU_X = CPU_C = 0; CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_lsl_r_32(void) { uint *d_dst = &DY; uint shift = DX & 0x3f; uint src = *d_dst; uint res = MASK_OUT_ABOVE_32(src << shift); USE_CLKS((shift << 1) + 8); if (shift != 0) { if (shift < 32) { *d_dst = res; CPU_X = CPU_C = (src >> (32 - shift)) & 1; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; return; } *d_dst = 0; CPU_X = CPU_C = (shift == 32 ? src & 1 : 0); CPU_N = 0; CPU_NOT_Z = 0; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_lsl_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(src << 1); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = GET_MSB_16(src); CPU_V = 0; USE_CLKS(8); } void m68000_move_dd_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint *d_dst = &DX; *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_dd_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint *d_dst = &DX; *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_ai_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = AX; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_ai_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = AX; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi7_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = (CPU_A[7] += 2) - 2; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = AX++; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi7_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = (CPU_A[7] += 2) - 2; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = AX++; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd7_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = CPU_A[7] -= 2; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = --AX; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd7_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = CPU_A[7] -= 2; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = --AX; m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_di_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_di_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_ix_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); m68ki_write_8(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(14); } void m68000_move_ix_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); m68ki_write_8(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(14); } void m68000_move_aw_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_aw_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_al_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); uint ea_dst = m68ki_read_imm_32(); m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_al_8(void) { uint res = m68ki_read_8(m68ki_get_ea_8()); uint ea_dst = m68ki_read_imm_32(); m68ki_write_8(ea_dst, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_dd_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint *d_dst = &DX; *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_dd_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint *d_dst = &DX; *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_dd_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint *d_dst = &DX; *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_ai_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint ea_dst = AX; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_ai_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint ea_dst = AX; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_ai_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint ea_dst = AX; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint ea_dst = (AX += 2) - 2; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint ea_dst = (AX += 2) - 2; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pi_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint ea_dst = (AX += 2) - 2; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint ea_dst = AX -= 2; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint ea_dst = AX -= 2; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_pd_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint ea_dst = AX -= 2; m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(8); } void m68000_move_di_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_di_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_di_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_ix_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); m68ki_write_16(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(14); } void m68000_move_ix_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); m68ki_write_16(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(14); } void m68000_move_ix_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); m68ki_write_16(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(14); } void m68000_move_aw_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_aw_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_aw_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_al_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); uint ea_dst = m68ki_read_imm_32(); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_al_a_16(void) { uint res = MASK_OUT_ABOVE_16(AY); uint ea_dst = m68ki_read_imm_32(); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_al_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); uint ea_dst = m68ki_read_imm_32(); m68ki_write_16(ea_dst, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_dd_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint *d_dst = &DX; *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_dd_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint *d_dst = &DX; *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_dd_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint *d_dst = &DX; *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_move_ai_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint ea_dst = AX; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_ai_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint ea_dst = AX; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_ai_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint ea_dst = AX; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_pi_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint ea_dst = (AX += 4) - 4; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_pi_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint ea_dst = (AX += 4) - 4; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_pi_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint ea_dst = (AX += 4) - 4; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_pd_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint ea_dst = AX -= 4; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_pd_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint ea_dst = AX -= 4; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_pd_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint ea_dst = AX -= 4; m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(12); } void m68000_move_di_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_di_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_di_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint ea_dst = AX + MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_ix_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); m68ki_write_32(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(18); } void m68000_move_ix_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); m68ki_write_32(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(18); } void m68000_move_ix_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); m68ki_write_32(m68ki_get_ea_ix_dst(), res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(18); } void m68000_move_aw_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_aw_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_aw_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint ea_dst = MAKE_INT_16(m68ki_read_imm_16()); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(16); } void m68000_move_al_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY); uint ea_dst = m68ki_read_imm_32(); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(20); } void m68000_move_al_a_32(void) { uint res = MASK_OUT_ABOVE_32(AY); uint ea_dst = m68ki_read_imm_32(); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(20); } void m68000_move_al_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); uint ea_dst = m68ki_read_imm_32(); m68ki_write_32(ea_dst, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(20); } void m68000_movea_d_16(void) { AX = MAKE_INT_16(DY); USE_CLKS(4); } void m68000_movea_a_16(void) { AX = MAKE_INT_16(AY); USE_CLKS(4); } void m68000_movea_16(void) { AX = MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16())); USE_CLKS(4); } void m68000_movea_d_32(void) { AX = MASK_OUT_ABOVE_32(DY); USE_CLKS(4); } void m68000_movea_a_32(void) { AX = MASK_OUT_ABOVE_32(AY); USE_CLKS(4); } void m68000_movea_32(void) { AX = m68ki_read_32(m68ki_get_ea_32()); USE_CLKS(4); } void m68010_move_fr_ccr_d(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); USE_CLKS(4); return; } m68000_illegal(); } void m68010_move_fr_ccr(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { m68ki_write_16(m68ki_get_ea_16(), m68ki_get_ccr()); USE_CLKS(8); return; } m68000_illegal(); } void m68000_move_to_ccr_d(void) { m68ki_set_ccr(DY); USE_CLKS(12); } void m68000_move_to_ccr(void) { m68ki_set_ccr(m68ki_read_16(m68ki_get_ea_16())); USE_CLKS(12); } void m68000_move_fr_sr_d(void) { if ((CPU_MODE & CPU_MODE_000) || CPU_S) /* NS990408 */ { DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); USE_CLKS(6); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_move_fr_sr(void) { uint ea = m68ki_get_ea_16(); if ((CPU_MODE & CPU_MODE_000) || CPU_S) /* NS990408 */ { m68ki_write_16(ea, m68ki_get_sr()); USE_CLKS(8); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_move_to_sr_d(void) { if (CPU_S) { m68ki_set_sr(DY); USE_CLKS(12); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_move_to_sr(void) { uint new_sr = m68ki_read_16(m68ki_get_ea_16()); if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_set_sr(new_sr); USE_CLKS(12); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_move_fr_usp(void) { if (CPU_S) { AY = CPU_USP; USE_CLKS(4); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_move_to_usp(void) { if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_USP = AY; USE_CLKS(4); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68010_movec_cr(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { if (CPU_S) { uint next_word = m68ki_read_imm_16(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(12); switch (next_word & 0xfff) { case 0x000: /* SFC */ m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] = CPU_SFC; return; case 0x001: /* DFC */ m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] = CPU_DFC; return; case 0x800: /* USP */ m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] = CPU_USP; return; case 0x801: /* VBR */ m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] = CPU_VBR; return; default: #ifdef M68K_LOG m68k_pc_offset = 4; #endif m68000_illegal(); return; } } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); return; } m68000_illegal(); } void m68010_movec_rc(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { if (CPU_S) { uint next_word = m68ki_read_imm_16(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(10); switch (next_word & 0xfff) { case 0x000: /* SFC */ CPU_SFC = m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] & 7; return; case 0x001: /* DFC */ CPU_DFC = m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] & 7; return; case 0x800: /* USP */ CPU_USP = m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7]; return; case 0x801: /* VBR */ CPU_VBR = m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7]; return; default: #ifdef M68K_LOG m68k_pc_offset = 4; #endif m68000_illegal(); return; } } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); return; } m68000_illegal(); } void m68000_movem_pd_16(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = AY; uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { ea -= 2; m68ki_write_16(ea, *(m68k_movem_pd_table[i])); count++; } AY = ea; USE_CLKS((count << 2) + 8); } void m68000_movem_pd_32(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = AY; uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { ea -= 4; m68ki_write_32(ea, *(m68k_movem_pd_table[i])); count++; } AY = ea; /* ASG: changed from (count << 4) to (count << 3) */ USE_CLKS((count << 3) + 8); } void m68000_movem_pi_16(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = AY; uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { *(m68k_movem_pi_table[i]) = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); ea += 2; count++; } AY = ea; USE_CLKS((count << 2) + 12); } void m68000_movem_pi_32(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = AY; uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { *(m68k_movem_pi_table[i]) = m68ki_read_32(ea); ea += 4; count++; } AY = ea; /* ASG: changed from (count << 4) to (count << 3) */ USE_CLKS((count << 3) + 12); } void m68000_movem_re_16(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { m68ki_write_16(ea, *(m68k_movem_pi_table[i])); ea += 2; count++; } USE_CLKS((count << 2) + 4); } void m68000_movem_re_32(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = m68ki_get_ea_32(); uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { m68ki_write_32(ea, *(m68k_movem_pi_table[i])); ea += 4; count++; } /* ASG: changed from (count << 4) to (count << 3) */ USE_CLKS((count << 3) + 4); } void m68000_movem_er_16(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { *(m68k_movem_pi_table[i]) = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(ea))); ea += 2; count++; } USE_CLKS((count << 2) + 8); } void m68000_movem_er_32(void) { uint i = 0; uint register_list = m68ki_read_imm_16(); uint ea = m68ki_get_ea_32(); uint count = 0; for (; i < 16; i++) if (register_list & (1 << i)) { *(m68k_movem_pi_table[i]) = m68ki_read_32(ea); ea += 4; count++; } /* ASG: changed from (count << 4) to (count << 3) */ USE_CLKS((count << 3) + 8); } void m68000_movep_re_16(void) { uint ea = AY + MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_imm_16())); uint src = DX; m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 8)); m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); USE_CLKS(16); } void m68000_movep_re_32(void) { uint ea = AY + MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_imm_16())); uint src = DX; m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); USE_CLKS(24); } void m68000_movep_er_16(void) { uint ea = AY + MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_imm_16())); uint *d_dst = &DX; *d_dst = MASK_OUT_BELOW_16(*d_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); USE_CLKS(16); } void m68000_movep_er_32(void) { uint ea = AY + MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_imm_16())); DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); USE_CLKS(24); } void m68010_moves_8(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { uint next_word = m68ki_read_imm_16(); uint ea = m68ki_get_ea_8(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(0); if (BIT_B(next_word)) /* Register to memory */ { m68ki_write_8_fc(ea, CPU_DFC, m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7]); return; } if (BIT_F(next_word)) /* Memory to address register */ { CPU_A[(next_word >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(ea, CPU_SFC)); return; } /* Memory to data register */ CPU_D[(next_word >> 12) & 7] = MASK_OUT_BELOW_8(CPU_D[(next_word >> 12) & 7]) | m68ki_read_8_fc(ea, CPU_SFC); return; } m68000_illegal(); } void m68010_moves_16(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { uint next_word = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(0); if (BIT_B(next_word)) /* Register to memory */ { m68ki_write_16_fc(ea, CPU_DFC, m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7]); return; } if (BIT_F(next_word)) /* Memory to address register */ { CPU_A[(next_word >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(ea, CPU_SFC)); return; } /* Memory to data register */ CPU_D[(next_word >> 12) & 7] = MASK_OUT_BELOW_16(CPU_D[(next_word >> 12) & 7]) | m68ki_read_16_fc(ea, CPU_SFC); return; } m68000_illegal(); } void m68010_moves_32(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { uint next_word = m68ki_read_imm_16(); uint ea = m68ki_get_ea_32(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(0); if (BIT_B(next_word)) /* Register to memory */ { m68ki_write_32_fc(ea, CPU_DFC, m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7]); return; } /* Memory to register */ m68k_cpu_dar[next_word >> 15][(next_word >> 12) & 7] = m68ki_read_32_fc(ea, CPU_SFC); return; } m68000_illegal(); } void m68000_moveq(void) { uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(CPU_IR)); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_muls_d_16(void) { uint *d_dst = &DX; uint res = MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*d_dst)); *d_dst = res; CPU_NOT_Z = res; CPU_N = GET_MSB_32(res); CPU_V = CPU_C = 0; USE_CLKS(54); } void m68000_muls_16(void) { uint *d_dst = &DX; uint res = MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16())) * MAKE_INT_16(MASK_OUT_ABOVE_16(*d_dst)); *d_dst = res; CPU_NOT_Z = res; CPU_N = GET_MSB_32(res); CPU_V = CPU_C = 0; USE_CLKS(54); } void m68000_mulu_d_16(void) { uint *d_dst = &DX; uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*d_dst); *d_dst = res; CPU_NOT_Z = res; CPU_N = GET_MSB_32(res); CPU_V = CPU_C = 0; USE_CLKS(54); } void m68000_mulu_16(void) { uint *d_dst = &DX; uint res = m68ki_read_16(m68ki_get_ea_16()) * MASK_OUT_ABOVE_16(*d_dst); *d_dst = res; CPU_NOT_Z = res; CPU_N = GET_MSB_32(res); CPU_V = CPU_C = 0; USE_CLKS(54); } void m68020_mull_d_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint src = DY; uint dst = CPU_D[(word2 >> 12) & 7]; uint neg = GET_MSB_32(src ^ dst); uint r1; uint r2; uint r3; uint lo; uint hi; if (BIT_B(word2)) /* signed */ { if (GET_MSB_32(src)) src = MASK_OUT_ABOVE_32(-src); if (GET_MSB_32(dst)) dst = MASK_OUT_ABOVE_32(-dst); } r1 = MASK_OUT_ABOVE_16(src) * MASK_OUT_ABOVE_16(dst); r2 = MASK_OUT_ABOVE_16(src >> 16) * MASK_OUT_ABOVE_16(dst); r3 = MASK_OUT_ABOVE_16(src) * MASK_OUT_ABOVE_16(dst >> 16); lo = r1 + MASK_OUT_BELOW_16(r2 << 16); hi = MASK_OUT_ABOVE_16(src >> 16) * MASK_OUT_ABOVE_16(dst >> 16) + (lo < r1); r1 = lo; lo = r1 + MASK_OUT_BELOW_16(r3 << 16); hi += (lo < r1) + MASK_OUT_ABOVE_16(r2 >> 16) + MASK_OUT_ABOVE_16(r3 >> 16); if (BIT_B(word2) && neg) { hi = MASK_OUT_ABOVE_32((-hi) - (lo != 0)); lo = MASK_OUT_ABOVE_32(-lo); } CPU_D[(word2 >> 12) & 7] = lo; if (BIT_A(word2)) { CPU_D[word2 & 7] = hi; CPU_N = GET_MSB_32(hi); CPU_NOT_Z = hi | lo; CPU_V = 0; USE_CLKS(43); return; } CPU_N = GET_MSB_32(lo); CPU_NOT_Z = lo; CPU_V = (GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi); USE_CLKS(43); return; } m68000_illegal(); } void m68020_mull_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint word2 = m68ki_read_imm_16(); uint src = m68ki_read_32(m68ki_get_ea_32()); uint dst = CPU_D[(word2 >> 12) & 7]; uint neg = GET_MSB_32(src ^ dst); uint r1; uint r2; uint r3; uint lo; uint hi; if (BIT_B(word2)) /* signed */ { if (GET_MSB_32(src)) src = MASK_OUT_ABOVE_32(-src); if (GET_MSB_32(dst)) dst = MASK_OUT_ABOVE_32(-dst); } r1 = MASK_OUT_ABOVE_16(src) * MASK_OUT_ABOVE_16(dst); r2 = MASK_OUT_ABOVE_16(src >> 16) * MASK_OUT_ABOVE_16(dst); r3 = MASK_OUT_ABOVE_16(src) * MASK_OUT_ABOVE_16(dst >> 16); lo = r1 + MASK_OUT_BELOW_16(r2 << 16); hi = MASK_OUT_ABOVE_16(src >> 16) * MASK_OUT_ABOVE_16(dst >> 16) + (lo < r1); r1 = lo; lo = r1 + MASK_OUT_BELOW_16(r3 << 16); hi += (lo < r1) + MASK_OUT_ABOVE_16(r2 >> 16) + MASK_OUT_ABOVE_16(r3 >> 16); if (BIT_B(word2) && neg) { hi = MASK_OUT_ABOVE_32((-hi) - (lo != 0)); lo = MASK_OUT_ABOVE_32(-lo); } CPU_D[(word2 >> 12) & 7] = lo; if (BIT_A(word2)) { CPU_D[word2 & 7] = hi; CPU_N = GET_MSB_32(hi); CPU_NOT_Z = hi | lo; CPU_V = 0; USE_CLKS(43); return; } CPU_N = GET_MSB_32(lo); CPU_NOT_Z = lo; CPU_V = (GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi); USE_CLKS(43); return; } m68000_illegal(); } void m68000_nbcd_d(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(0x9a - dst - (CPU_X != 0)); if (res != 0x9a) { if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; if (res != 0) CPU_NOT_Z = 1; CPU_C = CPU_X = 1; } else CPU_C = CPU_X = 0; USE_CLKS(6); } void m68000_nbcd(void) { uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(0x9a - dst - (CPU_X != 0)); if (res != 0x9a) { if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; m68ki_write_8(ea, res); if (res != 0) CPU_NOT_Z = 1; CPU_C = CPU_X = 1; } else CPU_C = CPU_X = 0; USE_CLKS(8); } void m68000_neg_d_8(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(-dst); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = GET_MSB_8(dst & res); CPU_C = CPU_X = res != 0; USE_CLKS(4); } void m68000_neg_8(void) { uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(-dst); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = GET_MSB_8(dst & res); CPU_C = CPU_X = res != 0; USE_CLKS(8); } void m68000_neg_d_16(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(-dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = GET_MSB_16(dst & res); CPU_C = CPU_X = res != 0; USE_CLKS(4); } void m68000_neg_16(void) { uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(-dst); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = GET_MSB_16(dst & res); CPU_C = CPU_X = res != 0; USE_CLKS(8); } void m68000_neg_d_32(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(-dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = GET_MSB_32(dst & res); CPU_C = CPU_X = res != 0; USE_CLKS(6); } void m68000_neg_32(void) { uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(-dst); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = GET_MSB_32(dst & res); CPU_C = CPU_X = res != 0; USE_CLKS(12); } void m68000_negx_d_8(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(-dst - (CPU_X != 0)); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = GET_MSB_8(dst & res); CPU_C = CPU_X = GET_MSB_8(dst | res); USE_CLKS(4); } void m68000_negx_8(void) { uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(-dst - (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = GET_MSB_8(dst & res); CPU_C = CPU_X = GET_MSB_8(dst | res); USE_CLKS(8); } void m68000_negx_d_16(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(-dst - (CPU_X != 0)); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = GET_MSB_16(dst & res); CPU_C = CPU_X = GET_MSB_16(dst | res); USE_CLKS(4); } void m68000_negx_16(void) { uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(-dst - (CPU_X != 0)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = GET_MSB_16(dst & res); CPU_C = CPU_X = GET_MSB_16(dst | res); USE_CLKS(8); } void m68000_negx_d_32(void) { uint *d_dst = &DY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(-dst - (CPU_X != 0)); CPU_N = GET_MSB_32(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = GET_MSB_32(dst & res); CPU_C = CPU_X = GET_MSB_32(dst | res); USE_CLKS(6); } void m68000_negx_32(void) { uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(-dst - (CPU_X != 0)); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); if (res != 0) CPU_NOT_Z = 1; CPU_V = GET_MSB_32(dst & res); CPU_C = CPU_X = GET_MSB_32(dst | res); USE_CLKS(12); } void m68000_nop(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(4); } void m68000_not_d_8(void) { uint *d_dst = &DY; uint res = MASK_OUT_ABOVE_8(~*d_dst); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_not_8(void) { uint ea = m68ki_get_ea_8(); uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_not_d_16(void) { uint *d_dst = &DY; uint res = MASK_OUT_ABOVE_16(~*d_dst); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_not_16(void) { uint ea = m68ki_get_ea_16(); uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_not_d_32(void) { uint *d_dst = &DY; uint res = *d_dst = MASK_OUT_ABOVE_32(~*d_dst); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(6); } void m68000_not_32(void) { uint ea = m68ki_get_ea_32(); uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_or_er_d_8(void) { uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_or_er_8(void) { uint res = MASK_OUT_ABOVE_8((DX |= m68ki_read_8(m68ki_get_ea_8()))); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_or_er_d_16(void) { uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_or_er_16(void) { uint res = MASK_OUT_ABOVE_16((DX |= m68ki_read_16(m68ki_get_ea_16()))); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_or_er_d_32(void) { uint res = MASK_OUT_ABOVE_32((DX |= DY)); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_or_er_32(void) { uint res = MASK_OUT_ABOVE_32((DX |= m68ki_read_32(m68ki_get_ea_32()))); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(6); } void m68000_or_re_8(void) { uint ea = m68ki_get_ea_8(); uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_or_re_16(void) { uint ea = m68ki_get_ea_16(); uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_or_re_32(void) { uint ea = m68ki_get_ea_32(); uint res = MASK_OUT_ABOVE_32(DX | m68ki_read_32(ea)); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_ori_d_8(void) { uint res = MASK_OUT_ABOVE_8((DY |= m68ki_read_imm_8())); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_ori_8(void) { uint tmp = m68ki_read_imm_8(); uint ea = m68ki_get_ea_8(); uint res = MASK_OUT_ABOVE_8(tmp | m68ki_read_8(ea)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_ori_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY |= m68ki_read_imm_16()); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(8); } void m68000_ori_16(void) { uint tmp = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint res = MASK_OUT_ABOVE_16(tmp | m68ki_read_16(ea)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(12); } void m68000_ori_d_32(void) { uint res = MASK_OUT_ABOVE_32(DY |= m68ki_read_imm_32()); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(16); } void m68000_ori_32(void) { uint tmp = m68ki_read_imm_32(); uint ea = m68ki_get_ea_32(); uint res = MASK_OUT_ABOVE_32(tmp | m68ki_read_32(ea)); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = CPU_V = 0; USE_CLKS(20); } void m68000_ori_to_ccr(void) { m68ki_set_ccr(m68ki_get_ccr() | m68ki_read_imm_16()); USE_CLKS(20); } void m68000_ori_to_sr(void) { uint or_val = m68ki_read_imm_16(); if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_set_sr(m68ki_get_sr() | or_val); USE_CLKS(20); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68020_pack_rr(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = DX + m68ki_read_imm_16(); DY = MASK_OUT_BELOW_8(DY) | ((src >> 4) & 0x00f0) | (src & 0x000f); USE_CLKS(6); return; } m68000_illegal(); } void m68020_pack_mm_ax7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_16(AX -= 2); src = (((src >> 8) & 0x00ff) | ((src << 8) & 0xff00)) + m68ki_read_imm_16(); m68ki_write_8(CPU_A[7] -= 2, ((src >> 4) & 0xf0) | (src & 0x0f)); USE_CLKS(13); return; } m68000_illegal(); } void m68020_pack_mm_ay7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_32(CPU_A[7] -= 4); src = (((src >> 16) & 0x00ff) | ((src << 8) & 0xff00)) + m68ki_read_imm_16(); /* I hate the way Motorola changes where Rx and Ry are */ m68ki_write_8(--AY, ((src >> 4) & 0xf0) | (src & 0x0f)); USE_CLKS(13); return; } m68000_illegal(); } void m68020_pack_mm_axy7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_32(CPU_A[7] -= 4); src = (((src >> 16) & 0x00ff) | ((src << 8) & 0xff00)) + m68ki_read_imm_16(); m68ki_write_8(CPU_A[7] -= 2, ((src >> 4) & 0xf0) | (src & 0x0f)); USE_CLKS(13); return; } m68000_illegal(); } void m68020_pack_mm(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_16(AX -= 2); src = (((src >> 8) & 0x00ff) | ((src << 8) & 0xff00)) + m68ki_read_imm_16(); m68ki_write_8(--AY, ((src >> 4) & 0xf0) | (src & 0x0f)); USE_CLKS(13); return; } m68000_illegal(); } void m68000_pea(void) { uint ea = m68ki_get_ea_32(); m68ki_push_32(ea); USE_CLKS(0); } void m68000_rst(void) { if (CPU_S) { m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ USE_CLKS(132); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_ror_s_8(void) { uint *d_dst = &DY; uint orig_shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint shift = orig_shift & 7; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = ROR_8(src, shift); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = (src >> ((shift - 1) & 7)) & 1; CPU_V = 0; USE_CLKS((orig_shift << 1) + 6); } void m68000_ror_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = ROR_16(src, shift); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = (src >> (shift - 1)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_ror_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = ROR_32(src, shift); *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = (src >> (shift - 1)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 8); } void m68000_ror_r_8(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift & 7; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = ROR_8(src, shift); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_C = (src >> ((shift - 1) & 7)) & 1; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_ror_r_16(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift & 15; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = ROR_16(src, shift); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_C = (src >> ((shift - 1) & 15)) & 1; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_ror_r_32(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift & 31; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = ROR_32(src, shift); USE_CLKS((orig_shift << 1) + 8); if (orig_shift != 0) { *d_dst = res; CPU_C = (src >> ((shift - 1) & 31)) & 1; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_ror_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint res = ROR_16(src, 1); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = src & 1; CPU_V = 0; USE_CLKS(8); } void m68000_rol_s_8(void) { uint *d_dst = &DY; uint orig_shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint shift = orig_shift & 7; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = MASK_OUT_ABOVE_8(ROL_8(src, shift)); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = (src >> (8 - orig_shift)) & 1; CPU_V = 0; USE_CLKS((orig_shift << 1) + 6); } void m68000_rol_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = MASK_OUT_ABOVE_16(ROL_16(src, shift)); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = (src >> (16 - shift)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_rol_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = MASK_OUT_ABOVE_32(ROL_32(src, shift)); *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_C = (src >> (32 - shift)) & 1; CPU_V = 0; USE_CLKS((shift << 1) + 8); } void m68000_rol_r_8(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift & 7; uint src = MASK_OUT_ABOVE_8(*d_dst); uint res = MASK_OUT_ABOVE_8(ROL_8(src, shift)); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { if (shift != 0) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_C = (src >> (8 - shift)) & 1; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = src & 1; CPU_N = GET_MSB_8(src); CPU_NOT_Z = src; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_rol_r_16(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift & 15; uint src = MASK_OUT_ABOVE_16(*d_dst); uint res = MASK_OUT_ABOVE_16(ROL_16(src, shift)); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { if (shift != 0) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_C = (src >> (16 - shift)) & 1; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = src & 1; CPU_N = GET_MSB_16(src); CPU_NOT_Z = src; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_rol_r_32(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift & 31; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = MASK_OUT_ABOVE_32(ROL_32(src, shift)); USE_CLKS((orig_shift << 1) + 8); if (orig_shift != 0) { *d_dst = res; CPU_C = (src >> (32 - shift)) & 1; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = 0; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_rol_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = GET_MSB_16(src); CPU_V = 0; USE_CLKS(8); } void m68000_roxr_s_8(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_8(*d_dst); uint tmp = ROR_9(src | ((CPU_X != 0) << 8), shift); uint res = MASK_OUT_ABOVE_8(tmp); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_X = GET_MSB_9(tmp); CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_roxr_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint tmp = ROR_17(src | ((CPU_X != 0) << 16), shift); uint res = MASK_OUT_ABOVE_16(tmp); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_X = GET_MSB_17(tmp); CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_roxr_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | ((CPU_X != 0) << (32 - shift))); uint new_x_flag = src & (1 << (shift - 1)); *d_dst = res; CPU_C = CPU_X = new_x_flag; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; USE_CLKS((shift << 1) + 8); } void m68000_roxr_r_8(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift % 9; uint src = MASK_OUT_ABOVE_8(*d_dst); uint tmp = ROR_9(src | ((CPU_X != 0) << 8), shift); uint res = MASK_OUT_ABOVE_8(tmp); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_C = CPU_X = GET_MSB_9(tmp); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = CPU_X; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_roxr_r_16(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift % 17; uint src = MASK_OUT_ABOVE_16(*d_dst); uint tmp = ROR_17(src | ((CPU_X != 0) << 16), shift); uint res = MASK_OUT_ABOVE_16(tmp); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_C = CPU_X = GET_MSB_17(tmp); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = CPU_X; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_roxr_r_32(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift % 33; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | ((CPU_X != 0) << (32 - shift))); uint new_x_flag = src & (1 << (shift - 1)); USE_CLKS((orig_shift << 1) + 8); if (shift != 0) { *d_dst = res; CPU_X = new_x_flag; } else res = src; CPU_C = CPU_X; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_roxr_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint tmp = ROR_17(src | ((CPU_X != 0) << 16), 1); uint res = MASK_OUT_ABOVE_16(tmp); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_X = GET_MSB_17(tmp); CPU_V = 0; USE_CLKS(8); } void m68000_roxl_s_8(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_8(*d_dst); uint tmp = ROL_9(src | ((CPU_X != 0) << 8), shift); uint res = MASK_OUT_ABOVE_8(tmp); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_C = CPU_X = GET_MSB_9(tmp); CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_roxl_s_16(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_16(*d_dst); uint tmp = ROL_17(src | ((CPU_X != 0) << 16), shift); uint res = MASK_OUT_ABOVE_16(tmp); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_X = GET_MSB_17(tmp); CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_roxl_s_32(void) { uint *d_dst = &DY; uint shift = (((CPU_IR >> 9) - 1) & 7) + 1; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | ((CPU_X != 0) << (shift - 1))); uint new_x_flag = src & (1 << (32 - shift)); *d_dst = res; CPU_C = CPU_X = new_x_flag; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; USE_CLKS((shift << 1) + 6); } void m68000_roxl_r_8(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift % 9; uint src = MASK_OUT_ABOVE_8(*d_dst); uint tmp = ROL_9(src | ((CPU_X != 0) << 8), shift); uint res = MASK_OUT_ABOVE_8(tmp); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_C = CPU_X = GET_MSB_9(tmp); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = CPU_X; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_roxl_r_16(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift % 17; uint src = MASK_OUT_ABOVE_16(*d_dst); uint tmp = ROL_17(src | ((CPU_X != 0) << 16), shift); uint res = MASK_OUT_ABOVE_16(tmp); USE_CLKS((orig_shift << 1) + 6); if (orig_shift != 0) { *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_C = CPU_X = GET_MSB_17(tmp); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; return; } CPU_C = CPU_X; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_roxl_r_32(void) { uint *d_dst = &DY; uint orig_shift = DX & 0x3f; uint shift = orig_shift % 33; uint src = MASK_OUT_ABOVE_32(*d_dst); uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | ((CPU_X != 0) << (shift - 1))); uint new_x_flag = src & (1 << (32 - shift)); USE_CLKS((orig_shift << 1) + 8); if (shift != 0) { *d_dst = res; CPU_X = new_x_flag; } else res = src; CPU_C = CPU_X; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = 0; } void m68000_roxl_ea(void) { uint ea = m68ki_get_ea_16(); uint src = m68ki_read_16(ea); uint tmp = ROL_17(src | ((CPU_X != 0) << 16), 1); uint res = MASK_OUT_ABOVE_16(tmp); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_C = CPU_X = GET_MSB_17(tmp); CPU_V = 0; USE_CLKS(8); } void m68010_rtd(void) { if (CPU_MODE & CPU_MODE_010_PLUS) { uint new_pc = m68ki_pull_32(); m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_A[7] += MAKE_INT_16(m68ki_read_imm_16()); m68ki_branch_long(new_pc); USE_CLKS(16); return; } m68000_illegal(); } void m68000_rte(void) { uint new_sr; uint new_pc; uint format_word; if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ new_sr = m68ki_pull_16(); new_pc = m68ki_pull_32(); m68ki_branch_long(new_pc); m68ki_set_sr(new_sr); if (!(CPU_MODE & CPU_MODE_010_PLUS)) { USE_CLKS(20); return; } format_word = (m68ki_pull_16() >> 12) & 0xf; /* I'm ignoring code 8 (bus error and address error) */ if (format_word != 0) /* Generate a new program counter from the format error vector */ m68ki_set_pc(m68ki_read_32((EXCEPTION_FORMAT_ERROR<<2)+CPU_VBR)); USE_CLKS(20); return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68020_rtm(void) { if (CPU_MODE & CPU_MODE_020) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ M68K_DO_LOG((M68K_LOG, "%s at %08x: called unimplemented instruction %04x (%s)\n", m68k_cpu_names[CPU_MODE], ADDRESS_68K(CPU_PC - 2), CPU_IR, m68k_disassemble_quick(ADDRESS_68K(CPU_PC - 2)))); USE_CLKS(19); return; } m68000_illegal(); } void m68000_rtr(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_set_ccr(m68ki_pull_16()); m68ki_branch_long(m68ki_pull_32()); USE_CLKS(20); } void m68000_rts(void) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_branch_long(m68ki_pull_32()); USE_CLKS(16); } void m68000_sbcd_rr(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - (CPU_X != 0); if (res > 9) res -= 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); if ((CPU_X = CPU_C = res > 0x99) != 0) res += 0xa0; *d_dst = MASK_OUT_BELOW_8(*d_dst) | MASK_OUT_ABOVE_8(res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(6); } void m68000_sbcd_mm_ax7(void) { uint src = m68ki_read_8(--(AY)); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - (CPU_X != 0); if (res > 9) res -= 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); if ((CPU_X = CPU_C = res > 0x99) != 0) res += 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_sbcd_mm_ay7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - (CPU_X != 0); if (res > 9) res -= 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); if ((CPU_X = CPU_C = res > 0x99) != 0) res += 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_sbcd_mm_axy7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - (CPU_X != 0); if (res > 9) res -= 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); if ((CPU_X = CPU_C = res > 0x99) != 0) res += 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_sbcd_mm(void) { uint src = m68ki_read_8(--AY); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - (CPU_X != 0); if (res > 9) res -= 6; res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); if ((CPU_X = CPU_C = res > 0x99) != 0) res += 0xa0; m68ki_write_8(ea, res); if (MASK_OUT_ABOVE_8(res) != 0) CPU_NOT_Z = 1; USE_CLKS(18); } void m68000_st_d(void) { DY |= 0xff; USE_CLKS(6); } void m68000_st(void) { m68ki_write_8(m68ki_get_ea_8(), 0xff); USE_CLKS(8); } void m68000_sf_d(void) { DY &= 0xffffff00; USE_CLKS(4); } void m68000_sf(void) { m68ki_write_8(m68ki_get_ea_8(), 0); USE_CLKS(8); } void m68000_shi_d(void) { if (CONDITION_HI) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_shi(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_HI ? 0xff : 0); USE_CLKS(8); } void m68000_sls_d(void) { if (CONDITION_LS) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_sls(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_LS ? 0xff : 0); USE_CLKS(8); } void m68000_scc_d(void) { if (CONDITION_CC) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_scc(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_CC ? 0xff : 0); USE_CLKS(8); } void m68000_scs_d(void) { if (CONDITION_CS) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_scs(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_CS ? 0xff : 0); USE_CLKS(8); } void m68000_sne_d(void) { if (CONDITION_NE) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_sne(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_NE ? 0xff : 0); USE_CLKS(8); } void m68000_seq_d(void) { if (CONDITION_EQ) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_seq(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_EQ ? 0xff : 0); USE_CLKS(8); } void m68000_svc_d(void) { if (CONDITION_VC) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_svc(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_VC ? 0xff : 0); USE_CLKS(8); } void m68000_svs_d(void) { if (CONDITION_VS) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_svs(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_VS ? 0xff : 0); USE_CLKS(8); } void m68000_spl_d(void) { if (CONDITION_PL) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_spl(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_PL ? 0xff : 0); USE_CLKS(8); } void m68000_smi_d(void) { if (CONDITION_MI) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_smi(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_MI ? 0xff : 0); USE_CLKS(8); } void m68000_sge_d(void) { if (CONDITION_GE) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_sge(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_GE ? 0xff : 0); USE_CLKS(8); } void m68000_slt_d(void) { if (CONDITION_LT) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_slt(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_LT ? 0xff : 0); USE_CLKS(8); } void m68000_sgt_d(void) { if (CONDITION_GT) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_sgt(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_GT ? 0xff : 0); USE_CLKS(8); } void m68000_sle_d(void) { if (CONDITION_LE) { DY |= 0xff; USE_CLKS(6); return; } DY &= 0xffffff00; USE_CLKS(4); } void m68000_sle(void) { m68ki_write_8(m68ki_get_ea_8(), CONDITION_LE ? 0xff : 0); USE_CLKS(8); } void m68000_stop(void) { uint new_sr = m68ki_read_imm_16(); if (CPU_S) { m68ki_add_trace(); /* auto-disable (see m68kcpu.h) */ CPU_STOPPED = 1; m68ki_set_sr(new_sr); m68k_clks_left = 0; return; } m68ki_exception(EXCEPTION_PRIVILEGE_VIOLATION); } void m68000_sub_er_d_8(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(dst - src); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(4); } void m68000_sub_er_8(void) { uint *d_dst = &DX; uint src = m68ki_read_8(m68ki_get_ea_8()); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(dst - src); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(4); } void m68000_sub_er_d_16(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(dst - src); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_sub_er_a_16(void) { uint *d_dst = &DX; uint src = AY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(dst - src); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_sub_er_16(void) { uint *d_dst = &DX; uint src = m68ki_read_16(m68ki_get_ea_16()); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(dst - src); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_sub_er_d_32(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(8); } void m68000_sub_er_a_32(void) { uint *d_dst = &DX; uint src = AY; uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(8); } void m68000_sub_er_32(void) { uint *d_dst = &DX; uint src = m68ki_read_32(m68ki_get_ea_32()); uint dst = *d_dst; uint res = *d_dst = MASK_OUT_ABOVE_32(dst - src); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(6); } void m68000_sub_re_8(void) { uint ea = m68ki_get_ea_8(); uint src = DX; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(8); } void m68000_sub_re_16(void) { uint ea = m68ki_get_ea_16(); uint src = DX; uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(dst - src); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(8); } void m68000_sub_re_32(void) { uint ea = m68ki_get_ea_32(); uint src = DX; uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(dst - src); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(12); } void m68000_suba_d_16(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst - MAKE_INT_16(DY)); USE_CLKS(8); } void m68000_suba_a_16(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst - MAKE_INT_16(AY)); USE_CLKS(8); } void m68000_suba_16(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst - MAKE_INT_16(m68ki_read_16(m68ki_get_ea_16()))); USE_CLKS(8); } void m68000_suba_d_32(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst - DY); USE_CLKS(8); } void m68000_suba_a_32(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst - AY); USE_CLKS(8); } void m68000_suba_32(void) { uint *a_dst = &AX; *a_dst = MASK_OUT_ABOVE_32(*a_dst - m68ki_read_32(m68ki_get_ea_32())); USE_CLKS(6); } void m68000_subi_d_8(void) { uint *d_dst = &DY; uint src = m68ki_read_imm_8(); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(dst - src); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(8); } void m68000_subi_8(void) { uint src = m68ki_read_imm_8(); uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(12); } void m68000_subi_d_16(void) { uint *d_dst = &DY; uint src = m68ki_read_imm_16(); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(dst - src); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(8); } void m68000_subi_16(void) { uint src = m68ki_read_imm_16(); uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(dst - src); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(12); } void m68000_subi_d_32(void) { uint *d_dst = &DY; uint src = m68ki_read_imm_32(); uint dst = *d_dst; uint res = MASK_OUT_ABOVE_32(dst - src); *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(16); } void m68000_subi_32(void) { uint src = m68ki_read_imm_32(); uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(dst - src); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(20); } void m68000_subq_d_8(void) { uint *d_dst = &DY; uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(dst - src); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(4); } void m68000_subq_8(void) { uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(8); } void m68000_subq_d_16(void) { uint *d_dst = &DY; uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(dst - src); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_subq_a_16(void) { uint *a_dst = &AY; *a_dst = MASK_OUT_ABOVE_32(*a_dst - ((((CPU_IR >> 9) - 1) & 7) + 1)); USE_CLKS(8); } void m68000_subq_16(void) { uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint ea = m68ki_get_ea_16(); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(dst - src); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(8); } void m68000_subq_d_32(void) { uint *d_dst = &DY; uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_32(dst - src); *d_dst = res; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(8); } void m68000_subq_a_32(void) { uint *a_dst = &AY; *a_dst = MASK_OUT_ABOVE_32(*a_dst - ((((CPU_IR >> 9) - 1) & 7) + 1)); USE_CLKS(8); } void m68000_subq_32(void) { uint src = (((CPU_IR >> 9) - 1) & 7) + 1; uint ea = m68ki_get_ea_32(); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(dst - src); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(12); } void m68000_subx_rr_8(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_8(dst - src - (CPU_X != 0)); *d_dst = MASK_OUT_BELOW_8(*d_dst) | res; CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(4); } void m68000_subx_rr_16(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_16(dst - src - (CPU_X != 0)); *d_dst = MASK_OUT_BELOW_16(*d_dst) | res; CPU_N = GET_MSB_16(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(4); } void m68000_subx_rr_32(void) { uint *d_dst = &DX; uint src = DY; uint dst = *d_dst; uint res = MASK_OUT_ABOVE_32(dst - src - (CPU_X != 0)); *d_dst = res; CPU_N = GET_MSB_32(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(8); } void m68000_subx_mm_8_ax7(void) { uint src = m68ki_read_8(--AY); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src - (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(18); } void m68000_subx_mm_8_ay7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = --AX; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src - (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(18); } void m68000_subx_mm_8_axy7(void) { uint src = m68ki_read_8(CPU_A[7] -= 2); uint ea = CPU_A[7] -= 2; uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src - (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(18); } void m68000_subx_mm_8(void) { uint src = m68ki_read_8(--(AY)); uint ea = --(AX); uint dst = m68ki_read_8(ea); uint res = MASK_OUT_ABOVE_8(dst - src - (CPU_X != 0)); m68ki_write_8(ea, res); CPU_N = GET_MSB_8(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_8(src, dst, res); CPU_V = VFLAG_SUB_8(src, dst, res); USE_CLKS(18); } void m68000_subx_mm_16(void) { uint src = m68ki_read_16(AY -= 2); uint ea = (AX -= 2); uint dst = m68ki_read_16(ea); uint res = MASK_OUT_ABOVE_16(dst - src - (CPU_X != 0)); m68ki_write_16(ea, res); CPU_N = GET_MSB_16(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_16(src, dst, res); CPU_V = VFLAG_SUB_16(src, dst, res); USE_CLKS(18); } void m68000_subx_mm_32(void) { uint src = m68ki_read_32(AY -= 4); uint ea = (AX -= 4); uint dst = m68ki_read_32(ea); uint res = MASK_OUT_ABOVE_32(dst - src - (CPU_X != 0)); m68ki_write_32(ea, res); CPU_N = GET_MSB_32(res); if (res != 0) CPU_NOT_Z = 1; CPU_X = CPU_C = CFLAG_SUB_32(src, dst, res); CPU_V = VFLAG_SUB_32(src, dst, res); USE_CLKS(30); } void m68000_swap(void) { uint *d_dst = &DY; *d_dst ^= (*d_dst >> 16) & 0x0000ffff; *d_dst ^= (*d_dst << 16) & 0xffff0000; *d_dst ^= (*d_dst >> 16) & 0x0000ffff; CPU_N = GET_MSB_32(*d_dst); CPU_NOT_Z = *d_dst; CPU_C = CPU_V = 0; USE_CLKS(4); } void m68000_tas_d(void) { uint *d_dst = &DY; CPU_NOT_Z = MASK_OUT_ABOVE_8(*d_dst); CPU_N = GET_MSB_8(*d_dst); CPU_V = CPU_C = 0; *d_dst |= 0x80; USE_CLKS(4); } void m68000_tas(void) { uint ea = m68ki_get_ea_8(); uint dst = m68ki_read_8(ea); CPU_NOT_Z = dst; CPU_N = GET_MSB_8(dst); CPU_V = CPU_C = 0; m68ki_write_8(ea, dst | 0x80); USE_CLKS(14); } void m68000_trap(void) { m68ki_interrupt(EXCEPTION_TRAP_BASE + (CPU_IR & 0xf)); /* HJB 990403 */ } void m68020_trapt_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ return; } m68000_illegal(); } void m68020_trapt_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ return; } m68000_illegal(); } void m68020_trapt_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ return; } m68000_illegal(); } void m68020_trapf_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapf_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapf_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_traphi_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_HI) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_traphi_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_HI) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_traphi_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_HI) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapls_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapls_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapls_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapcc_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CC) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapcc_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CC) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapcc_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CC) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapcs_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapcs_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapcs_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_CS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapne_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_NE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapne_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_NE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapne_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_NE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapeq_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_EQ) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapeq_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_EQ) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapeq_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_EQ) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapvc_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VC) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapvc_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VC) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapvc_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VC) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapvs_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapvs_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapvs_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_VS) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trappl_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_PL) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trappl_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_PL) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trappl_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_PL) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapmi_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_MI) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapmi_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_MI) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapmi_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_MI) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapge_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapge_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapge_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_traplt_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LT) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_traplt_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LT) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_traplt_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LT) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_trapgt_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GT) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_trapgt_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GT) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_trapgt_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_GT) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68020_traple_0(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(4); return; } m68000_illegal(); } void m68020_traple_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(6); CPU_PC += 2; return; } m68000_illegal(); } void m68020_traple_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { if (CONDITION_LE) m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ else USE_CLKS(8); CPU_PC += 4; return; } m68000_illegal(); } void m68000_trapv(void) { if (!CPU_V) { USE_CLKS(4); return; } m68ki_interrupt(EXCEPTION_TRAPV); /* HJB 990403 */ } void m68000_tst_d_8(void) { uint res = MASK_OUT_ABOVE_8(DY); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68000_tst_8(void) { uint ea = m68ki_get_ea_8(); uint res = m68ki_read_8(ea); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68020_tst_pcdi_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint old_pc = (CPU_PC += 2) - 2; uint ea = old_pc + MAKE_INT_16(m68ki_read_16(old_pc)); uint res = m68ki_read_8(ea); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68020_tst_pcix_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = m68ki_read_8(EA_PCIX); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68020_tst_imm_8(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = m68ki_read_imm_8(); CPU_N = GET_MSB_8(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68000_tst_d_16(void) { uint res = MASK_OUT_ABOVE_16(DY); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68020_tst_a_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = MASK_OUT_ABOVE_16(AY); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68000_tst_16(void) { uint res = m68ki_read_16(m68ki_get_ea_16()); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68020_tst_pcdi_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint old_pc = (CPU_PC += 2) - 2; uint ea = old_pc + MAKE_INT_16(m68ki_read_16(old_pc)); uint res = m68ki_read_16(ea); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68020_tst_pcix_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = m68ki_read_16(EA_PCIX); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68020_tst_imm_16(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = m68ki_read_imm_16(); CPU_N = GET_MSB_16(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68000_tst_d_32(void) { uint res = DY; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68020_tst_a_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = AY; CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68000_tst_32(void) { uint res = m68ki_read_32(m68ki_get_ea_32()); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); } void m68020_tst_pcdi_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint old_pc = (CPU_PC += 2) - 2; uint ea = old_pc + MAKE_INT_16(m68ki_read_16(old_pc)); uint res = m68ki_read_32(ea); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68020_tst_pcix_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = m68ki_read_32(EA_PCIX); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68020_tst_imm_32(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint res = m68ki_read_imm_32(); CPU_N = GET_MSB_32(res); CPU_NOT_Z = res; CPU_V = CPU_C = 0; USE_CLKS(4); return; } m68000_illegal(); } void m68000_unlk_a7(void) { CPU_A[7] = m68ki_read_32(CPU_A[7]); USE_CLKS(12); } void m68000_unlk(void) { uint *a_dst = &AY; CPU_A[7] = *a_dst; *a_dst = m68ki_pull_32(); USE_CLKS(12); } void m68020_unpk_rr(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = DX; DY = MASK_OUT_BELOW_16(DY) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + m68ki_read_imm_16()) & 0xffff); USE_CLKS(8); return; } m68000_illegal(); } void m68020_unpk_mm_ax7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_8(--AX); src = (((src << 4) & 0x0f00) | (src & 0x000f)) + m68ki_read_imm_16(); m68ki_write_8(CPU_A[7] -= 2, (src >> 8) & 0xff); m68ki_write_8(CPU_A[7] -= 2, src & 0xff); USE_CLKS(13); return; } m68000_illegal(); } void m68020_unpk_mm_ay7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_8(CPU_A[7] -= 2); src = (((src << 4) & 0x0f00) | (src & 0x000f)) + m68ki_read_imm_16(); m68ki_write_8(--AY, (src >> 8) & 0xff); m68ki_write_8(--AY, src & 0xff); USE_CLKS(13); return; } m68000_illegal(); } void m68020_unpk_mm_axy7(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_8(CPU_A[7] -= 2); src = (((src << 4) & 0x0f00) | (src & 0x000f)) + m68ki_read_imm_16(); m68ki_write_8(CPU_A[7] -= 2, (src >> 8) & 0xff); m68ki_write_8(CPU_A[7] -= 2, src & 0xff); USE_CLKS(13); return; } m68000_illegal(); } void m68020_unpk_mm(void) { if (CPU_MODE & CPU_MODE_020_PLUS) { uint src = m68ki_read_8(--AX); src = (((src << 4) & 0x0f00) | (src & 0x000f)) + m68ki_read_imm_16(); m68ki_write_8(--AY, (src >> 8) & 0xff); m68ki_write_8(--AY, src & 0xff); USE_CLKS(13); return; } m68000_illegal(); } dgen-sdl-1.23/musa/m68kmake.c 644 1750 1750 253440 7027317557 11076 #include #include #include #include int atoh(char* buff); char* modify_ea_string(char* old_ea_string, char* insert_string); char* modify_imm_string(char* old_ea_string, char* insert_string); char* replace_clk_string(char* old_clk_string, char* replace_string, int add_value); int get_clk_add(int func_num, int ea_mode); void add_op_header(FILE* filep, char low, char high); void add_prototype_header(FILE* filep); void add_prototype_footer(FILE* filep); void add_table_header(FILE* filep); void add_table_footer(FILE* filep); int generate_funcs(FILE* file_ac, FILE* file_dm, FILE* file_nz); int generate_table(FILE* table_file); int generate_prototypes(FILE* prototype_file); #define PRINT_TABLE_ENTRY(file, name, mask, match, clks) \ { \ unsigned bits = mask; \ bits = ((bits & 0xaaaa) >> 1) + (bits & 0x5555); \ bits = ((bits & 0xcccc) >> 2) + (bits & 0x3333); \ bits = ((bits & 0xf0f0) >> 4) + (bits & 0x0f0f); \ bits = ((bits & 0xff00) >> 8) + (bits & 0x00ff); \ fprintf(file, "\t{%-24s, %2d, 0x%04x, 0x%04x},\n", name, bits, mask, match); \ } #define PRINT_PROTOTYPE(file, name) fprintf(file, "void %s(void);\n", name) typedef struct { char* name; /* handler function */ int op_mask; /* mask on opcode */ int op_match; /* what to match after masking */ int ea_mask; /* what ea modes are allowed */ int size; /* operation size (0=8, 1=16, 2=32, 3=unsized) */ int base_cycles; /* base cycles used on real 68000 (-1 = special) */ } opcode_handler_struct; int g_errors = 0; char g_m68k_in_c[255+1] = "m68k_in.c"; int g_ea_8_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 4, 4, 4, 4, 4, 4, 4, 4, /* 010 xxx address register indirect */ 4, 4, 4, 4, 4, 4, 4, 4, /* 011 xxx address register indirect with postincrement */ 6, 6, 6, 6, 6, 6, 6, 6, /* 100 xxx address register indirect with predecrement */ 8, 8, 8, 8, 8, 8, 8, 8, /* 101 xxx address register indirect with displacement */ 10, 10, 10, 10, 10, 10, 10, 10, /* 110 xxx address register indirect with index */ 8, /* 111 000 absolute short */ 12, /* 111 001 absolute long */ 8, /* 111 010 program counter with displacement */ 10, /* 111 011 program counter with index */ 4, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int g_ea_32_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 8, 8, 8, 8, 8, 8, 8, 8, /* 010 xxx address register indirect */ 8, 8, 8, 8, 8, 8, 8, 8, /* 011 xxx address register indirect with postincrement */ 10, 10, 10, 10, 10, 10, 10, 10, /* 100 xxx address register indirect with predecrement */ 12, 12, 12, 12, 12, 12, 12, 12, /* 101 xxx address register indirect with displacement */ 14, 14, 14, 14, 14, 14, 14, 14, /* 110 xxx address register indirect with index */ 12, /* 111 000 absolute short */ 16, /* 111 001 absolute long */ 12, /* 111 010 program counter with displacement */ 14, /* 111 011 program counter with index */ 8, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int* g_ea_cycle_table[3] = {g_ea_8_cycle_table, g_ea_8_cycle_table, g_ea_32_cycle_table}; int g_jmp_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 8, 8, 8, 8, 8, 8, 8, 8, /* 010 xxx address register indirect */ 0, 0, 0, 0, 0, 0, 0, 0, /* 011 xxx address register indirect with postincrement */ 0, 0, 0, 0, 0, 0, 0, 0, /* 100 xxx address register indirect with predecrement */ 10, 10, 10, 10, 10, 10, 10, 10, /* 101 xxx address register indirect with displacement */ 14, 14, 14, 14, 14, 14, 14, 14, /* 110 xxx address register indirect with index */ 10, /* 111 000 absolute short */ 12, /* 111 001 absolute long */ 10, /* 111 010 program counter with displacement */ 14, /* 111 011 program counter with index */ 0, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int g_jsr_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 16, 16, 16, 16, 16, 16, 16, 16, /* 010 xxx address register indirect */ 0, 0, 0, 0, 0, 0, 0, 0, /* 011 xxx address register indirect with postincrement */ 0, 0, 0, 0, 0, 0, 0, 0, /* 100 xxx address register indirect with predecrement */ 18, 18, 18, 18, 18, 18, 18, 18, /* 101 xxx address register indirect with displacement */ 22, 22, 22, 22, 22, 22, 22, 22, /* 110 xxx address register indirect with index */ 18, /* 111 000 absolute short */ 20, /* 111 001 absolute long */ 18, /* 111 010 program counter with displacement */ 22, /* 111 011 program counter with index */ 0, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int g_lea_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 4, 4, 4, 4, 4, 4, 4, 4, /* 010 xxx address register indirect */ 0, 0, 0, 0, 0, 0, 0, 0, /* 011 xxx address register indirect with postincrement */ 0, 0, 0, 0, 0, 0, 0, 0, /* 100 xxx address register indirect with predecrement */ 8, 8, 8, 8, 8, 8, 8, 8, /* 101 xxx address register indirect with displacement */ 12, 12, 12, 12, 12, 12, 12, 12, /* 110 xxx address register indirect with index */ 8, /* 111 000 absolute short */ 12, /* 111 001 absolute long */ 8, /* 111 010 program counter with displacement */ 12, /* 111 011 program counter with index */ 0, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int g_pea_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 12, 12, 12, 12, 12, 12, 12, 12, /* 010 xxx address register indirect */ 0, 0, 0, 0, 0, 0, 0, 0, /* 011 xxx address register indirect with postincrement */ 0, 0, 0, 0, 0, 0, 0, 0, /* 100 xxx address register indirect with predecrement */ 16, 16, 16, 16, 16, 16, 16, 16, /* 101 xxx address register indirect with displacement */ 20, 20, 20, 20, 20, 20, 20, 20, /* 110 xxx address register indirect with index */ 16, /* 111 000 absolute short */ 20, /* 111 001 absolute long */ 16, /* 111 010 program counter with displacement */ 20, /* 111 011 program counter with index */ 0, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int g_moves_bw_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 18, 18, 18, 18, 18, 18, 18, 18, /* 010 xxx address register indirect */ 20, 20, 20, 20, 20, 20, 20, 20, /* 011 xxx address register indirect with postincrement */ 20, 20, 20, 20, 20, 20, 20, 20, /* 100 xxx address register indirect with predecrement */ 20, 20, 20, 20, 20, 20, 20, 20, /* 101 xxx address register indirect with displacement */ 24, 24, 24, 24, 24, 24, 24, 24, /* 110 xxx address register indirect with index */ 20, /* 111 000 absolute short */ 24, /* 111 001 absolute long */ 0, /* 111 010 program counter with displacement */ 0, /* 111 011 program counter with index */ 0, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; int g_moves_l_cycle_table[64]= { 0, 0, 0, 0, 0, 0, 0, 0, /* 000 xxx data register direct */ 0, 0, 0, 0, 0, 0, 0, 0, /* 001 xxx address register direct */ 22, 22, 22, 22, 22, 22, 22, 22, /* 010 xxx address register indirect */ 24, 24, 24, 24, 24, 24, 24, 24, /* 011 xxx address register indirect with postincrement */ 24, 24, 24, 24, 24, 24, 24, 24, /* 100 xxx address register indirect with predecrement */ 24, 24, 24, 24, 24, 24, 24, 24, /* 101 xxx address register indirect with displacement */ 28, 28, 28, 28, 28, 28, 28, 28, /* 110 xxx address register indirect with index */ 24, /* 111 000 absolute short */ 28, /* 111 001 absolute long */ 0, /* 111 010 program counter with displacement */ 0, /* 111 011 program counter with index */ 0, /* 111 100 immediate */ 0, /* 111 101 */ 0, /* 111 110 */ 0, /* 111 111 */ }; static opcode_handler_struct g_func_table[] = { /* name mask match ea size base clks */ {"m68000_1010" , 0xf000, 0xa000, 0x000, 1, 0}, {"m68000_1111" , 0xf000, 0xf000, 0x000, 1, 0}, {"m68000_abcd_rr" , 0xf1f8, 0xc100, 0x000, 0, 6}, {"m68000_abcd_mm_ax7" , 0xfff8, 0xcf08, 0x000, 0, 18}, {"m68000_abcd_mm_ay7" , 0xf1ff, 0xc10f, 0x000, 0, 18}, {"m68000_abcd_mm_axy7" , 0xffff, 0xcf0f, 0x000, 0, 18}, {"m68000_abcd_mm" , 0xf1f8, 0xc108, 0x000, 0, 18}, {"m68000_add_er_d_8" , 0xf1f8, 0xd000, 0x000, 0, 4}, {"m68000_add_er_8" , 0xf1c0, 0xd000, 0xbff, 0, 4}, {"m68000_add_er_d_16" , 0xf1f8, 0xd040, 0x000, 1, 4}, {"m68000_add_er_a_16" , 0xf1f8, 0xd048, 0x000, 1, 4}, {"m68000_add_er_16" , 0xf1c0, 0xd040, 0xfff, 1, 4}, {"m68000_add_er_d_32" , 0xf1f8, 0xd080, 0x000, 2, 8}, {"m68000_add_er_a_32" , 0xf1f8, 0xd088, 0x000, 2, 8}, {"m68000_add_er_32" , 0xf1c0, 0xd080, 0xfff, 2, 6}, /* 8 for imm */ {"m68000_add_re_8" , 0xf1c0, 0xd100, 0x3f8, 0, 8}, {"m68000_add_re_16" , 0xf1c0, 0xd140, 0x3f8, 1, 8}, {"m68000_add_re_32" , 0xf1c0, 0xd180, 0x3f8, 2, 12}, {"m68000_adda_d_16" , 0xf1f8, 0xd0c0, 0x000, 1, 8}, {"m68000_adda_a_16" , 0xf1f8, 0xd0c8, 0x000, 1, 8}, {"m68000_adda_16" , 0xf1c0, 0xd0c0, 0xfff, 1, 8}, {"m68000_adda_d_32" , 0xf1f8, 0xd1c0, 0x000, 2, 8}, {"m68000_adda_a_32" , 0xf1f8, 0xd1c8, 0x000, 2, 8}, {"m68000_adda_32" , 0xf1c0, 0xd1c0, 0xfff, 2, 6}, /* 8 for imm */ {"m68000_addi_d_8" , 0xfff8, 0x0600, 0x000, 0, 8}, {"m68000_addi_8" , 0xffc0, 0x0600, 0xbf8, 0, 12}, {"m68000_addi_d_16" , 0xfff8, 0x0640, 0x000, 1, 8}, {"m68000_addi_16" , 0xffc0, 0x0640, 0xbf8, 1, 12}, {"m68000_addi_d_32" , 0xfff8, 0x0680, 0x000, 2, 16}, {"m68000_addi_32" , 0xffc0, 0x0680, 0xbf8, 2, 20}, {"m68000_addq_d_8" , 0xf1f8, 0x5000, 0x000, 0, 4}, {"m68000_addq_8" , 0xf1c0, 0x5000, 0xbf8, 0, 8}, {"m68000_addq_d_16" , 0xf1f8, 0x5040, 0x000, 1, 4}, {"m68000_addq_a_16" , 0xf1f8, 0x5048, 0x000, 1, 4}, {"m68000_addq_16" , 0xf1c0, 0x5040, 0xff8, 1, 8}, {"m68000_addq_d_32" , 0xf1f8, 0x5080, 0x000, 2, 8}, {"m68000_addq_a_32" , 0xf1f8, 0x5088, 0x000, 2, 8}, {"m68000_addq_32" , 0xf1c0, 0x5080, 0xff8, 2, 12}, {"m68000_addx_rr_8" , 0xf1f8, 0xd100, 0x000, 0, 4}, {"m68000_addx_rr_16" , 0xf1f8, 0xd140, 0x000, 1, 4}, {"m68000_addx_rr_32" , 0xf1f8, 0xd180, 0x000, 2, 8}, {"m68000_addx_mm_8_ax7" , 0xfff8, 0xdf08, 0x000, 0, 18}, {"m68000_addx_mm_8_ay7" , 0xf1ff, 0xd10f, 0x000, 0, 18}, {"m68000_addx_mm_8_axy7" , 0xffff, 0xdf0f, 0x000, 0, 18}, {"m68000_addx_mm_8" , 0xf1f8, 0xd108, 0x000, 0, 18}, {"m68000_addx_mm_16" , 0xf1f8, 0xd148, 0x000, 1, 18}, {"m68000_addx_mm_32" , 0xf1f8, 0xd188, 0x000, 2, 30}, {"m68000_and_er_d_8" , 0xf1f8, 0xc000, 0x000, 0, 4}, {"m68000_and_er_8" , 0xf1c0, 0xc000, 0xbff, 0, 4}, {"m68000_and_er_d_16" , 0xf1f8, 0xc040, 0x000, 1, 4}, {"m68000_and_er_16" , 0xf1c0, 0xc040, 0xbff, 1, 4}, {"m68000_and_er_d_32" , 0xf1f8, 0xc080, 0x000, 2, 8}, {"m68000_and_er_32" , 0xf1c0, 0xc080, 0xbff, 2, 6}, /* 8 for imm */ {"m68000_and_re_8" , 0xf1c0, 0xc100, 0x3f8, 0, 8}, {"m68000_and_re_16" , 0xf1c0, 0xc140, 0x3f8, 1, 8}, {"m68000_and_re_32" , 0xf1c0, 0xc180, 0x3f8, 2, 12}, {"m68000_andi_to_ccr" , 0xffff, 0x023c, 0x000, 0, 20}, {"m68000_andi_to_sr" , 0xffff, 0x027c, 0x000, 1, 20}, {"m68000_andi_d_8" , 0xfff8, 0x0200, 0x000, 0, 8}, {"m68000_andi_8" , 0xffc0, 0x0200, 0xbf8, 0, 12}, {"m68000_andi_d_16" , 0xfff8, 0x0240, 0x000, 1, 8}, {"m68000_andi_16" , 0xffc0, 0x0240, 0xbf8, 1, 12}, {"m68000_andi_d_32" , 0xfff8, 0x0280, 0x000, 2, 14}, {"m68000_andi_32" , 0xffc0, 0x0280, 0xbf8, 2, 20}, {"m68000_asr_s_8" , 0xf1f8, 0xe000, 0x000, 0, 14}, /* fix in code */ {"m68000_asr_s_16" , 0xf1f8, 0xe040, 0x000, 1, 14}, {"m68000_asr_s_32" , 0xf1f8, 0xe080, 0x000, 2, 16}, {"m68000_asr_r_8" , 0xf1f8, 0xe020, 0x000, 0, 14}, {"m68000_asr_r_16" , 0xf1f8, 0xe060, 0x000, 1, 22}, {"m68000_asr_r_32" , 0xf1f8, 0xe0a0, 0x000, 2, 38}, {"m68000_asr_ea" , 0xffc0, 0xe0c0, 0x3f8, 1, 8}, {"m68000_asl_s_8" , 0xf1f8, 0xe100, 0x000, 0, 14}, {"m68000_asl_s_16" , 0xf1f8, 0xe140, 0x000, 1, 14}, {"m68000_asl_s_32" , 0xf1f8, 0xe180, 0x000, 2, 16}, {"m68000_asl_r_8" , 0xf1f8, 0xe120, 0x000, 0, 14}, {"m68000_asl_r_16" , 0xf1f8, 0xe160, 0x000, 1, 22}, {"m68000_asl_r_32" , 0xf1f8, 0xe1a0, 0x000, 2, 38}, {"m68000_asl_ea" , 0xffc0, 0xe1c0, 0x3f8, 1, 8}, {"m68000_bhi_16" , 0xffff, 0x6200, 0x000, 1, 11}, /* fix in code */ {"m68020_bhi_32" , 0xffff, 0x62ff, 0x000, 2, 11}, {"m68000_bhi_8" , 0xff00, 0x6200, 0x000, 0, 9}, {"m68000_bls_16" , 0xffff, 0x6300, 0x000, 1, 11}, {"m68020_bls_32" , 0xffff, 0x63ff, 0x000, 2, 11}, {"m68000_bls_8" , 0xff00, 0x6300, 0x000, 0, 9}, {"m68000_bcc_16" , 0xffff, 0x6400, 0x000, 1, 11}, {"m68020_bcc_32" , 0xffff, 0x64ff, 0x000, 2, 11}, {"m68000_bcc_8" , 0xff00, 0x6400, 0x000, 0, 9}, {"m68000_bcs_16" , 0xffff, 0x6500, 0x000, 1, 11}, {"m68020_bcs_32" , 0xffff, 0x65ff, 0x000, 2, 11}, {"m68000_bcs_8" , 0xff00, 0x6500, 0x000, 0, 9}, {"m68000_bne_16" , 0xffff, 0x6600, 0x000, 1, 11}, {"m68020_bne_32" , 0xffff, 0x66ff, 0x000, 2, 11}, {"m68000_bne_8" , 0xff00, 0x6600, 0x000, 0, 9}, {"m68000_beq_16" , 0xffff, 0x6700, 0x000, 1, 11}, {"m68020_beq_32" , 0xffff, 0x67ff, 0x000, 2, 11}, {"m68000_beq_8" , 0xff00, 0x6700, 0x000, 0, 9}, {"m68000_bvc_16" , 0xffff, 0x6800, 0x000, 1, 11}, {"m68020_bvc_32" , 0xffff, 0x68ff, 0x000, 2, 11}, {"m68000_bvc_8" , 0xff00, 0x6800, 0x000, 0, 9}, {"m68000_bvs_16" , 0xffff, 0x6900, 0x000, 1, 11}, {"m68020_bvs_32" , 0xffff, 0x69ff, 0x000, 2, 11}, {"m68000_bvs_8" , 0xff00, 0x6900, 0x000, 0, 9}, {"m68000_bpl_16" , 0xffff, 0x6a00, 0x000, 1, 11}, {"m68020_bpl_32" , 0xffff, 0x6aff, 0x000, 2, 11}, {"m68000_bpl_8" , 0xff00, 0x6a00, 0x000, 0, 9}, {"m68000_bmi_16" , 0xffff, 0x6b00, 0x000, 1, 11}, {"m68020_bmi_32" , 0xffff, 0x6bff, 0x000, 2, 11}, {"m68000_bmi_8" , 0xff00, 0x6b00, 0x000, 0, 9}, {"m68000_bge_16" , 0xffff, 0x6c00, 0x000, 1, 11}, {"m68020_bge_32" , 0xffff, 0x6cff, 0x000, 2, 11}, {"m68000_bge_8" , 0xff00, 0x6c00, 0x000, 0, 9}, {"m68000_blt_16" , 0xffff, 0x6d00, 0x000, 1, 11}, {"m68020_blt_32" , 0xffff, 0x6dff, 0x000, 2, 11}, {"m68000_blt_8" , 0xff00, 0x6d00, 0x000, 0, 9}, {"m68000_bgt_16" , 0xffff, 0x6e00, 0x000, 1, 11}, {"m68020_bgt_32" , 0xffff, 0x6eff, 0x000, 2, 11}, {"m68000_bgt_8" , 0xff00, 0x6e00, 0x000, 0, 9}, {"m68000_ble_16" , 0xffff, 0x6f00, 0x000, 1, 11}, {"m68020_ble_32" , 0xffff, 0x6fff, 0x000, 2, 11}, {"m68000_ble_8" , 0xff00, 0x6f00, 0x000, 0, 9}, {"m68000_bchg_r_d" , 0xf1f8, 0x0140, 0x000, 2, 8}, {"m68000_bchg_r" , 0xf1c0, 0x0140, 0xbf8, 0, 8}, {"m68000_bchg_s_d" , 0xfff8, 0x0840, 0x000, 2, 12}, {"m68000_bchg_s" , 0xffc0, 0x0840, 0xbf8, 0, 12}, {"m68000_bclr_r_d" , 0xf1f8, 0x0180, 0x000, 2, 10}, {"m68000_bclr_r" , 0xf1c0, 0x0180, 0xbf8, 0, 8}, {"m68000_bclr_s_d" , 0xfff8, 0x0880, 0x000, 2, 14}, {"m68000_bclr_s" , 0xffc0, 0x0880, 0xbf8, 0, 12}, {"m68020_bfchg_d" , 0xfff8, 0xeac0, 0x000, 2, 12}, {"m68020_bfchg" , 0xffc0, 0xeac0, 0xa78, 2, 12}, {"m68020_bfclr_d" , 0xfff8, 0xecc0, 0x000, 2, 12}, {"m68020_bfclr" , 0xffc0, 0xecc0, 0xa78, 2, 12}, {"m68020_bfexts_d" , 0xfff8, 0xebc0, 0x000, 2, 12}, {"m68020_bfexts" , 0xffc0, 0xebc0, 0xa7b, 2, 12}, {"m68020_bfextu_d" , 0xfff8, 0xe9c0, 0x000, 2, 12}, {"m68020_bfextu" , 0xffc0, 0xe9c0, 0xa7b, 2, 12}, {"m68020_bfffo_d" , 0xfff8, 0xedc0, 0x000, 2, 12}, {"m68020_bfffo" , 0xffc0, 0xedc0, 0xa7b, 2, 12}, {"m68020_bfins_d" , 0xfff8, 0xefc0, 0x000, 2, 12}, {"m68020_bfins" , 0xffc0, 0xefc0, 0xa78, 2, 12}, {"m68020_bfset_d" , 0xfff8, 0xeec0, 0x000, 2, 12}, {"m68020_bfset" , 0xffc0, 0xeec0, 0xa78, 2, 12}, {"m68020_bftst_d" , 0xfff8, 0xe8c0, 0x000, 2, 12}, {"m68020_bftst" , 0xffc0, 0xe8c0, 0xa7b, 2, 12}, {"m68010_bkpt" , 0xfff8, 0x4848, 0x000, 0, 11}, {"m68000_bra_16" , 0xffff, 0x6000, 0x000, 1, 10}, {"m68020_bra_32" , 0xffff, 0x60ff, 0x000, 2, 10}, {"m68000_bra_8" , 0xff00, 0x6000, 0x000, 0, 10}, {"m68000_bset_r_d" , 0xf1f8, 0x01c0, 0x000, 2, 8}, {"m68000_bset_r" , 0xf1c0, 0x01c0, 0xbf8, 0, 8}, {"m68000_bset_s_d" , 0xfff8, 0x08c0, 0x000, 2, 12}, {"m68000_bset_s" , 0xffc0, 0x08c0, 0xbf8, 0, 12}, {"m68000_bsr_16" , 0xffff, 0x6100, 0x000, 1, 18}, {"m68020_bsr_32" , 0xffff, 0x61ff, 0x000, 2, 18}, {"m68000_bsr_8" , 0xff00, 0x6100, 0x000, 0, 18}, {"m68000_btst_r_d" , 0xf1f8, 0x0100, 0x000, 2, 6}, {"m68000_btst_r" , 0xf1c0, 0x0100, 0xbff, 0, 4}, {"m68000_btst_s_d" , 0xfff8, 0x0800, 0x000, 2, 10}, {"m68000_btst_s" , 0xffc0, 0x0800, 0xbfb, 0, 8}, {"m68020_callm" , 0xffc0, 0x06c0, 0x27b, 2, 8}, {"m68020_cas_8" , 0xffc0, 0x0ac0, 0x3f8, 0, 36}, {"m68020_cas_16" , 0xffc0, 0x0cc0, 0x3f8, 1, 36}, {"m68020_cas_32" , 0xffc0, 0x0ec0, 0x3f8, 2, 36}, {"m68020_cas2_16" , 0xffff, 0x0cfc, 0x000, 1, 36}, {"m68020_cas2_32" , 0xffff, 0x0efc, 0x000, 2, 36}, {"m68000_chk_d_16" , 0xf1f8, 0x4180, 0x000, 1, 10}, {"m68000_chk_16" , 0xf1c0, 0x4180, 0xbff, 1, 10}, {"m68020_chk_d_32" , 0xf1f8, 0x4100, 0x000, 1, 10}, {"m68020_chk_32" , 0xf1c0, 0x4100, 0xbff, 1, 10}, {"m68020_chk2_cmp2_8" , 0xffc0, 0x00c0, 0x27b, 0, 12}, {"m68020_chk2_cmp2_16" , 0xffc0, 0x02c0, 0x27b, 1, 12}, {"m68020_chk2_cmp2_32" , 0xffc0, 0x04c0, 0x27b, 2, 12}, {"m68000_clr_d_8" , 0xfff8, 0x4200, 0x000, 0, 4}, {"m68000_clr_8" , 0xffc0, 0x4200, 0xbf8, 0, 8}, {"m68000_clr_d_16" , 0xfff8, 0x4240, 0x000, 1, 4}, {"m68000_clr_16" , 0xffc0, 0x4240, 0xbf8, 1, 8}, {"m68000_clr_d_32" , 0xfff8, 0x4280, 0x000, 2, 6}, {"m68000_clr_32" , 0xffc0, 0x4280, 0xbf8, 2, 12}, {"m68000_cmp_d_8" , 0xf1f8, 0xb000, 0x000, 0, 4}, {"m68000_cmp_8" , 0xf1c0, 0xb000, 0xbff, 0, 4}, {"m68000_cmp_d_16" , 0xf1f8, 0xb040, 0x000, 1, 4}, {"m68000_cmp_a_16" , 0xf1f8, 0xb048, 0x000, 1, 4}, {"m68000_cmp_16" , 0xf1c0, 0xb040, 0xfff, 1, 4}, {"m68000_cmp_d_32" , 0xf1f8, 0xb080, 0x000, 2, 6}, {"m68000_cmp_a_32" , 0xf1f8, 0xb088, 0x000, 2, 6}, {"m68000_cmp_32" , 0xf1c0, 0xb080, 0xfff, 2, 6}, {"m68000_cmpa_d_16" , 0xf1f8, 0xb0c0, 0x000, 1, 6}, {"m68000_cmpa_a_16" , 0xf1f8, 0xb0c8, 0x000, 1, 6}, {"m68000_cmpa_16" , 0xf1c0, 0xb0c0, 0xfff, 1, 6}, {"m68000_cmpa_d_32" , 0xf1f8, 0xb1c0, 0x000, 2, 6}, {"m68000_cmpa_a_32" , 0xf1f8, 0xb1c8, 0x000, 2, 6}, {"m68000_cmpa_32" , 0xf1c0, 0xb1c0, 0xfff, 2, 6}, {"m68000_cmpi_d_8" , 0xfff8, 0x0c00, 0x000, 0, 8}, {"m68000_cmpi_8" , 0xffc0, 0x0c00, 0xbf8, 0, 8}, {"m68020_cmpi_pcdi_8" , 0xffff, 0x0c3a, 0x000, 0, 8}, {"m68020_cmpi_pcix_8" , 0xffff, 0x0c3b, 0x000, 0, 8}, {"m68000_cmpi_d_16" , 0xfff8, 0x0c40, 0x000, 1, 8}, {"m68000_cmpi_16" , 0xffc0, 0x0c40, 0xbf8, 1, 8}, {"m68020_cmpi_pcdi_16" , 0xffff, 0x0c7a, 0x000, 1, 8}, {"m68020_cmpi_pcix_16" , 0xffff, 0x0c7b, 0x000, 1, 8}, {"m68000_cmpi_d_32" , 0xfff8, 0x0c80, 0x000, 2, 14}, {"m68000_cmpi_32" , 0xffc0, 0x0c80, 0xbf8, 2, 12}, {"m68020_cmpi_pcdi_32" , 0xffff, 0x0cba, 0x000, 2, 12}, {"m68020_cmpi_pcix_32" , 0xffff, 0x0cbb, 0x000, 2, 12}, {"m68000_cmpm_8_ax7" , 0xfff8, 0xbf08, 0x000, 0, 12}, {"m68000_cmpm_8_ay7" , 0xf1ff, 0xb10f, 0x000, 0, 12}, {"m68000_cmpm_8_axy7" , 0xffff, 0xbf0f, 0x000, 0, 12}, {"m68000_cmpm_8" , 0xf1f8, 0xb108, 0x000, 0, 12}, {"m68000_cmpm_16" , 0xf1f8, 0xb148, 0x000, 1, 12}, {"m68000_cmpm_32" , 0xf1f8, 0xb188, 0x000, 2, 20}, {"m68020_cpbcc" , 0xf180, 0xf080, 0x000, 2, 0}, {"m68020_cpdbcc" , 0xf1f8, 0xf048, 0x000, 2, 0}, {"m68020_cpgen" , 0xf1c0, 0xf000, 0x000, 2, 0}, {"m68020_cpscc" , 0xf1c0, 0xf040, 0x000, 2, 0}, {"m68020_cptrapcc" , 0xf1f8, 0xf078, 0x000, 2, 0}, {"m68000_dbt" , 0xfff8, 0x50c8, 0x000, 1, 12}, /* fix in code */ {"m68000_dbf" , 0xfff8, 0x51c8, 0x000, 1, 10}, {"m68000_dbhi" , 0xfff8, 0x52c8, 0x000, 1, 11}, {"m68000_dbls" , 0xfff8, 0x53c8, 0x000, 1, 11}, {"m68000_dbcc" , 0xfff8, 0x54c8, 0x000, 1, 11}, {"m68000_dbcs" , 0xfff8, 0x55c8, 0x000, 1, 11}, {"m68000_dbne" , 0xfff8, 0x56c8, 0x000, 1, 11}, {"m68000_dbeq" , 0xfff8, 0x57c8, 0x000, 1, 11}, {"m68000_dbvc" , 0xfff8, 0x58c8, 0x000, 1, 11}, {"m68000_dbvs" , 0xfff8, 0x59c8, 0x000, 1, 11}, {"m68000_dbpl" , 0xfff8, 0x5ac8, 0x000, 1, 11}, {"m68000_dbmi" , 0xfff8, 0x5bc8, 0x000, 1, 11}, {"m68000_dbge" , 0xfff8, 0x5cc8, 0x000, 1, 11}, {"m68000_dblt" , 0xfff8, 0x5dc8, 0x000, 1, 11}, {"m68000_dbgt" , 0xfff8, 0x5ec8, 0x000, 1, 11}, {"m68000_dble" , 0xfff8, 0x5fc8, 0x000, 1, 11}, {"m68000_divs_d_16" , 0xf1f8, 0x81c0, 0x000, 1, 158}, {"m68000_divs_16" , 0xf1c0, 0x81c0, 0xbff, 1, 158}, {"m68000_divu_d_16" , 0xf1f8, 0x80c0, 0x000, 1, 140}, {"m68000_divu_16" , 0xf1c0, 0x80c0, 0xbff, 1, 140}, {"m68020_divl_d_32" , 0xfff8, 0x4c40, 0x000, 2, 150}, {"m68020_divl_32" , 0xffc0, 0x4c40, 0xbff, 2, 150}, {"m68000_eor_d_8" , 0xf1f8, 0xb100, 0x000, 0, 4}, {"m68000_eor_8" , 0xf1c0, 0xb100, 0xbf8, 0, 8}, {"m68000_eor_d_16" , 0xf1f8, 0xb140, 0x000, 1, 4}, {"m68000_eor_16" , 0xf1c0, 0xb140, 0xbf8, 1, 8}, {"m68000_eor_d_32" , 0xf1f8, 0xb180, 0x000, 2, 8}, {"m68000_eor_32" , 0xf1c0, 0xb180, 0xbf8, 2, 12}, {"m68000_eori_to_ccr" , 0xffff, 0x0a3c, 0x000, 0, 20}, {"m68000_eori_to_sr" , 0xffff, 0x0a7c, 0x000, 1, 20}, {"m68000_eori_d_8" , 0xfff8, 0x0a00, 0x000, 0, 8}, {"m68000_eori_8" , 0xffc0, 0x0a00, 0xbf8, 0, 12}, {"m68000_eori_d_16" , 0xfff8, 0x0a40, 0x000, 1, 8}, {"m68000_eori_16" , 0xffc0, 0x0a40, 0xbf8, 1, 12}, {"m68000_eori_d_32" , 0xfff8, 0x0a80, 0x000, 2, 16}, {"m68000_eori_32" , 0xffc0, 0x0a80, 0xbf8, 2, 20}, {"m68000_exg_dd" , 0xf1f8, 0xc140, 0x000, 2, 6}, {"m68000_exg_aa" , 0xf1f8, 0xc148, 0x000, 2, 6}, {"m68000_exg_da" , 0xf1f8, 0xc188, 0x000, 2, 6}, {"m68000_ext_16" , 0xfff8, 0x4880, 0x000, 1, 4}, {"m68000_ext_32" , 0xfff8, 0x48c0, 0x000, 2, 4}, {"m68020_extb" , 0xfff8, 0x49c0, 0x000, 2, 4}, {"m68000_illegal" , 0xffff, 0x4afc, 0x000, 1, 0}, {"m68000_jmp" , 0xffc0, 0x4ec0, 0x27b, 2, 0}, /* make table */ {"m68000_jsr" , 0xffc0, 0x4e80, 0x27b, 2, 0}, /* make table */ {"m68000_lea" , 0xf1c0, 0x41c0, 0x27b, 2, 0}, /* make table */ {"m68000_link_16_a7" , 0xffff, 0x4e57, 0x000, 1, 16}, {"m68000_link_16" , 0xfff8, 0x4e50, 0x000, 1, 16}, {"m68020_link_32_a7" , 0xffff, 0x480f, 0x000, 1, 16}, {"m68020_link_32" , 0xfff8, 0x4808, 0x000, 1, 16}, {"m68000_lsr_s_8" , 0xf1f8, 0xe008, 0x000, 0, 14}, /* fix in code */ {"m68000_lsr_s_16" , 0xf1f8, 0xe048, 0x000, 1, 14}, {"m68000_lsr_s_32" , 0xf1f8, 0xe088, 0x000, 2, 16}, {"m68000_lsr_r_8" , 0xf1f8, 0xe028, 0x000, 0, 14}, {"m68000_lsr_r_16" , 0xf1f8, 0xe068, 0x000, 1, 22}, {"m68000_lsr_r_32" , 0xf1f8, 0xe0a8, 0x000, 2, 38}, {"m68000_lsr_ea" , 0xffc0, 0xe2c0, 0x3f8, 1, 8}, {"m68000_lsl_s_8" , 0xf1f8, 0xe108, 0x000, 0, 14}, /* fix in code */ {"m68000_lsl_s_16" , 0xf1f8, 0xe148, 0x000, 1, 14}, {"m68000_lsl_s_32" , 0xf1f8, 0xe188, 0x000, 2, 16}, {"m68000_lsl_r_8" , 0xf1f8, 0xe128, 0x000, 0, 14}, {"m68000_lsl_r_16" , 0xf1f8, 0xe168, 0x000, 1, 22}, {"m68000_lsl_r_32" , 0xf1f8, 0xe1a8, 0x000, 2, 38}, {"m68000_lsl_ea" , 0xffc0, 0xe3c0, 0x3f8, 1, 8}, {"m68000_move_dd_d_8" , 0xf1f8, 0x1000, 0x000, 0, 4}, {"m68000_move_dd_8" , 0xf1c0, 0x1000, 0xbff, 0, 4}, {"m68000_move_ai_d_8" , 0xf1f8, 0x1080, 0x000, 0, 8}, {"m68000_move_ai_8" , 0xf1c0, 0x1080, 0xbff, 0, 8}, {"m68000_move_pi_d_8" , 0xf1f8, 0x10c0, 0x000, 0, 8}, {"m68000_move_pi_8" , 0xf1c0, 0x10c0, 0xbff, 0, 8}, {"m68000_move_pi7_d_8" , 0xfff8, 0x1ec0, 0x000, 0, 8}, {"m68000_move_pi7_8" , 0xffc0, 0x1ec0, 0xbff, 0, 8}, {"m68000_move_pd_d_8" , 0xf1f8, 0x1100, 0x000, 0, 8}, {"m68000_move_pd_8" , 0xf1c0, 0x1100, 0xbff, 0, 8}, {"m68000_move_pd7_d_8" , 0xfff8, 0x1f00, 0x000, 0, 8}, {"m68000_move_pd7_8" , 0xffc0, 0x1f00, 0xbff, 0, 8}, {"m68000_move_di_d_8" , 0xf1f8, 0x1140, 0x000, 0, 12}, {"m68000_move_di_8" , 0xf1c0, 0x1140, 0xbff, 0, 12}, {"m68000_move_ix_d_8" , 0xf1f8, 0x1180, 0x000, 0, 14}, {"m68000_move_ix_8" , 0xf1c0, 0x1180, 0xbff, 0, 14}, {"m68000_move_aw_d_8" , 0xfff8, 0x11c0, 0x000, 0, 12}, {"m68000_move_aw_8" , 0xffc0, 0x11c0, 0xbff, 0, 12}, {"m68000_move_al_d_8" , 0xfff8, 0x13c0, 0x000, 0, 16}, {"m68000_move_al_8" , 0xffc0, 0x13c0, 0xbff, 0, 16}, {"m68000_move_dd_d_16" , 0xf1f8, 0x3000, 0x000, 1, 4}, {"m68000_move_dd_a_16" , 0xf1f8, 0x3008, 0x000, 1, 4}, {"m68000_move_dd_16" , 0xf1c0, 0x3000, 0xfff, 1, 4}, {"m68000_move_ai_d_16" , 0xf1f8, 0x3080, 0x000, 1, 8}, {"m68000_move_ai_a_16" , 0xf1f8, 0x3088, 0x000, 1, 8}, {"m68000_move_ai_16" , 0xf1c0, 0x3080, 0xfff, 1, 8}, {"m68000_move_pi_d_16" , 0xf1f8, 0x30c0, 0x000, 1, 8}, {"m68000_move_pi_a_16" , 0xf1f8, 0x30c8, 0x000, 1, 8}, {"m68000_move_pi_16" , 0xf1c0, 0x30c0, 0xfff, 1, 8}, {"m68000_move_pd_d_16" , 0xf1f8, 0x3100, 0x000, 1, 8}, {"m68000_move_pd_a_16" , 0xf1f8, 0x3108, 0x000, 1, 8}, {"m68000_move_pd_16" , 0xf1c0, 0x3100, 0xfff, 1, 8}, {"m68000_move_di_d_16" , 0xf1f8, 0x3140, 0x000, 1, 12}, {"m68000_move_di_a_16" , 0xf1f8, 0x3148, 0x000, 1, 12}, {"m68000_move_di_16" , 0xf1c0, 0x3140, 0xfff, 1, 12}, {"m68000_move_ix_d_16" , 0xf1f8, 0x3180, 0x000, 1, 14}, {"m68000_move_ix_a_16" , 0xf1f8, 0x3188, 0x000, 1, 14}, {"m68000_move_ix_16" , 0xf1c0, 0x3180, 0xfff, 1, 14}, {"m68000_move_aw_d_16" , 0xfff8, 0x31c0, 0x000, 1, 12}, {"m68000_move_aw_a_16" , 0xfff8, 0x31c8, 0x000, 1, 12}, {"m68000_move_aw_16" , 0xffc0, 0x31c0, 0xfff, 1, 12}, {"m68000_move_al_d_16" , 0xfff8, 0x33c0, 0x000, 1, 16}, {"m68000_move_al_a_16" , 0xfff8, 0x33c8, 0x000, 1, 16}, {"m68000_move_al_16" , 0xffc0, 0x33c0, 0xfff, 1, 16}, {"m68000_move_dd_d_32" , 0xf1f8, 0x2000, 0x000, 2, 4}, {"m68000_move_dd_a_32" , 0xf1f8, 0x2008, 0x000, 2, 4}, {"m68000_move_dd_32" , 0xf1c0, 0x2000, 0xfff, 2, 4}, {"m68000_move_ai_d_32" , 0xf1f8, 0x2080, 0x000, 2, 12}, {"m68000_move_ai_a_32" , 0xf1f8, 0x2088, 0x000, 2, 12}, {"m68000_move_ai_32" , 0xf1c0, 0x2080, 0xfff, 2, 12}, {"m68000_move_pi_d_32" , 0xf1f8, 0x20c0, 0x000, 2, 12}, {"m68000_move_pi_a_32" , 0xf1f8, 0x20c8, 0x000, 2, 12}, {"m68000_move_pi_32" , 0xf1c0, 0x20c0, 0xfff, 2, 12}, {"m68000_move_pd_d_32" , 0xf1f8, 0x2100, 0x000, 2, 12}, {"m68000_move_pd_a_32" , 0xf1f8, 0x2108, 0x000, 2, 12}, {"m68000_move_pd_32" , 0xf1c0, 0x2100, 0xfff, 2, 12}, {"m68000_move_di_d_32" , 0xf1f8, 0x2140, 0x000, 2, 16}, {"m68000_move_di_a_32" , 0xf1f8, 0x2148, 0x000, 2, 16}, {"m68000_move_di_32" , 0xf1c0, 0x2140, 0xfff, 2, 16}, {"m68000_move_ix_d_32" , 0xf1f8, 0x2180, 0x000, 2, 18}, {"m68000_move_ix_a_32" , 0xf1f8, 0x2188, 0x000, 2, 18}, {"m68000_move_ix_32" , 0xf1c0, 0x2180, 0xfff, 2, 18}, {"m68000_move_aw_d_32" , 0xfff8, 0x21c0, 0x000, 2, 16}, {"m68000_move_aw_a_32" , 0xfff8, 0x21c8, 0x000, 2, 16}, {"m68000_move_aw_32" , 0xffc0, 0x21c0, 0xfff, 2, 16}, {"m68000_move_al_d_32" , 0xfff8, 0x23c0, 0x000, 2, 20}, {"m68000_move_al_a_32" , 0xfff8, 0x23c8, 0x000, 2, 20}, {"m68000_move_al_32" , 0xffc0, 0x23c0, 0xfff, 2, 20}, {"m68000_movea_d_16" , 0xf1f8, 0x3040, 0x000, 1, 4}, {"m68000_movea_a_16" , 0xf1f8, 0x3048, 0x000, 1, 4}, {"m68000_movea_16" , 0xf1c0, 0x3040, 0xfff, 1, 4}, {"m68000_movea_d_32" , 0xf1f8, 0x2040, 0x000, 2, 4}, {"m68000_movea_a_32" , 0xf1f8, 0x2048, 0x000, 2, 4}, {"m68000_movea_32" , 0xf1c0, 0x2040, 0xfff, 2, 4}, {"m68010_move_fr_ccr_d" , 0xfff8, 0x42c0, 0x000, 1, 4}, {"m68010_move_fr_ccr" , 0xffc0, 0x42c0, 0xbf8, 1, 8}, {"m68000_move_to_ccr_d" , 0xfff8, 0x44c0, 0x000, 1, 12}, {"m68000_move_to_ccr" , 0xffc0, 0x44c0, 0xbff, 1, 12}, {"m68000_move_fr_sr_d" , 0xfff8, 0x40c0, 0x000, 1, 6}, {"m68000_move_fr_sr" , 0xffc0, 0x40c0, 0xbf8, 1, 8}, {"m68000_move_to_sr_d" , 0xfff8, 0x46c0, 0x000, 1, 12}, {"m68000_move_to_sr" , 0xffc0, 0x46c0, 0xbff, 1, 12}, {"m68000_move_fr_usp" , 0xfff8, 0x4e68, 0x000, 2, 4}, {"m68000_move_to_usp" , 0xfff8, 0x4e60, 0x000, 2, 4}, {"m68010_movec_cr" , 0xffff, 0x4e7a, 0x000, 0, 12}, {"m68010_movec_rc" , 0xffff, 0x4e7b, 0x000, 0, 10}, {"m68000_movem_pd_16" , 0xfff8, 0x48a0, 0x000, 1, 40}, /* fix in code */ {"m68000_movem_pd_32" , 0xfff8, 0x48e0, 0x000, 1, 72}, /* ASG: size really 2, but cycles like 1 */ {"m68000_movem_pi_16" , 0xfff8, 0x4c98, 0x000, 1, 44}, {"m68000_movem_pi_32" , 0xfff8, 0x4cd8, 0x000, 1, 76}, /* ASG: size really 2, but cycles like 1 */ {"m68000_movem_re_16" , 0xffc0, 0x4880, 0x278, 1, 36}, /* HJB was 0x2f8 */ {"m68000_movem_re_32" , 0xffc0, 0x48c0, 0x278, 1, 68}, /* HJB was 0x2f8 */ /* ASG: size really 2, but cycles like 1 */ {"m68000_movem_er_16" , 0xffc0, 0x4c80, 0x27b, 1, 40}, /* JCB was 0x37b */ {"m68000_movem_er_32" , 0xffc0, 0x4cc0, 0x27b, 1, 72}, /* JCB was 0x37b */ /* ASG: size really 2, but cycles like 1 */ {"m68000_movep_er_16" , 0xf1f8, 0x0108, 0x000, 1, 16}, {"m68000_movep_er_32" , 0xf1f8, 0x0148, 0x000, 2, 24}, {"m68000_movep_re_16" , 0xf1f8, 0x0188, 0x000, 1, 16}, {"m68000_movep_re_32" , 0xf1f8, 0x01c8, 0x000, 2, 24}, {"m68010_moves_8" , 0xffc0, 0x0e00, 0x3f8, 0, 0}, /* make table */ {"m68010_moves_16" , 0xffc0, 0x0e40, 0x3f8, 1, 0}, /* make table */ {"m68010_moves_32" , 0xffc0, 0x0e80, 0x3f8, 2, 0}, /* make table */ {"m68000_moveq" , 0xf100, 0x7000, 0x000, 2, 4}, {"m68000_muls_d_16" , 0xf1f8, 0xc1c0, 0x000, 1, 54}, {"m68000_muls_16" , 0xf1c0, 0xc1c0, 0xbff, 1, 54}, {"m68000_mulu_d_16" , 0xf1f8, 0xc0c0, 0x000, 1, 54}, {"m68000_mulu_16" , 0xf1c0, 0xc0c0, 0xbff, 1, 54}, {"m68020_mull_d_32" , 0xfff8, 0x4c00, 0x000, 2, 54}, {"m68020_mull_32" , 0xffc0, 0x4c00, 0xbff, 2, 54}, {"m68000_nbcd_d" , 0xfff8, 0x4800, 0x000, 0, 6}, {"m68000_nbcd" , 0xffc0, 0x4800, 0xbf8, 0, 8}, {"m68000_neg_d_8" , 0xfff8, 0x4400, 0x000, 0, 4}, {"m68000_neg_8" , 0xffc0, 0x4400, 0xbf8, 0, 8}, {"m68000_neg_d_16" , 0xfff8, 0x4440, 0x000, 1, 4}, {"m68000_neg_16" , 0xffc0, 0x4440, 0xbf8, 1, 8}, {"m68000_neg_d_32" , 0xfff8, 0x4480, 0x000, 2, 6}, {"m68000_neg_32" , 0xffc0, 0x4480, 0xbf8, 2, 12}, {"m68000_negx_d_8" , 0xfff8, 0x4000, 0x000, 0, 4}, {"m68000_negx_8" , 0xffc0, 0x4000, 0xbf8, 0, 8}, {"m68000_negx_d_16" , 0xfff8, 0x4040, 0x000, 1, 4}, {"m68000_negx_16" , 0xffc0, 0x4040, 0xbf8, 1, 8}, {"m68000_negx_d_32" , 0xfff8, 0x4080, 0x000, 2, 6}, {"m68000_negx_32" , 0xffc0, 0x4080, 0xbf8, 2, 12}, {"m68000_nop" , 0xffff, 0x4e71, 0x000, 1, 4}, {"m68000_not_d_8" , 0xfff8, 0x4600, 0x000, 0, 4}, {"m68000_not_8" , 0xffc0, 0x4600, 0xbf8, 0, 8}, {"m68000_not_d_16" , 0xfff8, 0x4640, 0x000, 1, 4}, {"m68000_not_16" , 0xffc0, 0x4640, 0xbf8, 1, 8}, {"m68000_not_d_32" , 0xfff8, 0x4680, 0x000, 2, 6}, {"m68000_not_32" , 0xffc0, 0x4680, 0xbf8, 2, 12}, {"m68000_or_er_d_8" , 0xf1f8, 0x8000, 0x000, 0, 4}, {"m68000_or_er_8" , 0xf1c0, 0x8000, 0xbff, 0, 4}, {"m68000_or_er_d_16" , 0xf1f8, 0x8040, 0x000, 1, 4}, {"m68000_or_er_16" , 0xf1c0, 0x8040, 0xbff, 1, 4}, {"m68000_or_er_d_32" , 0xf1f8, 0x8080, 0x000, 2, 8}, {"m68000_or_er_32" , 0xf1c0, 0x8080, 0xbff, 2, 6}, /* 8 for imm */ {"m68000_or_re_8" , 0xf1c0, 0x8100, 0x3f8, 0, 8}, {"m68000_or_re_16" , 0xf1c0, 0x8140, 0x3f8, 1, 8}, {"m68000_or_re_32" , 0xf1c0, 0x8180, 0x3f8, 2, 12}, {"m68000_ori_to_ccr" , 0xffff, 0x003c, 0x000, 0, 20}, {"m68000_ori_to_sr" , 0xffff, 0x007c, 0x000, 1, 20}, {"m68000_ori_d_8" , 0xfff8, 0x0000, 0x000, 0, 8}, {"m68000_ori_8" , 0xffc0, 0x0000, 0xbf8, 0, 12}, {"m68000_ori_d_16" , 0xfff8, 0x0040, 0x000, 1, 8}, {"m68000_ori_16" , 0xffc0, 0x0040, 0xbf8, 1, 12}, {"m68000_ori_d_32" , 0xfff8, 0x0080, 0x000, 2, 16}, {"m68000_ori_32" , 0xffc0, 0x0080, 0xbf8, 2, 20}, {"m68020_pack_rr" , 0xf1f8, 0x8140, 0x000, 0, 8}, {"m68020_pack_mm_ax7" , 0xf1ff, 0x814f, 0x000, 0, 8}, {"m68020_pack_mm_ay7" , 0xfff8, 0x8f48, 0x000, 0, 8}, {"m68020_pack_mm_axy7" , 0xffff, 0x8f4f, 0x000, 0, 8}, {"m68020_pack_mm" , 0xf1f8, 0x8148, 0x000, 0, 8}, {"m68000_pea" , 0xffc0, 0x4840, 0x27b, 2, 0}, /* make table */ {"m68000_rst" , 0xffff, 0x4e70, 0x000, 1, 132}, {"m68000_ror_s_8" , 0xf1f8, 0xe018, 0x000, 0, 14}, /* fix in code */ {"m68000_ror_s_16" , 0xf1f8, 0xe058, 0x000, 1, 14}, {"m68000_ror_s_32" , 0xf1f8, 0xe098, 0x000, 2, 16}, {"m68000_ror_r_8" , 0xf1f8, 0xe038, 0x000, 0, 14}, {"m68000_ror_r_16" , 0xf1f8, 0xe078, 0x000, 1, 22}, {"m68000_ror_r_32" , 0xf1f8, 0xe0b8, 0x000, 2, 38}, {"m68000_ror_ea" , 0xffc0, 0xe6c0, 0x3f8, 1, 8}, {"m68000_rol_s_8" , 0xf1f8, 0xe118, 0x000, 0, 14}, /* fix in code */ {"m68000_rol_s_16" , 0xf1f8, 0xe158, 0x000, 1, 14}, {"m68000_rol_s_32" , 0xf1f8, 0xe198, 0x000, 2, 16}, {"m68000_rol_r_8" , 0xf1f8, 0xe138, 0x000, 0, 14}, {"m68000_rol_r_16" , 0xf1f8, 0xe178, 0x000, 1, 22}, {"m68000_rol_r_32" , 0xf1f8, 0xe1b8, 0x000, 2, 38}, {"m68000_rol_ea" , 0xffc0, 0xe7c0, 0x3f8, 1, 8}, {"m68000_roxr_s_8" , 0xf1f8, 0xe010, 0x000, 0, 14}, /* fix in code */ {"m68000_roxr_s_16" , 0xf1f8, 0xe050, 0x000, 1, 14}, {"m68000_roxr_s_32" , 0xf1f8, 0xe090, 0x000, 2, 16}, {"m68000_roxr_r_8" , 0xf1f8, 0xe030, 0x000, 0, 14}, {"m68000_roxr_r_16" , 0xf1f8, 0xe070, 0x000, 1, 22}, {"m68000_roxr_r_32" , 0xf1f8, 0xe0b0, 0x000, 2, 38}, {"m68000_roxr_ea" , 0xffc0, 0xe4c0, 0x3f8, 1, 8}, {"m68000_roxl_s_8" , 0xf1f8, 0xe110, 0x000, 0, 14}, /* fix in code */ {"m68000_roxl_s_16" , 0xf1f8, 0xe150, 0x000, 1, 14}, {"m68000_roxl_s_32" , 0xf1f8, 0xe190, 0x000, 2, 16}, {"m68000_roxl_r_8" , 0xf1f8, 0xe130, 0x000, 0, 14}, {"m68000_roxl_r_16" , 0xf1f8, 0xe170, 0x000, 1, 22}, {"m68000_roxl_r_32" , 0xf1f8, 0xe1b0, 0x000, 2, 38}, {"m68000_roxl_ea" , 0xffc0, 0xe5c0, 0x3f8, 1, 8}, {"m68010_rtd" , 0xffff, 0x4e74, 0x000, 2, 16}, {"m68000_rte" , 0xffff, 0x4e73, 0x000, 2, 20}, {"m68020_rtm" , 0xfff0, 0x06c0, 0x000, 2, 20}, {"m68000_rtr" , 0xffff, 0x4e77, 0x000, 2, 20}, {"m68000_rts" , 0xffff, 0x4e75, 0x000, 2, 16}, {"m68000_sbcd_rr" , 0xf1f8, 0x8100, 0x000, 0, 6}, {"m68000_sbcd_mm_ax7" , 0xfff8, 0x8f08, 0x000, 0, 18}, {"m68000_sbcd_mm_ay7" , 0xf1ff, 0x810f, 0x000, 0, 18}, {"m68000_sbcd_mm_axy7" , 0xffff, 0x8f0f, 0x000, 0, 18}, {"m68000_sbcd_mm" , 0xf1f8, 0x8108, 0x000, 0, 18}, {"m68000_st_d" , 0xfff8, 0x50c0, 0x000, 0, 6}, /* fix in code */ {"m68000_st" , 0xffc0, 0x50c0, 0xbf8, 0, 8}, {"m68000_sf_d" , 0xfff8, 0x51c0, 0x000, 0, 4}, {"m68000_sf" , 0xffc0, 0x51c0, 0xbf8, 0, 8}, {"m68000_shi_d" , 0xfff8, 0x52c0, 0x000, 0, 5}, {"m68000_shi" , 0xffc0, 0x52c0, 0xbf8, 0, 8}, {"m68000_sls_d" , 0xfff8, 0x53c0, 0x000, 0, 5}, {"m68000_sls" , 0xffc0, 0x53c0, 0xbf8, 0, 8}, {"m68000_scc_d" , 0xfff8, 0x54c0, 0x000, 0, 5}, {"m68000_scc" , 0xffc0, 0x54c0, 0xbf8, 0, 8}, {"m68000_scs_d" , 0xfff8, 0x55c0, 0x000, 0, 5}, {"m68000_scs" , 0xffc0, 0x55c0, 0xbf8, 0, 8}, {"m68000_sne_d" , 0xfff8, 0x56c0, 0x000, 0, 5}, {"m68000_sne" , 0xffc0, 0x56c0, 0xbf8, 0, 8}, {"m68000_seq_d" , 0xfff8, 0x57c0, 0x000, 0, 5}, {"m68000_seq" , 0xffc0, 0x57c0, 0xbf8, 0, 8}, {"m68000_svc_d" , 0xfff8, 0x58c0, 0x000, 0, 5}, {"m68000_svc" , 0xffc0, 0x58c0, 0xbf8, 0, 8}, {"m68000_svs_d" , 0xfff8, 0x59c0, 0x000, 0, 5}, {"m68000_svs" , 0xffc0, 0x59c0, 0xbf8, 0, 8}, {"m68000_spl_d" , 0xfff8, 0x5ac0, 0x000, 0, 5}, {"m68000_spl" , 0xffc0, 0x5ac0, 0xbf8, 0, 8}, {"m68000_smi_d" , 0xfff8, 0x5bc0, 0x000, 0, 5}, {"m68000_smi" , 0xffc0, 0x5bc0, 0xbf8, 0, 8}, {"m68000_sge_d" , 0xfff8, 0x5cc0, 0x000, 0, 5}, {"m68000_sge" , 0xffc0, 0x5cc0, 0xbf8, 0, 8}, {"m68000_slt_d" , 0xfff8, 0x5dc0, 0x000, 0, 5}, {"m68000_slt" , 0xffc0, 0x5dc0, 0xbf8, 0, 8}, {"m68000_sgt_d" , 0xfff8, 0x5ec0, 0x000, 0, 5}, {"m68000_sgt" , 0xffc0, 0x5ec0, 0xbf8, 0, 8}, {"m68000_sle_d" , 0xfff8, 0x5fc0, 0x000, 0, 5}, {"m68000_sle" , 0xffc0, 0x5fc0, 0xbf8, 0, 8}, {"m68000_stop" , 0xffff, 0x4e72, 0x000, 1, 4}, {"m68000_sub_er_d_8" , 0xf1f8, 0x9000, 0x000, 0, 4}, {"m68000_sub_er_8" , 0xf1c0, 0x9000, 0xbff, 0, 4}, {"m68000_sub_er_d_16" , 0xf1f8, 0x9040, 0x000, 1, 4}, {"m68000_sub_er_a_16" , 0xf1f8, 0x9048, 0x000, 1, 4}, {"m68000_sub_er_16" , 0xf1c0, 0x9040, 0xfff, 1, 4}, {"m68000_sub_er_d_32" , 0xf1f8, 0x9080, 0x000, 2, 8}, {"m68000_sub_er_a_32" , 0xf1f8, 0x9088, 0x000, 2, 8}, {"m68000_sub_er_32" , 0xf1c0, 0x9080, 0xfff, 2, 6}, /* 8 for imm */ {"m68000_sub_re_8" , 0xf1c0, 0x9100, 0x3f8, 0, 8}, {"m68000_sub_re_16" , 0xf1c0, 0x9140, 0x3f8, 1, 8}, {"m68000_sub_re_32" , 0xf1c0, 0x9180, 0x3f8, 2, 12}, {"m68000_suba_d_16" , 0xf1f8, 0x90c0, 0x000, 1, 8}, {"m68000_suba_a_16" , 0xf1f8, 0x90c8, 0x000, 1, 8}, {"m68000_suba_16" , 0xf1c0, 0x90c0, 0xfff, 1, 8}, {"m68000_suba_d_32" , 0xf1f8, 0x91c0, 0x000, 2, 8}, {"m68000_suba_a_32" , 0xf1f8, 0x91c8, 0x000, 2, 8}, {"m68000_suba_32" , 0xf1c0, 0x91c0, 0xfff, 2, 6}, /* 8 for imm */ {"m68000_subi_d_8" , 0xfff8, 0x0400, 0x000, 0, 8}, {"m68000_subi_8" , 0xffc0, 0x0400, 0xbf8, 0, 12}, {"m68000_subi_d_16" , 0xfff8, 0x0440, 0x000, 1, 8}, {"m68000_subi_16" , 0xffc0, 0x0440, 0xbf8, 1, 12}, {"m68000_subi_d_32" , 0xfff8, 0x0480, 0x000, 2, 16}, {"m68000_subi_32" , 0xffc0, 0x0480, 0xbf8, 2, 20}, {"m68000_subq_d_8" , 0xf1f8, 0x5100, 0x000, 0, 4}, {"m68000_subq_8" , 0xf1c0, 0x5100, 0xbf8, 0, 8}, {"m68000_subq_d_16" , 0xf1f8, 0x5140, 0x000, 1, 4}, {"m68000_subq_a_16" , 0xf1f8, 0x5148, 0x000, 1, 8}, {"m68000_subq_16" , 0xf1c0, 0x5140, 0xff8, 1, 8}, {"m68000_subq_d_32" , 0xf1f8, 0x5180, 0x000, 2, 8}, {"m68000_subq_a_32" , 0xf1f8, 0x5188, 0x000, 2, 8}, {"m68000_subq_32" , 0xf1c0, 0x5180, 0xff8, 2, 12}, {"m68000_subx_rr_8" , 0xf1f8, 0x9100, 0x000, 0, 4}, {"m68000_subx_rr_16" , 0xf1f8, 0x9140, 0x000, 1, 4}, {"m68000_subx_rr_32" , 0xf1f8, 0x9180, 0x000, 2, 8}, {"m68000_subx_mm_8_ax7" , 0xfff8, 0x9f08, 0x000, 0, 18}, {"m68000_subx_mm_8_ay7" , 0xf1ff, 0x910f, 0x000, 0, 18}, {"m68000_subx_mm_8_axy7" , 0xffff, 0x9f0f, 0x000, 0, 18}, {"m68000_subx_mm_8" , 0xf1f8, 0x9108, 0x000, 0, 18}, {"m68000_subx_mm_16" , 0xf1f8, 0x9148, 0x000, 1, 18}, {"m68000_subx_mm_32" , 0xf1f8, 0x9188, 0x000, 2, 30}, {"m68000_swap" , 0xfff8, 0x4840, 0x000, 1, 4}, {"m68000_tas_d" , 0xfff8, 0x4ac0, 0x000, 0, 4}, {"m68000_tas" , 0xffc0, 0x4ac0, 0xbf8, 0, 14}, {"m68000_trap" , 0xfff0, 0x4e40, 0x000, 1, 4}, {"m68020_trapt_0" , 0xffff, 0x50fc, 0x000, 0, 4}, {"m68020_trapt_16" , 0xffff, 0x50fa, 0x000, 0, 4}, {"m68020_trapt_32" , 0xffff, 0x50fb, 0x000, 0, 4}, {"m68020_trapf_0" , 0xffff, 0x51fc, 0x000, 0, 4}, {"m68020_trapf_16" , 0xffff, 0x51fa, 0x000, 0, 4}, {"m68020_trapf_32" , 0xffff, 0x51fb, 0x000, 0, 4}, {"m68020_traphi_0" , 0xffff, 0x52fc, 0x000, 0, 4}, {"m68020_traphi_16" , 0xffff, 0x52fa, 0x000, 0, 4}, {"m68020_traphi_32" , 0xffff, 0x52fb, 0x000, 0, 4}, {"m68020_trapls_0" , 0xffff, 0x53fc, 0x000, 0, 4}, {"m68020_trapls_16" , 0xffff, 0x53fa, 0x000, 0, 4}, {"m68020_trapls_32" , 0xffff, 0x53fb, 0x000, 0, 4}, {"m68020_trapcc_0" , 0xffff, 0x54fc, 0x000, 0, 4}, {"m68020_trapcc_16" , 0xffff, 0x54fa, 0x000, 0, 4}, {"m68020_trapcc_32" , 0xffff, 0x54fb, 0x000, 0, 4}, {"m68020_trapcs_0" , 0xffff, 0x55fc, 0x000, 0, 4}, {"m68020_trapcs_16" , 0xffff, 0x55fa, 0x000, 0, 4}, {"m68020_trapcs_32" , 0xffff, 0x55fb, 0x000, 0, 4}, {"m68020_trapne_0" , 0xffff, 0x56fc, 0x000, 0, 4}, {"m68020_trapne_16" , 0xffff, 0x56fa, 0x000, 0, 4}, {"m68020_trapne_32" , 0xffff, 0x56fb, 0x000, 0, 4}, {"m68020_trapeq_0" , 0xffff, 0x57fc, 0x000, 0, 4}, {"m68020_trapeq_16" , 0xffff, 0x57fa, 0x000, 0, 4}, {"m68020_trapeq_32" , 0xffff, 0x57fb, 0x000, 0, 4}, {"m68020_trapvc_0" , 0xffff, 0x58fc, 0x000, 0, 4}, {"m68020_trapvc_16" , 0xffff, 0x58fa, 0x000, 0, 4}, {"m68020_trapvc_32" , 0xffff, 0x58fb, 0x000, 0, 4}, {"m68020_trapvs_0" , 0xffff, 0x59fc, 0x000, 0, 4}, {"m68020_trapvs_16" , 0xffff, 0x59fa, 0x000, 0, 4}, {"m68020_trapvs_32" , 0xffff, 0x59fb, 0x000, 0, 4}, {"m68020_trappl_0" , 0xffff, 0x5afc, 0x000, 0, 4}, {"m68020_trappl_16" , 0xffff, 0x5afa, 0x000, 0, 4}, {"m68020_trappl_32" , 0xffff, 0x5afb, 0x000, 0, 4}, {"m68020_trapmi_0" , 0xffff, 0x5bfc, 0x000, 0, 4}, {"m68020_trapmi_16" , 0xffff, 0x5bfa, 0x000, 0, 4}, {"m68020_trapmi_32" , 0xffff, 0x5bfb, 0x000, 0, 4}, {"m68020_trapge_0" , 0xffff, 0x5cfc, 0x000, 0, 4}, {"m68020_trapge_16" , 0xffff, 0x5cfa, 0x000, 0, 4}, {"m68020_trapge_32" , 0xffff, 0x5cfb, 0x000, 0, 4}, {"m68020_traplt_0" , 0xffff, 0x5dfc, 0x000, 0, 4}, {"m68020_traplt_16" , 0xffff, 0x5dfa, 0x000, 0, 4}, {"m68020_traplt_32" , 0xffff, 0x5dfb, 0x000, 0, 4}, {"m68020_trapgt_0" , 0xffff, 0x5efc, 0x000, 0, 4}, {"m68020_trapgt_16" , 0xffff, 0x5efa, 0x000, 0, 4}, {"m68020_trapgt_32" , 0xffff, 0x5efb, 0x000, 0, 4}, {"m68020_traple_0" , 0xffff, 0x5ffc, 0x000, 0, 4}, {"m68020_traple_16" , 0xffff, 0x5ffa, 0x000, 0, 4}, {"m68020_traple_32" , 0xffff, 0x5ffb, 0x000, 0, 4}, {"m68000_trapv" , 0xffff, 0x4e76, 0x000, 1, 4}, {"m68000_tst_d_8" , 0xfff8, 0x4a00, 0x000, 0, 4}, {"m68000_tst_8" , 0xffc0, 0x4a00, 0xbf8, 0, 4}, {"m68020_tst_pcdi_8" , 0xffff, 0x4a3a, 0x000, 0, 4}, {"m68020_tst_pcix_8" , 0xffff, 0x4a3b, 0x000, 0, 4}, {"m68020_tst_imm_8" , 0xffff, 0x4a3c, 0x000, 0, 4}, {"m68000_tst_d_16" , 0xfff8, 0x4a40, 0x000, 1, 4}, {"m68020_tst_a_16" , 0xfff8, 0x4a48, 0x000, 1, 4}, {"m68000_tst_16" , 0xffc0, 0x4a40, 0xbf8, 1, 4}, {"m68020_tst_pcdi_16" , 0xffff, 0x4a7a, 0x000, 1, 4}, {"m68020_tst_pcix_16" , 0xffff, 0x4a7b, 0x000, 1, 4}, {"m68020_tst_imm_16" , 0xffff, 0x4a7c, 0x000, 1, 4}, {"m68000_tst_d_32" , 0xfff8, 0x4a80, 0x000, 2, 4}, {"m68020_tst_a_32" , 0xfff8, 0x4a88, 0x000, 2, 4}, {"m68000_tst_32" , 0xffc0, 0x4a80, 0xbf8, 2, 4}, {"m68020_tst_pcdi_32" , 0xffff, 0x4aba, 0x000, 2, 4}, {"m68020_tst_pcix_32" , 0xffff, 0x4abb, 0x000, 2, 4}, {"m68020_tst_imm_32" , 0xffff, 0x4abc, 0x000, 2, 4}, {"m68000_unlk_a7" , 0xffff, 0x4e5f, 0x000, 1, 12}, {"m68000_unlk" , 0xfff8, 0x4e58, 0x000, 1, 12}, {"m68020_unpk_rr" , 0xf1f8, 0x8180, 0x000, 0, 8}, {"m68020_unpk_mm_ax7" , 0xf1ff, 0x818f, 0x000, 0, 8}, {"m68020_unpk_mm_ay7" , 0xfff8, 0x8f88, 0x000, 0, 8}, {"m68020_unpk_mm_axy7" , 0xffff, 0x8f8f, 0x000, 0, 8}, {"m68020_unpk_mm" , 0xf1f8, 0x8188, 0x000, 0, 8}, {0, 0, 0, 0, 0} }; /* Convert a hex value written in ASCII */ int atoh(char* buff) { int accum = 0; for(;;buff++) { if(*buff >= '0' && *buff <= '9') { accum <<= 4; accum += *buff - '0'; } else if(*buff >= 'a' && *buff <= 'f') { accum <<= 4; accum += *buff - 'a' + 10; } else break; } return accum; } /* Safe version of fgets that works on Macs and PCs */ char *safe_fgets(char * s, int n, FILE * file) { char *result = fgets(s, n, file); if (s[0] == '\r') memcpy(s, s + 1, n - 1); return result; } char* modify_ea_string(char* old_ea_string, char* insert_string) { static char buff[300]; static char* blank = ""; char end_bit[200]; char* ea_start; char* ea_end; if(strstr(old_ea_string, "uint ea") != NULL) return blank; strcpy(buff, old_ea_string); ea_start = strstr(buff, "m68ki_get_ea_"); ea_end = *(ea_start+13) == '8' ? ea_start + 16 : ea_start + 17; strcpy(end_bit, ea_end); sprintf(ea_start, "%s%s", insert_string, end_bit); return buff; } char* modify_imm_string(char* old_ea_string, char* insert_string) { static char buff[300]; static char* blank = ""; char end_bit[200]; char* real_start; char* ea_start; char* ea_end; if(strstr(old_ea_string, "uint ea") != NULL) return blank; strcpy(buff, old_ea_string); real_start = strstr(buff, "m68ki_read_"); ea_start = strstr(buff, "m68ki_get_ea_"); ea_end = *(ea_start+13) == '8' ? ea_start + 17 : ea_start + 18; strcpy(end_bit, ea_end); sprintf(real_start, "%s%s", insert_string, end_bit); return buff; } char* replace_clk_string(char* old_clk_string, char* replace_string, int add_value) { static char buff[300]; char spaces[200]; char guts[30]; char* guts_start; char* guts_end; char* ptr; int i; strcpy(spaces, old_clk_string); for( i = 0; i < 199; i++ ) if( !isspace(spaces[i]) ) break; spaces[i] = 0; guts_start = strstr(old_clk_string, "(") + 1; strcpy(guts, guts_start); guts_end = strstr(guts, ")"); while((ptr = strstr(guts_end+1, ")")) != NULL) guts_end = ptr; *guts_end = 0; sprintf(buff, "%s%s(%s+%d);\n", spaces, replace_string, guts, add_value); return buff; } int get_clk_add(int func_num, int ea_mode) { if(strcmp(g_func_table[func_num].name, "m68000_jmp") == 0) return g_jmp_cycle_table[ea_mode]; if(strcmp(g_func_table[func_num].name, "m68000_jsr") == 0) return g_jsr_cycle_table[ea_mode]; if(strcmp(g_func_table[func_num].name, "m68000_lea") == 0) return g_lea_cycle_table[ea_mode]; if(strcmp(g_func_table[func_num].name, "m68000_pea") == 0) return g_pea_cycle_table[ea_mode]; if(strcmp(g_func_table[func_num].name, "m68010_moves_8") == 0 || strcmp(g_func_table[func_num].name, "m68010_moves_16") == 0) return g_moves_bw_cycle_table[ea_mode]; if(strcmp(g_func_table[func_num].name, "m68000_moves_32") == 0) return g_moves_l_cycle_table[ea_mode]; /* ASG: added these cases -- immediate modes take 2 extra cycles here */ if(ea_mode == 0x3c && (strcmp(g_func_table[func_num].name, "m68000_add_er_32") == 0 || strcmp(g_func_table[func_num].name, "m68000_adda_32") == 0 || strcmp(g_func_table[func_num].name, "m68000_and_er_32") == 0 || strcmp(g_func_table[func_num].name, "m68000_or_er_32") == 0 || strcmp(g_func_table[func_num].name, "m68000_sub_er_32") == 0 || strcmp(g_func_table[func_num].name, "m68000_suba_32") == 0)) return g_ea_cycle_table[g_func_table[func_num].size][ea_mode] + 2; return g_ea_cycle_table[g_func_table[func_num].size][ea_mode]; } void add_op_header(FILE* filep, char low, char high) { fprintf(filep, "#include \"m68kcpu.h\"\n\n"); fprintf(filep, "#include \"m68kops.h\"\n\n"); fprintf(filep, "/* ======================================================================== */\n"); fprintf(filep, "/* ======================= INSTRUCTION HANDLERS %c-%c ======================= */\n", low, high); fprintf(filep, "/* ======================================================================== */\n"); fprintf(filep, "/* Instruction handler function names follow this convention:\n"); fprintf(filep, " *\n"); fprintf(filep, " * m68000_NAME_EXTENSIONS(void)\n"); fprintf(filep, " * where NAME is the name of the opcode it handles and EXTENSIONS are any\n"); fprintf(filep, " * extensions for special instances of that opcode.\n"); fprintf(filep, " *\n"); fprintf(filep, " * Examples:\n"); fprintf(filep, " * m68000_add_er_ai_8(): add opcode, from effective address to register,\n"); fprintf(filep, " * using address register indirect, size = byte\n"); fprintf(filep, " *\n"); fprintf(filep, " * m68000_asr_s_8(): arithmetic shift right, static count, size = byte\n"); fprintf(filep, " *\n"); fprintf(filep, " *\n"); fprintf(filep, " * Note: move uses the form m68000_move_DST_SRC_SIZE\n"); fprintf(filep, " *\n"); fprintf(filep, " * Common extensions:\n"); fprintf(filep, " * 8 : size = byte\n"); fprintf(filep, " * 16 : size = word\n"); fprintf(filep, " * 32 : size = long\n"); fprintf(filep, " * rr : register to register\n"); fprintf(filep, " * mm : memory to memory\n"); fprintf(filep, " * a7 : using a7 register\n"); fprintf(filep, " * ax7 : using a7 in X part of instruction (....XXX......YYY)\n"); fprintf(filep, " * ay7 : using a7 in Y part of instruction (....XXX......YYY)\n"); fprintf(filep, " * axy7: using a7 in both parts of instruction (....XXX......YYY)\n"); fprintf(filep, " * r : register\n"); fprintf(filep, " * s : static\n"); fprintf(filep, " * er : effective address -> register\n"); fprintf(filep, " * re : register -> effective address\n"); fprintf(filep, " * ea : using effective address mode of operation\n"); fprintf(filep, " * d : data register direct\n"); fprintf(filep, " * a : address register direct\n"); fprintf(filep, " * ai : address register indirect\n"); fprintf(filep, " * pi : address register indirect with postincrement\n"); fprintf(filep, " * pi7 : address register 7 indirect with postincrement\n"); fprintf(filep, " * pd : address register indirect with predecrement\n"); fprintf(filep, " * pd7 : address register 7 indirect with predecrement\n"); fprintf(filep, " * di : address register indirect with displacement\n"); fprintf(filep, " * ix : address register indirect with index\n"); fprintf(filep, " * aw : absolute word\n"); fprintf(filep, " * al : absolute long\n"); fprintf(filep, " * pcdi: program counter with displacement\n"); fprintf(filep, " * pcix: program counter with index\n"); fprintf(filep, " */\n\n\n"); } void add_prototype_header(FILE* filep) { fprintf(filep, "#ifndef M68KOPS__HEADER\n"); fprintf(filep, "#define M68KOPS__HEADER\n\n"); } void add_prototype_footer(FILE* filep) { fprintf(filep, "\n#endif /* M68KOPS__HEADER */\n"); } void add_table_header(FILE* filep) { fprintf(filep, "/* ======================================================================== */\n"); fprintf(filep, "/* ========================= OPCODE TABLE BUILDER ========================= */\n"); fprintf(filep, "/* ======================================================================== */\n\n"); fprintf(filep, "#include \"m68kops.h\"\n"); fprintf(filep, "#include \"m68kcpu.h\"\n"); fprintf(filep, "#include \n\n"); fprintf(filep, "#include \n\n"); fprintf(filep, "extern void (*m68k_instruction_jump_table[])(void); /* opcode handler jump table */\n\n"); fprintf(filep, "/* This is used to generate the opcode handler jump table */\n"); fprintf(filep, "typedef struct\n"); fprintf(filep, "{\n"); fprintf(filep, "\tvoid (*opcode_handler)(void); /* handler function */\n"); fprintf(filep, "\tuint bits;\t\t\t/* number of bits set in mask */\n"); fprintf(filep, "\tuint mask;\t\t\t/* mask on opcode */\n"); fprintf(filep, "\tuint match;\t\t\t/* what to match after masking */\n"); fprintf(filep, "} opcode_handler_struct;\n\n\n"); fprintf(filep, "/* Opcode handler table */\n"); fprintf(filep, "static opcode_handler_struct m68k_opcode_handler_table[] =\n"); fprintf(filep, "{\n"); fprintf(filep, "/* opcode handler mask match */\n"); } void add_table_footer(FILE* filep) { fprintf(filep, "\t{0, 0, 0, 0}\n"); fprintf(filep, "};\n\n\n"); fprintf(filep, "/*\n"); fprintf(filep, " * Comparison function for qsort()\n"); fprintf(filep, " * For entries with an equal number of set bits in\n"); fprintf(filep, " * the mask compare the match values\n"); fprintf(filep, " */\n"); // Dave commented out fprintf(filep, "static int /* DECL_SPEC */ compare_nof_true_bits(const void* aptr, const void* bptr)\n"); fprintf(filep, "{\n"); fprintf(filep, "\tconst opcode_handler_struct *a = aptr, *b = bptr;\n"); fprintf(filep, "\tif( a->bits != b->bits )\n"); fprintf(filep, "\t\treturn a->bits - b->bits;\n"); fprintf(filep, "\tif( a->mask != b->mask )\n"); fprintf(filep, "\t\treturn a->mask - b->mask;\n"); fprintf(filep, "\treturn a->match - b->match;\n"); fprintf(filep, "}\n\n"); fprintf(filep, "/* Build the opcode handler jump table */\n"); fprintf(filep, "void m68ki_build_opcode_table(void)\n"); fprintf(filep, "{\n"); fprintf(filep, "\topcode_handler_struct *ostruct;\n"); fprintf(filep, "\tuint table_length = 0;\n"); fprintf(filep, "\tint i,j;\n"); fprintf(filep, "\n"); fprintf(filep, "\tfor(ostruct = m68k_opcode_handler_table;ostruct->opcode_handler != 0;ostruct++)\n"); fprintf(filep, "\t\ttable_length++;\n"); fprintf(filep, "\n"); fprintf(filep, "\tqsort((void *)m68k_opcode_handler_table, table_length, sizeof(m68k_opcode_handler_table[0]), compare_nof_true_bits);\n"); fprintf(filep, "\n"); fprintf(filep, "\tfor( i = 0; i < 0x10000; i++ )\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\t/* default to illegal */\n"); fprintf(filep, "\t\tm68k_instruction_jump_table[i] = m68000_illegal;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\n"); fprintf(filep, "\tostruct = m68k_opcode_handler_table;\n"); fprintf(filep, "\twhile (ostruct->mask != 0xff00)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tfor (i = 0;i < 0x10000;i++)\n"); fprintf(filep, "\t\t{\n"); fprintf(filep, "\t\t\tif ((i & ostruct->mask) == ostruct->match)\n"); fprintf(filep, "\t\t\t{\n"); fprintf(filep, "\t\t\t\tm68k_instruction_jump_table[i] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\t\t}\n"); fprintf(filep, "\t\t}\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\twhile (ostruct->mask == 0xff00)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tfor (i = 0;i <= 0xff;i++)\n"); fprintf(filep, "\t\t\tm68k_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\twhile (ostruct->mask == 0xf1f8)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tfor (i = 0;i < 8;i++)\n"); fprintf(filep, "\t\t{\n"); fprintf(filep, "\t\t\tfor (j = 0;j < 8;j++)\n"); fprintf(filep, "\t\t\t{\n"); fprintf(filep, "\t\t\t\tm68k_instruction_jump_table[ostruct->match | (i << 9) | j] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\t\t}\n"); fprintf(filep, "\t\t}\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\twhile (ostruct->mask == 0xfff0)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tfor (i = 0;i <= 0x0f;i++)\n"); fprintf(filep, "\t\t\tm68k_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\twhile (ostruct->mask == 0xf1ff)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tfor (i = 0;i <= 0x07;i++)\n"); fprintf(filep, "\t\t\tm68k_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\twhile (ostruct->mask == 0xfff8)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tfor (i = 0;i <= 0x07;i++)\n"); fprintf(filep, "\t\t\tm68k_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "\twhile (ostruct->mask == 0xffff)\n"); fprintf(filep, "\t{\n"); fprintf(filep, "\t\tm68k_instruction_jump_table[ostruct->match] = ostruct->opcode_handler;\n"); fprintf(filep, "\t\tostruct++;\n"); fprintf(filep, "\t}\n"); fprintf(filep, "}\n"); } int generate_funcs(FILE* file_ac, FILE* file_dm, FILE* file_nz) { FILE* input_file; FILE* output_file; static char func_lines[200][300]; char name[200]; char full_name[200]; char* name_start; char* name_end; char insert[30]; int insert_pt; int num_lines = 0; int ea_line = 0; int i; int func_num; int ea; int size; char ea_spaces[200]; /* Our input file is m68k_in.c */ if((input_file=fopen(g_m68k_in_c, "rt")) == NULL) { sprintf(name, "can't open %s", g_m68k_in_c); perror(name); exit(-1); } /* Add the header to the first output file */ add_op_header(output_file = file_ac, 'A', 'C'); for(;;) { /* Find the first line of the function */ func_lines[0][0] = '\n'; while(func_lines[0][0] == '\n') if(safe_fgets(func_lines[0], 200, input_file) == NULL) exit(0); /* Extract the name of the function */ name_start = strstr(func_lines[0], "m68"); strcpy(name, name_start); name_end = strstr(name, "("); *name_end = '\0'; while( name_end > name && name_end[-1] == ' ' ) *--name_end = '\0'; strcpy(full_name, name); /* Change output files if we pass 'c' or 'n' */ if(output_file == file_ac && full_name[7] > 'c') add_op_header(output_file = file_dm, 'D', 'M'); if(output_file == file_dm && full_name[7] > 'm') add_op_header(output_file = file_nz, 'N', 'Z'); /* Find the point in the name to insert ea mode bits */ switch(*(name_end-1)) { case '8': insert_pt = - 2; break; case '2': case '6': insert_pt = - 3; break; default: insert_pt = 0; } strcpy(insert, name_end+insert_pt); *(name_end+insert_pt) = 0; /* Get the rest of the function and find the "get_ea" bit */ num_lines = 0; ea_line = 0; for(i=1;i<200;i++) { if(safe_fgets(func_lines[i], 200, input_file) == NULL) exit(0); if(func_lines[i][0] == '}') { num_lines = i+1; /* don't cut off the } */ break; } if(strstr(func_lines[i], "m68ki_get_ea_8") != NULL || strstr(func_lines[i], "m68ki_get_ea_16") != NULL || strstr(func_lines[i], "m68ki_get_ea_32") != NULL) ea_line = i; } /* Look for the function in the function table */ func_num = -1; /* find what function it is */ for(i=0;g_func_table[i].name != NULL;i++) if(strcmp(full_name, g_func_table[i].name) == 0) func_num = i; if(func_num == -1) { printf("Unable to find function %s\n", full_name); g_errors++; continue; } /* Get the ea mask and size of function */ ea = g_func_table[func_num].ea_mask; size = g_func_table[func_num].size; /* If there's no get_ea part to this function */ if(ea_line == 0) { /* Error: there's no get_ea, but the function table says ther should be) */ if(ea != 0) { printf("Can't find EA line for function %s\n", full_name); g_errors++; continue; } /* This function doesn't need any ea modes added */ /* print function as-is */ for(i=0;i 1 ) { char *p; strcpy( output_path, av[1] ); for( p = strchr(output_path, '\\'); p; p = strchr(p, '\\') ) *p = '/'; if( output_path[strlen(output_path)-1] != '/' ) strcat( output_path, "/" ); if( ac > 2 ) strcpy(g_m68k_in_c, av[2]); } sprintf(filename, "%s%s", output_path, prototype_filename); if((prototype_file = fopen(filename, "wt")) == NULL) { fprintf(stderr, "Unable to create prototype file (%s)\n", filename); perror(""); exit(-1); } sprintf(filename, "%s%s", output_path, table_filename); if((table_file = fopen(filename, "wt")) == NULL) { fprintf(stderr, "Unable to create table file (%s)\n", filename); perror(""); exit(-1); } sprintf(filename, "%s%s", output_path, ops_ac_filename); if((ops_ac_file = fopen(filename, "wt")) == NULL) { fprintf(stderr, "Unable to create ops a-c file (%s)\n", filename); perror(""); exit(-1); } sprintf(filename, "%s%s", output_path, ops_dm_filename); if((ops_dm_file = fopen(filename, "wt")) == NULL) { fprintf(stderr, "Unable to create ops d-m file (%s)\n", filename); exit(-1); } sprintf(filename, "%s%s", output_path, ops_nz_filename); if((ops_nz_file = fopen(filename, "wt")) == NULL) { fprintf(stderr, "Unable to create ops n-z file (%s)\n", filename); perror(""); exit(-1); } add_prototype_header(prototype_file); generate_prototypes(prototype_file); add_prototype_footer(prototype_file); add_table_header(table_file); generate_table(table_file); add_table_footer(table_file); generate_funcs(ops_ac_file, ops_dm_file, ops_nz_file); fclose(prototype_file); fclose(table_file); fclose(ops_ac_file); fclose(ops_dm_file); fclose(ops_nz_file); printf("Process completed with %d errors\n", g_errors); return g_errors ? -1 : 0; } dgen-sdl-1.23/musa/m68kops.h 644 1750 1750 162677 7320166715 10774 #ifndef M68KOPS__HEADER #define M68KOPS__HEADER /* ======================================================================== */ /* ============================ OPCODE HANDLERS =========================== */ /* ======================================================================== */ void m68000_1010(void); void m68000_1111(void); void m68000_abcd_rr(void); void m68000_abcd_mm_ax7(void); void m68000_abcd_mm_ay7(void); void m68000_abcd_mm_axy7(void); void m68000_abcd_mm(void); void m68000_add_er_d_8(void); void m68000_add_er_ai_8(void); void m68000_add_er_pi_8(void); void m68000_add_er_pi7_8(void); void m68000_add_er_pd_8(void); void m68000_add_er_pd7_8(void); void m68000_add_er_di_8(void); void m68000_add_er_ix_8(void); void m68000_add_er_aw_8(void); void m68000_add_er_al_8(void); void m68000_add_er_pcdi_8(void); void m68000_add_er_pcix_8(void); void m68000_add_er_i_8(void); void m68000_add_er_d_16(void); void m68000_add_er_a_16(void); void m68000_add_er_ai_16(void); void m68000_add_er_pi_16(void); void m68000_add_er_pd_16(void); void m68000_add_er_di_16(void); void m68000_add_er_ix_16(void); void m68000_add_er_aw_16(void); void m68000_add_er_al_16(void); void m68000_add_er_pcdi_16(void); void m68000_add_er_pcix_16(void); void m68000_add_er_i_16(void); void m68000_add_er_d_32(void); void m68000_add_er_a_32(void); void m68000_add_er_ai_32(void); void m68000_add_er_pi_32(void); void m68000_add_er_pd_32(void); void m68000_add_er_di_32(void); void m68000_add_er_ix_32(void); void m68000_add_er_aw_32(void); void m68000_add_er_al_32(void); void m68000_add_er_pcdi_32(void); void m68000_add_er_pcix_32(void); void m68000_add_er_i_32(void); void m68000_add_re_ai_8(void); void m68000_add_re_pi_8(void); void m68000_add_re_pi7_8(void); void m68000_add_re_pd_8(void); void m68000_add_re_pd7_8(void); void m68000_add_re_di_8(void); void m68000_add_re_ix_8(void); void m68000_add_re_aw_8(void); void m68000_add_re_al_8(void); void m68000_add_re_ai_16(void); void m68000_add_re_pi_16(void); void m68000_add_re_pd_16(void); void m68000_add_re_di_16(void); void m68000_add_re_ix_16(void); void m68000_add_re_aw_16(void); void m68000_add_re_al_16(void); void m68000_add_re_ai_32(void); void m68000_add_re_pi_32(void); void m68000_add_re_pd_32(void); void m68000_add_re_di_32(void); void m68000_add_re_ix_32(void); void m68000_add_re_aw_32(void); void m68000_add_re_al_32(void); void m68000_adda_d_16(void); void m68000_adda_a_16(void); void m68000_adda_ai_16(void); void m68000_adda_pi_16(void); void m68000_adda_pd_16(void); void m68000_adda_di_16(void); void m68000_adda_ix_16(void); void m68000_adda_aw_16(void); void m68000_adda_al_16(void); void m68000_adda_pcdi_16(void); void m68000_adda_pcix_16(void); void m68000_adda_i_16(void); void m68000_adda_d_32(void); void m68000_adda_a_32(void); void m68000_adda_ai_32(void); void m68000_adda_pi_32(void); void m68000_adda_pd_32(void); void m68000_adda_di_32(void); void m68000_adda_ix_32(void); void m68000_adda_aw_32(void); void m68000_adda_al_32(void); void m68000_adda_pcdi_32(void); void m68000_adda_pcix_32(void); void m68000_adda_i_32(void); void m68000_addi_d_8(void); void m68000_addi_ai_8(void); void m68000_addi_pi_8(void); void m68000_addi_pi7_8(void); void m68000_addi_pd_8(void); void m68000_addi_pd7_8(void); void m68000_addi_di_8(void); void m68000_addi_ix_8(void); void m68000_addi_aw_8(void); void m68000_addi_al_8(void); void m68000_addi_d_16(void); void m68000_addi_ai_16(void); void m68000_addi_pi_16(void); void m68000_addi_pd_16(void); void m68000_addi_di_16(void); void m68000_addi_ix_16(void); void m68000_addi_aw_16(void); void m68000_addi_al_16(void); void m68000_addi_d_32(void); void m68000_addi_ai_32(void); void m68000_addi_pi_32(void); void m68000_addi_pd_32(void); void m68000_addi_di_32(void); void m68000_addi_ix_32(void); void m68000_addi_aw_32(void); void m68000_addi_al_32(void); void m68000_addq_d_8(void); void m68000_addq_ai_8(void); void m68000_addq_pi_8(void); void m68000_addq_pi7_8(void); void m68000_addq_pd_8(void); void m68000_addq_pd7_8(void); void m68000_addq_di_8(void); void m68000_addq_ix_8(void); void m68000_addq_aw_8(void); void m68000_addq_al_8(void); void m68000_addq_d_16(void); void m68000_addq_a_16(void); void m68000_addq_ai_16(void); void m68000_addq_pi_16(void); void m68000_addq_pd_16(void); void m68000_addq_di_16(void); void m68000_addq_ix_16(void); void m68000_addq_aw_16(void); void m68000_addq_al_16(void); void m68000_addq_d_32(void); void m68000_addq_a_32(void); void m68000_addq_ai_32(void); void m68000_addq_pi_32(void); void m68000_addq_pd_32(void); void m68000_addq_di_32(void); void m68000_addq_ix_32(void); void m68000_addq_aw_32(void); void m68000_addq_al_32(void); void m68000_addx_rr_8(void); void m68000_addx_rr_16(void); void m68000_addx_rr_32(void); void m68000_addx_mm_8_ax7(void); void m68000_addx_mm_8_ay7(void); void m68000_addx_mm_8_axy7(void); void m68000_addx_mm_8(void); void m68000_addx_mm_16(void); void m68000_addx_mm_32(void); void m68000_and_er_d_8(void); void m68000_and_er_ai_8(void); void m68000_and_er_pi_8(void); void m68000_and_er_pi7_8(void); void m68000_and_er_pd_8(void); void m68000_and_er_pd7_8(void); void m68000_and_er_di_8(void); void m68000_and_er_ix_8(void); void m68000_and_er_aw_8(void); void m68000_and_er_al_8(void); void m68000_and_er_pcdi_8(void); void m68000_and_er_pcix_8(void); void m68000_and_er_i_8(void); void m68000_and_er_d_16(void); void m68000_and_er_ai_16(void); void m68000_and_er_pi_16(void); void m68000_and_er_pd_16(void); void m68000_and_er_di_16(void); void m68000_and_er_ix_16(void); void m68000_and_er_aw_16(void); void m68000_and_er_al_16(void); void m68000_and_er_pcdi_16(void); void m68000_and_er_pcix_16(void); void m68000_and_er_i_16(void); void m68000_and_er_d_32(void); void m68000_and_er_ai_32(void); void m68000_and_er_pi_32(void); void m68000_and_er_pd_32(void); void m68000_and_er_di_32(void); void m68000_and_er_ix_32(void); void m68000_and_er_aw_32(void); void m68000_and_er_al_32(void); void m68000_and_er_pcdi_32(void); void m68000_and_er_pcix_32(void); void m68000_and_er_i_32(void); void m68000_and_re_ai_8(void); void m68000_and_re_pi_8(void); void m68000_and_re_pi7_8(void); void m68000_and_re_pd_8(void); void m68000_and_re_pd7_8(void); void m68000_and_re_di_8(void); void m68000_and_re_ix_8(void); void m68000_and_re_aw_8(void); void m68000_and_re_al_8(void); void m68000_and_re_ai_16(void); void m68000_and_re_pi_16(void); void m68000_and_re_pd_16(void); void m68000_and_re_di_16(void); void m68000_and_re_ix_16(void); void m68000_and_re_aw_16(void); void m68000_and_re_al_16(void); void m68000_and_re_ai_32(void); void m68000_and_re_pi_32(void); void m68000_and_re_pd_32(void); void m68000_and_re_di_32(void); void m68000_and_re_ix_32(void); void m68000_and_re_aw_32(void); void m68000_and_re_al_32(void); void m68000_andi_to_ccr(void); void m68000_andi_to_sr(void); void m68000_andi_d_8(void); void m68000_andi_ai_8(void); void m68000_andi_pi_8(void); void m68000_andi_pi7_8(void); void m68000_andi_pd_8(void); void m68000_andi_pd7_8(void); void m68000_andi_di_8(void); void m68000_andi_ix_8(void); void m68000_andi_aw_8(void); void m68000_andi_al_8(void); void m68000_andi_d_16(void); void m68000_andi_ai_16(void); void m68000_andi_pi_16(void); void m68000_andi_pd_16(void); void m68000_andi_di_16(void); void m68000_andi_ix_16(void); void m68000_andi_aw_16(void); void m68000_andi_al_16(void); void m68000_andi_d_32(void); void m68000_andi_ai_32(void); void m68000_andi_pi_32(void); void m68000_andi_pd_32(void); void m68000_andi_di_32(void); void m68000_andi_ix_32(void); void m68000_andi_aw_32(void); void m68000_andi_al_32(void); void m68000_asr_s_8(void); void m68000_asr_s_16(void); void m68000_asr_s_32(void); void m68000_asr_r_8(void); void m68000_asr_r_16(void); void m68000_asr_r_32(void); void m68000_asr_ea_ai(void); void m68000_asr_ea_pi(void); void m68000_asr_ea_pd(void); void m68000_asr_ea_di(void); void m68000_asr_ea_ix(void); void m68000_asr_ea_aw(void); void m68000_asr_ea_al(void); void m68000_asl_s_8(void); void m68000_asl_s_16(void); void m68000_asl_s_32(void); void m68000_asl_r_8(void); void m68000_asl_r_16(void); void m68000_asl_r_32(void); void m68000_asl_ea_ai(void); void m68000_asl_ea_pi(void); void m68000_asl_ea_pd(void); void m68000_asl_ea_di(void); void m68000_asl_ea_ix(void); void m68000_asl_ea_aw(void); void m68000_asl_ea_al(void); void m68000_bhi_16(void); void m68020_bhi_32(void); void m68000_bhi_8(void); void m68000_bls_16(void); void m68020_bls_32(void); void m68000_bls_8(void); void m68000_bcc_16(void); void m68020_bcc_32(void); void m68000_bcc_8(void); void m68000_bcs_16(void); void m68020_bcs_32(void); void m68000_bcs_8(void); void m68000_bne_16(void); void m68020_bne_32(void); void m68000_bne_8(void); void m68000_beq_16(void); void m68020_beq_32(void); void m68000_beq_8(void); void m68000_bvc_16(void); void m68020_bvc_32(void); void m68000_bvc_8(void); void m68000_bvs_16(void); void m68020_bvs_32(void); void m68000_bvs_8(void); void m68000_bpl_16(void); void m68020_bpl_32(void); void m68000_bpl_8(void); void m68000_bmi_16(void); void m68020_bmi_32(void); void m68000_bmi_8(void); void m68000_bge_16(void); void m68020_bge_32(void); void m68000_bge_8(void); void m68000_blt_16(void); void m68020_blt_32(void); void m68000_blt_8(void); void m68000_bgt_16(void); void m68020_bgt_32(void); void m68000_bgt_8(void); void m68000_ble_16(void); void m68020_ble_32(void); void m68000_ble_8(void); void m68000_bchg_r_d(void); void m68000_bchg_r_ai(void); void m68000_bchg_r_pi(void); void m68000_bchg_r_pi7(void); void m68000_bchg_r_pd(void); void m68000_bchg_r_pd7(void); void m68000_bchg_r_di(void); void m68000_bchg_r_ix(void); void m68000_bchg_r_aw(void); void m68000_bchg_r_al(void); void m68000_bchg_s_d(void); void m68000_bchg_s_ai(void); void m68000_bchg_s_pi(void); void m68000_bchg_s_pi7(void); void m68000_bchg_s_pd(void); void m68000_bchg_s_pd7(void); void m68000_bchg_s_di(void); void m68000_bchg_s_ix(void); void m68000_bchg_s_aw(void); void m68000_bchg_s_al(void); void m68000_bclr_r_d(void); void m68000_bclr_r_ai(void); void m68000_bclr_r_pi(void); void m68000_bclr_r_pi7(void); void m68000_bclr_r_pd(void); void m68000_bclr_r_pd7(void); void m68000_bclr_r_di(void); void m68000_bclr_r_ix(void); void m68000_bclr_r_aw(void); void m68000_bclr_r_al(void); void m68000_bclr_s_d(void); void m68000_bclr_s_ai(void); void m68000_bclr_s_pi(void); void m68000_bclr_s_pi7(void); void m68000_bclr_s_pd(void); void m68000_bclr_s_pd7(void); void m68000_bclr_s_di(void); void m68000_bclr_s_ix(void); void m68000_bclr_s_aw(void); void m68000_bclr_s_al(void); void m68020_bfchg_d(void); void m68020_bfchg_ai(void); void m68020_bfchg_di(void); void m68020_bfchg_ix(void); void m68020_bfchg_aw(void); void m68020_bfchg_al(void); void m68020_bfclr_d(void); void m68020_bfclr_ai(void); void m68020_bfclr_di(void); void m68020_bfclr_ix(void); void m68020_bfclr_aw(void); void m68020_bfclr_al(void); void m68020_bfexts_d(void); void m68020_bfexts_ai(void); void m68020_bfexts_di(void); void m68020_bfexts_ix(void); void m68020_bfexts_aw(void); void m68020_bfexts_al(void); void m68020_bfexts_pcdi(void); void m68020_bfexts_pcix(void); void m68020_bfextu_d(void); void m68020_bfextu_ai(void); void m68020_bfextu_di(void); void m68020_bfextu_ix(void); void m68020_bfextu_aw(void); void m68020_bfextu_al(void); void m68020_bfextu_pcdi(void); void m68020_bfextu_pcix(void); void m68020_bfffo_d(void); void m68020_bfffo_ai(void); void m68020_bfffo_di(void); void m68020_bfffo_ix(void); void m68020_bfffo_aw(void); void m68020_bfffo_al(void); void m68020_bfffo_pcdi(void); void m68020_bfffo_pcix(void); void m68020_bfins_d(void); void m68020_bfins_ai(void); void m68020_bfins_di(void); void m68020_bfins_ix(void); void m68020_bfins_aw(void); void m68020_bfins_al(void); void m68020_bfset_d(void); void m68020_bfset_ai(void); void m68020_bfset_di(void); void m68020_bfset_ix(void); void m68020_bfset_aw(void); void m68020_bfset_al(void); void m68020_bftst_d(void); void m68020_bftst_ai(void); void m68020_bftst_di(void); void m68020_bftst_ix(void); void m68020_bftst_aw(void); void m68020_bftst_al(void); void m68020_bftst_pcdi(void); void m68020_bftst_pcix(void); void m68010_bkpt(void); void m68000_bra_16(void); void m68020_bra_32(void); void m68000_bra_8(void); void m68000_bset_r_d(void); void m68000_bset_r_ai(void); void m68000_bset_r_pi(void); void m68000_bset_r_pi7(void); void m68000_bset_r_pd(void); void m68000_bset_r_pd7(void); void m68000_bset_r_di(void); void m68000_bset_r_ix(void); void m68000_bset_r_aw(void); void m68000_bset_r_al(void); void m68000_bset_s_d(void); void m68000_bset_s_ai(void); void m68000_bset_s_pi(void); void m68000_bset_s_pi7(void); void m68000_bset_s_pd(void); void m68000_bset_s_pd7(void); void m68000_bset_s_di(void); void m68000_bset_s_ix(void); void m68000_bset_s_aw(void); void m68000_bset_s_al(void); void m68000_bsr_16(void); void m68020_bsr_32(void); void m68000_bsr_8(void); void m68000_btst_r_d(void); void m68000_btst_r_ai(void); void m68000_btst_r_pi(void); void m68000_btst_r_pi7(void); void m68000_btst_r_pd(void); void m68000_btst_r_pd7(void); void m68000_btst_r_di(void); void m68000_btst_r_ix(void); void m68000_btst_r_aw(void); void m68000_btst_r_al(void); void m68000_btst_r_pcdi(void); void m68000_btst_r_pcix(void); void m68000_btst_r_i(void); void m68000_btst_s_d(void); void m68000_btst_s_ai(void); void m68000_btst_s_pi(void); void m68000_btst_s_pi7(void); void m68000_btst_s_pd(void); void m68000_btst_s_pd7(void); void m68000_btst_s_di(void); void m68000_btst_s_ix(void); void m68000_btst_s_aw(void); void m68000_btst_s_al(void); void m68000_btst_s_pcdi(void); void m68000_btst_s_pcix(void); void m68020_callm_ai(void); void m68020_callm_di(void); void m68020_callm_ix(void); void m68020_callm_aw(void); void m68020_callm_al(void); void m68020_callm_pcdi(void); void m68020_callm_pcix(void); void m68020_cas_ai_8(void); void m68020_cas_pi_8(void); void m68020_cas_pi7_8(void); void m68020_cas_pd_8(void); void m68020_cas_pd7_8(void); void m68020_cas_di_8(void); void m68020_cas_ix_8(void); void m68020_cas_aw_8(void); void m68020_cas_al_8(void); void m68020_cas_ai_16(void); void m68020_cas_pi_16(void); void m68020_cas_pd_16(void); void m68020_cas_di_16(void); void m68020_cas_ix_16(void); void m68020_cas_aw_16(void); void m68020_cas_al_16(void); void m68020_cas_ai_32(void); void m68020_cas_pi_32(void); void m68020_cas_pd_32(void); void m68020_cas_di_32(void); void m68020_cas_ix_32(void); void m68020_cas_aw_32(void); void m68020_cas_al_32(void); void m68020_cas2_16(void); void m68020_cas2_32(void); void m68000_chk_d_16(void); void m68000_chk_ai_16(void); void m68000_chk_pi_16(void); void m68000_chk_pd_16(void); void m68000_chk_di_16(void); void m68000_chk_ix_16(void); void m68000_chk_aw_16(void); void m68000_chk_al_16(void); void m68000_chk_pcdi_16(void); void m68000_chk_pcix_16(void); void m68000_chk_i_16(void); void m68020_chk_d_32(void); void m68020_chk_ai_32(void); void m68020_chk_pi_32(void); void m68020_chk_pd_32(void); void m68020_chk_di_32(void); void m68020_chk_ix_32(void); void m68020_chk_aw_32(void); void m68020_chk_al_32(void); void m68020_chk_pcdi_32(void); void m68020_chk_pcix_32(void); void m68020_chk_i_32(void); void m68020_chk2_cmp2_ai_8(void); void m68020_chk2_cmp2_di_8(void); void m68020_chk2_cmp2_ix_8(void); void m68020_chk2_cmp2_aw_8(void); void m68020_chk2_cmp2_al_8(void); void m68020_chk2_cmp2_pcdi_8(void); void m68020_chk2_cmp2_pcix_8(void); void m68020_chk2_cmp2_ai_16(void); void m68020_chk2_cmp2_di_16(void); void m68020_chk2_cmp2_ix_16(void); void m68020_chk2_cmp2_aw_16(void); void m68020_chk2_cmp2_al_16(void); void m68020_chk2_cmp2_pcdi_16(void); void m68020_chk2_cmp2_pcix_16(void); void m68020_chk2_cmp2_ai_32(void); void m68020_chk2_cmp2_di_32(void); void m68020_chk2_cmp2_ix_32(void); void m68020_chk2_cmp2_aw_32(void); void m68020_chk2_cmp2_al_32(void); void m68020_chk2_cmp2_pcdi_32(void); void m68020_chk2_cmp2_pcix_32(void); void m68000_clr_d_8(void); void m68000_clr_ai_8(void); void m68000_clr_pi_8(void); void m68000_clr_pi7_8(void); void m68000_clr_pd_8(void); void m68000_clr_pd7_8(void); void m68000_clr_di_8(void); void m68000_clr_ix_8(void); void m68000_clr_aw_8(void); void m68000_clr_al_8(void); void m68000_clr_d_16(void); void m68000_clr_ai_16(void); void m68000_clr_pi_16(void); void m68000_clr_pd_16(void); void m68000_clr_di_16(void); void m68000_clr_ix_16(void); void m68000_clr_aw_16(void); void m68000_clr_al_16(void); void m68000_clr_d_32(void); void m68000_clr_ai_32(void); void m68000_clr_pi_32(void); void m68000_clr_pd_32(void); void m68000_clr_di_32(void); void m68000_clr_ix_32(void); void m68000_clr_aw_32(void); void m68000_clr_al_32(void); void m68000_cmp_d_8(void); void m68000_cmp_ai_8(void); void m68000_cmp_pi_8(void); void m68000_cmp_pi7_8(void); void m68000_cmp_pd_8(void); void m68000_cmp_pd7_8(void); void m68000_cmp_di_8(void); void m68000_cmp_ix_8(void); void m68000_cmp_aw_8(void); void m68000_cmp_al_8(void); void m68000_cmp_pcdi_8(void); void m68000_cmp_pcix_8(void); void m68000_cmp_i_8(void); void m68000_cmp_d_16(void); void m68000_cmp_a_16(void); void m68000_cmp_ai_16(void); void m68000_cmp_pi_16(void); void m68000_cmp_pd_16(void); void m68000_cmp_di_16(void); void m68000_cmp_ix_16(void); void m68000_cmp_aw_16(void); void m68000_cmp_al_16(void); void m68000_cmp_pcdi_16(void); void m68000_cmp_pcix_16(void); void m68000_cmp_i_16(void); void m68000_cmp_d_32(void); void m68000_cmp_a_32(void); void m68000_cmp_ai_32(void); void m68000_cmp_pi_32(void); void m68000_cmp_pd_32(void); void m68000_cmp_di_32(void); void m68000_cmp_ix_32(void); void m68000_cmp_aw_32(void); void m68000_cmp_al_32(void); void m68000_cmp_pcdi_32(void); void m68000_cmp_pcix_32(void); void m68000_cmp_i_32(void); void m68000_cmpa_d_16(void); void m68000_cmpa_a_16(void); void m68000_cmpa_ai_16(void); void m68000_cmpa_pi_16(void); void m68000_cmpa_pd_16(void); void m68000_cmpa_di_16(void); void m68000_cmpa_ix_16(void); void m68000_cmpa_aw_16(void); void m68000_cmpa_al_16(void); void m68000_cmpa_pcdi_16(void); void m68000_cmpa_pcix_16(void); void m68000_cmpa_i_16(void); void m68000_cmpa_d_32(void); void m68000_cmpa_a_32(void); void m68000_cmpa_ai_32(void); void m68000_cmpa_pi_32(void); void m68000_cmpa_pd_32(void); void m68000_cmpa_di_32(void); void m68000_cmpa_ix_32(void); void m68000_cmpa_aw_32(void); void m68000_cmpa_al_32(void); void m68000_cmpa_pcdi_32(void); void m68000_cmpa_pcix_32(void); void m68000_cmpa_i_32(void); void m68000_cmpi_d_8(void); void m68000_cmpi_ai_8(void); void m68000_cmpi_pi_8(void); void m68000_cmpi_pi7_8(void); void m68000_cmpi_pd_8(void); void m68000_cmpi_pd7_8(void); void m68000_cmpi_di_8(void); void m68000_cmpi_ix_8(void); void m68000_cmpi_aw_8(void); void m68000_cmpi_al_8(void); void m68020_cmpi_pcdi_8(void); void m68020_cmpi_pcix_8(void); void m68000_cmpi_d_16(void); void m68000_cmpi_ai_16(void); void m68000_cmpi_pi_16(void); void m68000_cmpi_pd_16(void); void m68000_cmpi_di_16(void); void m68000_cmpi_ix_16(void); void m68000_cmpi_aw_16(void); void m68000_cmpi_al_16(void); void m68020_cmpi_pcdi_16(void); void m68020_cmpi_pcix_16(void); void m68000_cmpi_d_32(void); void m68000_cmpi_ai_32(void); void m68000_cmpi_pi_32(void); void m68000_cmpi_pd_32(void); void m68000_cmpi_di_32(void); void m68000_cmpi_ix_32(void); void m68000_cmpi_aw_32(void); void m68000_cmpi_al_32(void); void m68020_cmpi_pcdi_32(void); void m68020_cmpi_pcix_32(void); void m68000_cmpm_8_ax7(void); void m68000_cmpm_8_ay7(void); void m68000_cmpm_8_axy7(void); void m68000_cmpm_8(void); void m68000_cmpm_16(void); void m68000_cmpm_32(void); void m68020_cpbcc(void); void m68020_cpdbcc(void); void m68020_cpgen(void); void m68020_cpscc(void); void m68020_cptrapcc(void); void m68000_dbt(void); void m68000_dbf(void); void m68000_dbhi(void); void m68000_dbls(void); void m68000_dbcc(void); void m68000_dbcs(void); void m68000_dbne(void); void m68000_dbeq(void); void m68000_dbvc(void); void m68000_dbvs(void); void m68000_dbpl(void); void m68000_dbmi(void); void m68000_dbge(void); void m68000_dblt(void); void m68000_dbgt(void); void m68000_dble(void); void m68000_divs_d_16(void); void m68000_divs_ai_16(void); void m68000_divs_pi_16(void); void m68000_divs_pd_16(void); void m68000_divs_di_16(void); void m68000_divs_ix_16(void); void m68000_divs_aw_16(void); void m68000_divs_al_16(void); void m68000_divs_pcdi_16(void); void m68000_divs_pcix_16(void); void m68000_divs_i_16(void); void m68000_divu_d_16(void); void m68000_divu_ai_16(void); void m68000_divu_pi_16(void); void m68000_divu_pd_16(void); void m68000_divu_di_16(void); void m68000_divu_ix_16(void); void m68000_divu_aw_16(void); void m68000_divu_al_16(void); void m68000_divu_pcdi_16(void); void m68000_divu_pcix_16(void); void m68000_divu_i_16(void); void m68020_divl_d_32(void); void m68020_divl_ai_32(void); void m68020_divl_pi_32(void); void m68020_divl_pd_32(void); void m68020_divl_di_32(void); void m68020_divl_ix_32(void); void m68020_divl_aw_32(void); void m68020_divl_al_32(void); void m68020_divl_pcdi_32(void); void m68020_divl_pcix_32(void); void m68020_divl_i_32(void); void m68000_eor_d_8(void); void m68000_eor_ai_8(void); void m68000_eor_pi_8(void); void m68000_eor_pi7_8(void); void m68000_eor_pd_8(void); void m68000_eor_pd7_8(void); void m68000_eor_di_8(void); void m68000_eor_ix_8(void); void m68000_eor_aw_8(void); void m68000_eor_al_8(void); void m68000_eor_d_16(void); void m68000_eor_ai_16(void); void m68000_eor_pi_16(void); void m68000_eor_pd_16(void); void m68000_eor_di_16(void); void m68000_eor_ix_16(void); void m68000_eor_aw_16(void); void m68000_eor_al_16(void); void m68000_eor_d_32(void); void m68000_eor_ai_32(void); void m68000_eor_pi_32(void); void m68000_eor_pd_32(void); void m68000_eor_di_32(void); void m68000_eor_ix_32(void); void m68000_eor_aw_32(void); void m68000_eor_al_32(void); void m68000_eori_to_ccr(void); void m68000_eori_to_sr(void); void m68000_eori_d_8(void); void m68000_eori_ai_8(void); void m68000_eori_pi_8(void); void m68000_eori_pi7_8(void); void m68000_eori_pd_8(void); void m68000_eori_pd7_8(void); void m68000_eori_di_8(void); void m68000_eori_ix_8(void); void m68000_eori_aw_8(void); void m68000_eori_al_8(void); void m68000_eori_d_16(void); void m68000_eori_ai_16(void); void m68000_eori_pi_16(void); void m68000_eori_pd_16(void); void m68000_eori_di_16(void); void m68000_eori_ix_16(void); void m68000_eori_aw_16(void); void m68000_eori_al_16(void); void m68000_eori_d_32(void); void m68000_eori_ai_32(void); void m68000_eori_pi_32(void); void m68000_eori_pd_32(void); void m68000_eori_di_32(void); void m68000_eori_ix_32(void); void m68000_eori_aw_32(void); void m68000_eori_al_32(void); void m68000_exg_dd(void); void m68000_exg_aa(void); void m68000_exg_da(void); void m68000_ext_16(void); void m68000_ext_32(void); void m68020_extb(void); void m68000_illegal(void); void m68000_jmp_ai(void); void m68000_jmp_di(void); void m68000_jmp_ix(void); void m68000_jmp_aw(void); void m68000_jmp_al(void); void m68000_jmp_pcdi(void); void m68000_jmp_pcix(void); void m68000_jsr_ai(void); void m68000_jsr_di(void); void m68000_jsr_ix(void); void m68000_jsr_aw(void); void m68000_jsr_al(void); void m68000_jsr_pcdi(void); void m68000_jsr_pcix(void); void m68000_lea_ai(void); void m68000_lea_di(void); void m68000_lea_ix(void); void m68000_lea_aw(void); void m68000_lea_al(void); void m68000_lea_pcdi(void); void m68000_lea_pcix(void); void m68000_link_16_a7(void); void m68000_link_16(void); void m68020_link_32_a7(void); void m68020_link_32(void); void m68000_lsr_s_8(void); void m68000_lsr_s_16(void); void m68000_lsr_s_32(void); void m68000_lsr_r_8(void); void m68000_lsr_r_16(void); void m68000_lsr_r_32(void); void m68000_lsr_ea_ai(void); void m68000_lsr_ea_pi(void); void m68000_lsr_ea_pd(void); void m68000_lsr_ea_di(void); void m68000_lsr_ea_ix(void); void m68000_lsr_ea_aw(void); void m68000_lsr_ea_al(void); void m68000_lsl_s_8(void); void m68000_lsl_s_16(void); void m68000_lsl_s_32(void); void m68000_lsl_r_8(void); void m68000_lsl_r_16(void); void m68000_lsl_r_32(void); void m68000_lsl_ea_ai(void); void m68000_lsl_ea_pi(void); void m68000_lsl_ea_pd(void); void m68000_lsl_ea_di(void); void m68000_lsl_ea_ix(void); void m68000_lsl_ea_aw(void); void m68000_lsl_ea_al(void); void m68000_move_dd_d_8(void); void m68000_move_dd_ai_8(void); void m68000_move_dd_pi_8(void); void m68000_move_dd_pi7_8(void); void m68000_move_dd_pd_8(void); void m68000_move_dd_pd7_8(void); void m68000_move_dd_di_8(void); void m68000_move_dd_ix_8(void); void m68000_move_dd_aw_8(void); void m68000_move_dd_al_8(void); void m68000_move_dd_pcdi_8(void); void m68000_move_dd_pcix_8(void); void m68000_move_dd_i_8(void); void m68000_move_ai_d_8(void); void m68000_move_ai_ai_8(void); void m68000_move_ai_pi_8(void); void m68000_move_ai_pi7_8(void); void m68000_move_ai_pd_8(void); void m68000_move_ai_pd7_8(void); void m68000_move_ai_di_8(void); void m68000_move_ai_ix_8(void); void m68000_move_ai_aw_8(void); void m68000_move_ai_al_8(void); void m68000_move_ai_pcdi_8(void); void m68000_move_ai_pcix_8(void); void m68000_move_ai_i_8(void); void m68000_move_pi_d_8(void); void m68000_move_pi_ai_8(void); void m68000_move_pi_pi_8(void); void m68000_move_pi_pi7_8(void); void m68000_move_pi_pd_8(void); void m68000_move_pi_pd7_8(void); void m68000_move_pi_di_8(void); void m68000_move_pi_ix_8(void); void m68000_move_pi_aw_8(void); void m68000_move_pi_al_8(void); void m68000_move_pi_pcdi_8(void); void m68000_move_pi_pcix_8(void); void m68000_move_pi_i_8(void); void m68000_move_pi7_d_8(void); void m68000_move_pi7_ai_8(void); void m68000_move_pi7_pi_8(void); void m68000_move_pi7_pi7_8(void); void m68000_move_pi7_pd_8(void); void m68000_move_pi7_pd7_8(void); void m68000_move_pi7_di_8(void); void m68000_move_pi7_ix_8(void); void m68000_move_pi7_aw_8(void); void m68000_move_pi7_al_8(void); void m68000_move_pi7_pcdi_8(void); void m68000_move_pi7_pcix_8(void); void m68000_move_pi7_i_8(void); void m68000_move_pd_d_8(void); void m68000_move_pd_ai_8(void); void m68000_move_pd_pi_8(void); void m68000_move_pd_pi7_8(void); void m68000_move_pd_pd_8(void); void m68000_move_pd_pd7_8(void); void m68000_move_pd_di_8(void); void m68000_move_pd_ix_8(void); void m68000_move_pd_aw_8(void); void m68000_move_pd_al_8(void); void m68000_move_pd_pcdi_8(void); void m68000_move_pd_pcix_8(void); void m68000_move_pd_i_8(void); void m68000_move_pd7_d_8(void); void m68000_move_pd7_ai_8(void); void m68000_move_pd7_pi_8(void); void m68000_move_pd7_pi7_8(void); void m68000_move_pd7_pd_8(void); void m68000_move_pd7_pd7_8(void); void m68000_move_pd7_di_8(void); void m68000_move_pd7_ix_8(void); void m68000_move_pd7_aw_8(void); void m68000_move_pd7_al_8(void); void m68000_move_pd7_pcdi_8(void); void m68000_move_pd7_pcix_8(void); void m68000_move_pd7_i_8(void); void m68000_move_di_d_8(void); void m68000_move_di_ai_8(void); void m68000_move_di_pi_8(void); void m68000_move_di_pi7_8(void); void m68000_move_di_pd_8(void); void m68000_move_di_pd7_8(void); void m68000_move_di_di_8(void); void m68000_move_di_ix_8(void); void m68000_move_di_aw_8(void); void m68000_move_di_al_8(void); void m68000_move_di_pcdi_8(void); void m68000_move_di_pcix_8(void); void m68000_move_di_i_8(void); void m68000_move_ix_d_8(void); void m68000_move_ix_ai_8(void); void m68000_move_ix_pi_8(void); void m68000_move_ix_pi7_8(void); void m68000_move_ix_pd_8(void); void m68000_move_ix_pd7_8(void); void m68000_move_ix_di_8(void); void m68000_move_ix_ix_8(void); void m68000_move_ix_aw_8(void); void m68000_move_ix_al_8(void); void m68000_move_ix_pcdi_8(void); void m68000_move_ix_pcix_8(void); void m68000_move_ix_i_8(void); void m68000_move_aw_d_8(void); void m68000_move_aw_ai_8(void); void m68000_move_aw_pi_8(void); void m68000_move_aw_pi7_8(void); void m68000_move_aw_pd_8(void); void m68000_move_aw_pd7_8(void); void m68000_move_aw_di_8(void); void m68000_move_aw_ix_8(void); void m68000_move_aw_aw_8(void); void m68000_move_aw_al_8(void); void m68000_move_aw_pcdi_8(void); void m68000_move_aw_pcix_8(void); void m68000_move_aw_i_8(void); void m68000_move_al_d_8(void); void m68000_move_al_ai_8(void); void m68000_move_al_pi_8(void); void m68000_move_al_pi7_8(void); void m68000_move_al_pd_8(void); void m68000_move_al_pd7_8(void); void m68000_move_al_di_8(void); void m68000_move_al_ix_8(void); void m68000_move_al_aw_8(void); void m68000_move_al_al_8(void); void m68000_move_al_pcdi_8(void); void m68000_move_al_pcix_8(void); void m68000_move_al_i_8(void); void m68000_move_dd_d_16(void); void m68000_move_dd_a_16(void); void m68000_move_dd_ai_16(void); void m68000_move_dd_pi_16(void); void m68000_move_dd_pd_16(void); void m68000_move_dd_di_16(void); void m68000_move_dd_ix_16(void); void m68000_move_dd_aw_16(void); void m68000_move_dd_al_16(void); void m68000_move_dd_pcdi_16(void); void m68000_move_dd_pcix_16(void); void m68000_move_dd_i_16(void); void m68000_move_ai_d_16(void); void m68000_move_ai_a_16(void); void m68000_move_ai_ai_16(void); void m68000_move_ai_pi_16(void); void m68000_move_ai_pd_16(void); void m68000_move_ai_di_16(void); void m68000_move_ai_ix_16(void); void m68000_move_ai_aw_16(void); void m68000_move_ai_al_16(void); void m68000_move_ai_pcdi_16(void); void m68000_move_ai_pcix_16(void); void m68000_move_ai_i_16(void); void m68000_move_pi_d_16(void); void m68000_move_pi_a_16(void); void m68000_move_pi_ai_16(void); void m68000_move_pi_pi_16(void); void m68000_move_pi_pd_16(void); void m68000_move_pi_di_16(void); void m68000_move_pi_ix_16(void); void m68000_move_pi_aw_16(void); void m68000_move_pi_al_16(void); void m68000_move_pi_pcdi_16(void); void m68000_move_pi_pcix_16(void); void m68000_move_pi_i_16(void); void m68000_move_pd_d_16(void); void m68000_move_pd_a_16(void); void m68000_move_pd_ai_16(void); void m68000_move_pd_pi_16(void); void m68000_move_pd_pd_16(void); void m68000_move_pd_di_16(void); void m68000_move_pd_ix_16(void); void m68000_move_pd_aw_16(void); void m68000_move_pd_al_16(void); void m68000_move_pd_pcdi_16(void); void m68000_move_pd_pcix_16(void); void m68000_move_pd_i_16(void); void m68000_move_di_d_16(void); void m68000_move_di_a_16(void); void m68000_move_di_ai_16(void); void m68000_move_di_pi_16(void); void m68000_move_di_pd_16(void); void m68000_move_di_di_16(void); void m68000_move_di_ix_16(void); void m68000_move_di_aw_16(void); void m68000_move_di_al_16(void); void m68000_move_di_pcdi_16(void); void m68000_move_di_pcix_16(void); void m68000_move_di_i_16(void); void m68000_move_ix_d_16(void); void m68000_move_ix_a_16(void); void m68000_move_ix_ai_16(void); void m68000_move_ix_pi_16(void); void m68000_move_ix_pd_16(void); void m68000_move_ix_di_16(void); void m68000_move_ix_ix_16(void); void m68000_move_ix_aw_16(void); void m68000_move_ix_al_16(void); void m68000_move_ix_pcdi_16(void); void m68000_move_ix_pcix_16(void); void m68000_move_ix_i_16(void); void m68000_move_aw_d_16(void); void m68000_move_aw_a_16(void); void m68000_move_aw_ai_16(void); void m68000_move_aw_pi_16(void); void m68000_move_aw_pd_16(void); void m68000_move_aw_di_16(void); void m68000_move_aw_ix_16(void); void m68000_move_aw_aw_16(void); void m68000_move_aw_al_16(void); void m68000_move_aw_pcdi_16(void); void m68000_move_aw_pcix_16(void); void m68000_move_aw_i_16(void); void m68000_move_al_d_16(void); void m68000_move_al_a_16(void); void m68000_move_al_ai_16(void); void m68000_move_al_pi_16(void); void m68000_move_al_pd_16(void); void m68000_move_al_di_16(void); void m68000_move_al_ix_16(void); void m68000_move_al_aw_16(void); void m68000_move_al_al_16(void); void m68000_move_al_pcdi_16(void); void m68000_move_al_pcix_16(void); void m68000_move_al_i_16(void); void m68000_move_dd_d_32(void); void m68000_move_dd_a_32(void); void m68000_move_dd_ai_32(void); void m68000_move_dd_pi_32(void); void m68000_move_dd_pd_32(void); void m68000_move_dd_di_32(void); void m68000_move_dd_ix_32(void); void m68000_move_dd_aw_32(void); void m68000_move_dd_al_32(void); void m68000_move_dd_pcdi_32(void); void m68000_move_dd_pcix_32(void); void m68000_move_dd_i_32(void); void m68000_move_ai_d_32(void); void m68000_move_ai_a_32(void); void m68000_move_ai_ai_32(void); void m68000_move_ai_pi_32(void); void m68000_move_ai_pd_32(void); void m68000_move_ai_di_32(void); void m68000_move_ai_ix_32(void); void m68000_move_ai_aw_32(void); void m68000_move_ai_al_32(void); void m68000_move_ai_pcdi_32(void); void m68000_move_ai_pcix_32(void); void m68000_move_ai_i_32(void); void m68000_move_pi_d_32(void); void m68000_move_pi_a_32(void); void m68000_move_pi_ai_32(void); void m68000_move_pi_pi_32(void); void m68000_move_pi_pd_32(void); void m68000_move_pi_di_32(void); void m68000_move_pi_ix_32(void); void m68000_move_pi_aw_32(void); void m68000_move_pi_al_32(void); void m68000_move_pi_pcdi_32(void); void m68000_move_pi_pcix_32(void); void m68000_move_pi_i_32(void); void m68000_move_pd_d_32(void); void m68000_move_pd_a_32(void); void m68000_move_pd_ai_32(void); void m68000_move_pd_pi_32(void); void m68000_move_pd_pd_32(void); void m68000_move_pd_di_32(void); void m68000_move_pd_ix_32(void); void m68000_move_pd_aw_32(void); void m68000_move_pd_al_32(void); void m68000_move_pd_pcdi_32(void); void m68000_move_pd_pcix_32(void); void m68000_move_pd_i_32(void); void m68000_move_di_d_32(void); void m68000_move_di_a_32(void); void m68000_move_di_ai_32(void); void m68000_move_di_pi_32(void); void m68000_move_di_pd_32(void); void m68000_move_di_di_32(void); void m68000_move_di_ix_32(void); void m68000_move_di_aw_32(void); void m68000_move_di_al_32(void); void m68000_move_di_pcdi_32(void); void m68000_move_di_pcix_32(void); void m68000_move_di_i_32(void); void m68000_move_ix_d_32(void); void m68000_move_ix_a_32(void); void m68000_move_ix_ai_32(void); void m68000_move_ix_pi_32(void); void m68000_move_ix_pd_32(void); void m68000_move_ix_di_32(void); void m68000_move_ix_ix_32(void); void m68000_move_ix_aw_32(void); void m68000_move_ix_al_32(void); void m68000_move_ix_pcdi_32(void); void m68000_move_ix_pcix_32(void); void m68000_move_ix_i_32(void); void m68000_move_aw_d_32(void); void m68000_move_aw_a_32(void); void m68000_move_aw_ai_32(void); void m68000_move_aw_pi_32(void); void m68000_move_aw_pd_32(void); void m68000_move_aw_di_32(void); void m68000_move_aw_ix_32(void); void m68000_move_aw_aw_32(void); void m68000_move_aw_al_32(void); void m68000_move_aw_pcdi_32(void); void m68000_move_aw_pcix_32(void); void m68000_move_aw_i_32(void); void m68000_move_al_d_32(void); void m68000_move_al_a_32(void); void m68000_move_al_ai_32(void); void m68000_move_al_pi_32(void); void m68000_move_al_pd_32(void); void m68000_move_al_di_32(void); void m68000_move_al_ix_32(void); void m68000_move_al_aw_32(void); void m68000_move_al_al_32(void); void m68000_move_al_pcdi_32(void); void m68000_move_al_pcix_32(void); void m68000_move_al_i_32(void); void m68000_movea_d_16(void); void m68000_movea_a_16(void); void m68000_movea_ai_16(void); void m68000_movea_pi_16(void); void m68000_movea_pd_16(void); void m68000_movea_di_16(void); void m68000_movea_ix_16(void); void m68000_movea_aw_16(void); void m68000_movea_al_16(void); void m68000_movea_pcdi_16(void); void m68000_movea_pcix_16(void); void m68000_movea_i_16(void); void m68000_movea_d_32(void); void m68000_movea_a_32(void); void m68000_movea_ai_32(void); void m68000_movea_pi_32(void); void m68000_movea_pd_32(void); void m68000_movea_di_32(void); void m68000_movea_ix_32(void); void m68000_movea_aw_32(void); void m68000_movea_al_32(void); void m68000_movea_pcdi_32(void); void m68000_movea_pcix_32(void); void m68000_movea_i_32(void); void m68010_move_fr_ccr_d(void); void m68010_move_fr_ccr_ai(void); void m68010_move_fr_ccr_pi(void); void m68010_move_fr_ccr_pd(void); void m68010_move_fr_ccr_di(void); void m68010_move_fr_ccr_ix(void); void m68010_move_fr_ccr_aw(void); void m68010_move_fr_ccr_al(void); void m68000_move_to_ccr_d(void); void m68000_move_to_ccr_ai(void); void m68000_move_to_ccr_pi(void); void m68000_move_to_ccr_pd(void); void m68000_move_to_ccr_di(void); void m68000_move_to_ccr_ix(void); void m68000_move_to_ccr_aw(void); void m68000_move_to_ccr_al(void); void m68000_move_to_ccr_pcdi(void); void m68000_move_to_ccr_pcix(void); void m68000_move_to_ccr_i(void); void m68000_move_fr_sr_d(void); void m68000_move_fr_sr_ai(void); void m68000_move_fr_sr_pi(void); void m68000_move_fr_sr_pd(void); void m68000_move_fr_sr_di(void); void m68000_move_fr_sr_ix(void); void m68000_move_fr_sr_aw(void); void m68000_move_fr_sr_al(void); void m68000_move_to_sr_d(void); void m68000_move_to_sr_ai(void); void m68000_move_to_sr_pi(void); void m68000_move_to_sr_pd(void); void m68000_move_to_sr_di(void); void m68000_move_to_sr_ix(void); void m68000_move_to_sr_aw(void); void m68000_move_to_sr_al(void); void m68000_move_to_sr_pcdi(void); void m68000_move_to_sr_pcix(void); void m68000_move_to_sr_i(void); void m68000_move_fr_usp(void); void m68000_move_to_usp(void); void m68010_movec_cr(void); void m68010_movec_rc(void); void m68000_movem_pd_16(void); void m68000_movem_pd_32(void); void m68000_movem_pi_16(void); void m68000_movem_pi_32(void); void m68000_movem_re_ai_16(void); void m68000_movem_re_di_16(void); void m68000_movem_re_ix_16(void); void m68000_movem_re_aw_16(void); void m68000_movem_re_al_16(void); void m68000_movem_re_ai_32(void); void m68000_movem_re_di_32(void); void m68000_movem_re_ix_32(void); void m68000_movem_re_aw_32(void); void m68000_movem_re_al_32(void); void m68000_movem_er_ai_16(void); void m68000_movem_er_di_16(void); void m68000_movem_er_ix_16(void); void m68000_movem_er_aw_16(void); void m68000_movem_er_al_16(void); void m68000_movem_er_pcdi_16(void); void m68000_movem_er_pcix_16(void); void m68000_movem_er_ai_32(void); void m68000_movem_er_di_32(void); void m68000_movem_er_ix_32(void); void m68000_movem_er_aw_32(void); void m68000_movem_er_al_32(void); void m68000_movem_er_pcdi_32(void); void m68000_movem_er_pcix_32(void); void m68000_movep_er_16(void); void m68000_movep_er_32(void); void m68000_movep_re_16(void); void m68000_movep_re_32(void); void m68010_moves_ai_8(void); void m68010_moves_pi_8(void); void m68010_moves_pi7_8(void); void m68010_moves_pd_8(void); void m68010_moves_pd7_8(void); void m68010_moves_di_8(void); void m68010_moves_ix_8(void); void m68010_moves_aw_8(void); void m68010_moves_al_8(void); void m68010_moves_ai_16(void); void m68010_moves_pi_16(void); void m68010_moves_pd_16(void); void m68010_moves_di_16(void); void m68010_moves_ix_16(void); void m68010_moves_aw_16(void); void m68010_moves_al_16(void); void m68010_moves_ai_32(void); void m68010_moves_pi_32(void); void m68010_moves_pd_32(void); void m68010_moves_di_32(void); void m68010_moves_ix_32(void); void m68010_moves_aw_32(void); void m68010_moves_al_32(void); void m68000_moveq(void); void m68000_muls_d_16(void); void m68000_muls_ai_16(void); void m68000_muls_pi_16(void); void m68000_muls_pd_16(void); void m68000_muls_di_16(void); void m68000_muls_ix_16(void); void m68000_muls_aw_16(void); void m68000_muls_al_16(void); void m68000_muls_pcdi_16(void); void m68000_muls_pcix_16(void); void m68000_muls_i_16(void); void m68000_mulu_d_16(void); void m68000_mulu_ai_16(void); void m68000_mulu_pi_16(void); void m68000_mulu_pd_16(void); void m68000_mulu_di_16(void); void m68000_mulu_ix_16(void); void m68000_mulu_aw_16(void); void m68000_mulu_al_16(void); void m68000_mulu_pcdi_16(void); void m68000_mulu_pcix_16(void); void m68000_mulu_i_16(void); void m68020_mull_d_32(void); void m68020_mull_ai_32(void); void m68020_mull_pi_32(void); void m68020_mull_pd_32(void); void m68020_mull_di_32(void); void m68020_mull_ix_32(void); void m68020_mull_aw_32(void); void m68020_mull_al_32(void); void m68020_mull_pcdi_32(void); void m68020_mull_pcix_32(void); void m68020_mull_i_32(void); void m68000_nbcd_d(void); void m68000_nbcd_ai(void); void m68000_nbcd_pi(void); void m68000_nbcd_pi7(void); void m68000_nbcd_pd(void); void m68000_nbcd_pd7(void); void m68000_nbcd_di(void); void m68000_nbcd_ix(void); void m68000_nbcd_aw(void); void m68000_nbcd_al(void); void m68000_neg_d_8(void); void m68000_neg_ai_8(void); void m68000_neg_pi_8(void); void m68000_neg_pi7_8(void); void m68000_neg_pd_8(void); void m68000_neg_pd7_8(void); void m68000_neg_di_8(void); void m68000_neg_ix_8(void); void m68000_neg_aw_8(void); void m68000_neg_al_8(void); void m68000_neg_d_16(void); void m68000_neg_ai_16(void); void m68000_neg_pi_16(void); void m68000_neg_pd_16(void); void m68000_neg_di_16(void); void m68000_neg_ix_16(void); void m68000_neg_aw_16(void); void m68000_neg_al_16(void); void m68000_neg_d_32(void); void m68000_neg_ai_32(void); void m68000_neg_pi_32(void); void m68000_neg_pd_32(void); void m68000_neg_di_32(void); void m68000_neg_ix_32(void); void m68000_neg_aw_32(void); void m68000_neg_al_32(void); void m68000_negx_d_8(void); void m68000_negx_ai_8(void); void m68000_negx_pi_8(void); void m68000_negx_pi7_8(void); void m68000_negx_pd_8(void); void m68000_negx_pd7_8(void); void m68000_negx_di_8(void); void m68000_negx_ix_8(void); void m68000_negx_aw_8(void); void m68000_negx_al_8(void); void m68000_negx_d_16(void); void m68000_negx_ai_16(void); void m68000_negx_pi_16(void); void m68000_negx_pd_16(void); void m68000_negx_di_16(void); void m68000_negx_ix_16(void); void m68000_negx_aw_16(void); void m68000_negx_al_16(void); void m68000_negx_d_32(void); void m68000_negx_ai_32(void); void m68000_negx_pi_32(void); void m68000_negx_pd_32(void); void m68000_negx_di_32(void); void m68000_negx_ix_32(void); void m68000_negx_aw_32(void); void m68000_negx_al_32(void); void m68000_nop(void); void m68000_not_d_8(void); void m68000_not_ai_8(void); void m68000_not_pi_8(void); void m68000_not_pi7_8(void); void m68000_not_pd_8(void); void m68000_not_pd7_8(void); void m68000_not_di_8(void); void m68000_not_ix_8(void); void m68000_not_aw_8(void); void m68000_not_al_8(void); void m68000_not_d_16(void); void m68000_not_ai_16(void); void m68000_not_pi_16(void); void m68000_not_pd_16(void); void m68000_not_di_16(void); void m68000_not_ix_16(void); void m68000_not_aw_16(void); void m68000_not_al_16(void); void m68000_not_d_32(void); void m68000_not_ai_32(void); void m68000_not_pi_32(void); void m68000_not_pd_32(void); void m68000_not_di_32(void); void m68000_not_ix_32(void); void m68000_not_aw_32(void); void m68000_not_al_32(void); void m68000_or_er_d_8(void); void m68000_or_er_ai_8(void); void m68000_or_er_pi_8(void); void m68000_or_er_pi7_8(void); void m68000_or_er_pd_8(void); void m68000_or_er_pd7_8(void); void m68000_or_er_di_8(void); void m68000_or_er_ix_8(void); void m68000_or_er_aw_8(void); void m68000_or_er_al_8(void); void m68000_or_er_pcdi_8(void); void m68000_or_er_pcix_8(void); void m68000_or_er_i_8(void); void m68000_or_er_d_16(void); void m68000_or_er_ai_16(void); void m68000_or_er_pi_16(void); void m68000_or_er_pd_16(void); void m68000_or_er_di_16(void); void m68000_or_er_ix_16(void); void m68000_or_er_aw_16(void); void m68000_or_er_al_16(void); void m68000_or_er_pcdi_16(void); void m68000_or_er_pcix_16(void); void m68000_or_er_i_16(void); void m68000_or_er_d_32(void); void m68000_or_er_ai_32(void); void m68000_or_er_pi_32(void); void m68000_or_er_pd_32(void); void m68000_or_er_di_32(void); void m68000_or_er_ix_32(void); void m68000_or_er_aw_32(void); void m68000_or_er_al_32(void); void m68000_or_er_pcdi_32(void); void m68000_or_er_pcix_32(void); void m68000_or_er_i_32(void); void m68000_or_re_ai_8(void); void m68000_or_re_pi_8(void); void m68000_or_re_pi7_8(void); void m68000_or_re_pd_8(void); void m68000_or_re_pd7_8(void); void m68000_or_re_di_8(void); void m68000_or_re_ix_8(void); void m68000_or_re_aw_8(void); void m68000_or_re_al_8(void); void m68000_or_re_ai_16(void); void m68000_or_re_pi_16(void); void m68000_or_re_pd_16(void); void m68000_or_re_di_16(void); void m68000_or_re_ix_16(void); void m68000_or_re_aw_16(void); void m68000_or_re_al_16(void); void m68000_or_re_ai_32(void); void m68000_or_re_pi_32(void); void m68000_or_re_pd_32(void); void m68000_or_re_di_32(void); void m68000_or_re_ix_32(void); void m68000_or_re_aw_32(void); void m68000_or_re_al_32(void); void m68000_ori_to_ccr(void); void m68000_ori_to_sr(void); void m68000_ori_d_8(void); void m68000_ori_ai_8(void); void m68000_ori_pi_8(void); void m68000_ori_pi7_8(void); void m68000_ori_pd_8(void); void m68000_ori_pd7_8(void); void m68000_ori_di_8(void); void m68000_ori_ix_8(void); void m68000_ori_aw_8(void); void m68000_ori_al_8(void); void m68000_ori_d_16(void); void m68000_ori_ai_16(void); void m68000_ori_pi_16(void); void m68000_ori_pd_16(void); void m68000_ori_di_16(void); void m68000_ori_ix_16(void); void m68000_ori_aw_16(void); void m68000_ori_al_16(void); void m68000_ori_d_32(void); void m68000_ori_ai_32(void); void m68000_ori_pi_32(void); void m68000_ori_pd_32(void); void m68000_ori_di_32(void); void m68000_ori_ix_32(void); void m68000_ori_aw_32(void); void m68000_ori_al_32(void); void m68020_pack_rr(void); void m68020_pack_mm_ax7(void); void m68020_pack_mm_ay7(void); void m68020_pack_mm_axy7(void); void m68020_pack_mm(void); void m68000_pea_ai(void); void m68000_pea_di(void); void m68000_pea_ix(void); void m68000_pea_aw(void); void m68000_pea_al(void); void m68000_pea_pcdi(void); void m68000_pea_pcix(void); void m68000_rst(void); void m68000_ror_s_8(void); void m68000_ror_s_16(void); void m68000_ror_s_32(void); void m68000_ror_r_8(void); void m68000_ror_r_16(void); void m68000_ror_r_32(void); void m68000_ror_ea_ai(void); void m68000_ror_ea_pi(void); void m68000_ror_ea_pd(void); void m68000_ror_ea_di(void); void m68000_ror_ea_ix(void); void m68000_ror_ea_aw(void); void m68000_ror_ea_al(void); void m68000_rol_s_8(void); void m68000_rol_s_16(void); void m68000_rol_s_32(void); void m68000_rol_r_8(void); void m68000_rol_r_16(void); void m68000_rol_r_32(void); void m68000_rol_ea_ai(void); void m68000_rol_ea_pi(void); void m68000_rol_ea_pd(void); void m68000_rol_ea_di(void); void m68000_rol_ea_ix(void); void m68000_rol_ea_aw(void); void m68000_rol_ea_al(void); void m68000_roxr_s_8(void); void m68000_roxr_s_16(void); void m68000_roxr_s_32(void); void m68000_roxr_r_8(void); void m68000_roxr_r_16(void); void m68000_roxr_r_32(void); void m68000_roxr_ea_ai(void); void m68000_roxr_ea_pi(void); void m68000_roxr_ea_pd(void); void m68000_roxr_ea_di(void); void m68000_roxr_ea_ix(void); void m68000_roxr_ea_aw(void); void m68000_roxr_ea_al(void); void m68000_roxl_s_8(void); void m68000_roxl_s_16(void); void m68000_roxl_s_32(void); void m68000_roxl_r_8(void); void m68000_roxl_r_16(void); void m68000_roxl_r_32(void); void m68000_roxl_ea_ai(void); void m68000_roxl_ea_pi(void); void m68000_roxl_ea_pd(void); void m68000_roxl_ea_di(void); void m68000_roxl_ea_ix(void); void m68000_roxl_ea_aw(void); void m68000_roxl_ea_al(void); void m68010_rtd(void); void m68000_rte(void); void m68020_rtm(void); void m68000_rtr(void); void m68000_rts(void); void m68000_sbcd_rr(void); void m68000_sbcd_mm_ax7(void); void m68000_sbcd_mm_ay7(void); void m68000_sbcd_mm_axy7(void); void m68000_sbcd_mm(void); void m68000_st_d(void); void m68000_st_ai(void); void m68000_st_pi(void); void m68000_st_pi7(void); void m68000_st_pd(void); void m68000_st_pd7(void); void m68000_st_di(void); void m68000_st_ix(void); void m68000_st_aw(void); void m68000_st_al(void); void m68000_sf_d(void); void m68000_sf_ai(void); void m68000_sf_pi(void); void m68000_sf_pi7(void); void m68000_sf_pd(void); void m68000_sf_pd7(void); void m68000_sf_di(void); void m68000_sf_ix(void); void m68000_sf_aw(void); void m68000_sf_al(void); void m68000_shi_d(void); void m68000_shi_ai(void); void m68000_shi_pi(void); void m68000_shi_pi7(void); void m68000_shi_pd(void); void m68000_shi_pd7(void); void m68000_shi_di(void); void m68000_shi_ix(void); void m68000_shi_aw(void); void m68000_shi_al(void); void m68000_sls_d(void); void m68000_sls_ai(void); void m68000_sls_pi(void); void m68000_sls_pi7(void); void m68000_sls_pd(void); void m68000_sls_pd7(void); void m68000_sls_di(void); void m68000_sls_ix(void); void m68000_sls_aw(void); void m68000_sls_al(void); void m68000_scc_d(void); void m68000_scc_ai(void); void m68000_scc_pi(void); void m68000_scc_pi7(void); void m68000_scc_pd(void); void m68000_scc_pd7(void); void m68000_scc_di(void); void m68000_scc_ix(void); void m68000_scc_aw(void); void m68000_scc_al(void); void m68000_scs_d(void); void m68000_scs_ai(void); void m68000_scs_pi(void); void m68000_scs_pi7(void); void m68000_scs_pd(void); void m68000_scs_pd7(void); void m68000_scs_di(void); void m68000_scs_ix(void); void m68000_scs_aw(void); void m68000_scs_al(void); void m68000_sne_d(void); void m68000_sne_ai(void); void m68000_sne_pi(void); void m68000_sne_pi7(void); void m68000_sne_pd(void); void m68000_sne_pd7(void); void m68000_sne_di(void); void m68000_sne_ix(void); void m68000_sne_aw(void); void m68000_sne_al(void); void m68000_seq_d(void); void m68000_seq_ai(void); void m68000_seq_pi(void); void m68000_seq_pi7(void); void m68000_seq_pd(void); void m68000_seq_pd7(void); void m68000_seq_di(void); void m68000_seq_ix(void); void m68000_seq_aw(void); void m68000_seq_al(void); void m68000_svc_d(void); void m68000_svc_ai(void); void m68000_svc_pi(void); void m68000_svc_pi7(void); void m68000_svc_pd(void); void m68000_svc_pd7(void); void m68000_svc_di(void); void m68000_svc_ix(void); void m68000_svc_aw(void); void m68000_svc_al(void); void m68000_svs_d(void); void m68000_svs_ai(void); void m68000_svs_pi(void); void m68000_svs_pi7(void); void m68000_svs_pd(void); void m68000_svs_pd7(void); void m68000_svs_di(void); void m68000_svs_ix(void); void m68000_svs_aw(void); void m68000_svs_al(void); void m68000_spl_d(void); void m68000_spl_ai(void); void m68000_spl_pi(void); void m68000_spl_pi7(void); void m68000_spl_pd(void); void m68000_spl_pd7(void); void m68000_spl_di(void); void m68000_spl_ix(void); void m68000_spl_aw(void); void m68000_spl_al(void); void m68000_smi_d(void); void m68000_smi_ai(void); void m68000_smi_pi(void); void m68000_smi_pi7(void); void m68000_smi_pd(void); void m68000_smi_pd7(void); void m68000_smi_di(void); void m68000_smi_ix(void); void m68000_smi_aw(void); void m68000_smi_al(void); void m68000_sge_d(void); void m68000_sge_ai(void); void m68000_sge_pi(void); void m68000_sge_pi7(void); void m68000_sge_pd(void); void m68000_sge_pd7(void); void m68000_sge_di(void); void m68000_sge_ix(void); void m68000_sge_aw(void); void m68000_sge_al(void); void m68000_slt_d(void); void m68000_slt_ai(void); void m68000_slt_pi(void); void m68000_slt_pi7(void); void m68000_slt_pd(void); void m68000_slt_pd7(void); void m68000_slt_di(void); void m68000_slt_ix(void); void m68000_slt_aw(void); void m68000_slt_al(void); void m68000_sgt_d(void); void m68000_sgt_ai(void); void m68000_sgt_pi(void); void m68000_sgt_pi7(void); void m68000_sgt_pd(void); void m68000_sgt_pd7(void); void m68000_sgt_di(void); void m68000_sgt_ix(void); void m68000_sgt_aw(void); void m68000_sgt_al(void); void m68000_sle_d(void); void m68000_sle_ai(void); void m68000_sle_pi(void); void m68000_sle_pi7(void); void m68000_sle_pd(void); void m68000_sle_pd7(void); void m68000_sle_di(void); void m68000_sle_ix(void); void m68000_sle_aw(void); void m68000_sle_al(void); void m68000_stop(void); void m68000_sub_er_d_8(void); void m68000_sub_er_ai_8(void); void m68000_sub_er_pi_8(void); void m68000_sub_er_pi7_8(void); void m68000_sub_er_pd_8(void); void m68000_sub_er_pd7_8(void); void m68000_sub_er_di_8(void); void m68000_sub_er_ix_8(void); void m68000_sub_er_aw_8(void); void m68000_sub_er_al_8(void); void m68000_sub_er_pcdi_8(void); void m68000_sub_er_pcix_8(void); void m68000_sub_er_i_8(void); void m68000_sub_er_d_16(void); void m68000_sub_er_a_16(void); void m68000_sub_er_ai_16(void); void m68000_sub_er_pi_16(void); void m68000_sub_er_pd_16(void); void m68000_sub_er_di_16(void); void m68000_sub_er_ix_16(void); void m68000_sub_er_aw_16(void); void m68000_sub_er_al_16(void); void m68000_sub_er_pcdi_16(void); void m68000_sub_er_pcix_16(void); void m68000_sub_er_i_16(void); void m68000_sub_er_d_32(void); void m68000_sub_er_a_32(void); void m68000_sub_er_ai_32(void); void m68000_sub_er_pi_32(void); void m68000_sub_er_pd_32(void); void m68000_sub_er_di_32(void); void m68000_sub_er_ix_32(void); void m68000_sub_er_aw_32(void); void m68000_sub_er_al_32(void); void m68000_sub_er_pcdi_32(void); void m68000_sub_er_pcix_32(void); void m68000_sub_er_i_32(void); void m68000_sub_re_ai_8(void); void m68000_sub_re_pi_8(void); void m68000_sub_re_pi7_8(void); void m68000_sub_re_pd_8(void); void m68000_sub_re_pd7_8(void); void m68000_sub_re_di_8(void); void m68000_sub_re_ix_8(void); void m68000_sub_re_aw_8(void); void m68000_sub_re_al_8(void); void m68000_sub_re_ai_16(void); void m68000_sub_re_pi_16(void); void m68000_sub_re_pd_16(void); void m68000_sub_re_di_16(void); void m68000_sub_re_ix_16(void); void m68000_sub_re_aw_16(void); void m68000_sub_re_al_16(void); void m68000_sub_re_ai_32(void); void m68000_sub_re_pi_32(void); void m68000_sub_re_pd_32(void); void m68000_sub_re_di_32(void); void m68000_sub_re_ix_32(void); void m68000_sub_re_aw_32(void); void m68000_sub_re_al_32(void); void m68000_suba_d_16(void); void m68000_suba_a_16(void); void m68000_suba_ai_16(void); void m68000_suba_pi_16(void); void m68000_suba_pd_16(void); void m68000_suba_di_16(void); void m68000_suba_ix_16(void); void m68000_suba_aw_16(void); void m68000_suba_al_16(void); void m68000_suba_pcdi_16(void); void m68000_suba_pcix_16(void); void m68000_suba_i_16(void); void m68000_suba_d_32(void); void m68000_suba_a_32(void); void m68000_suba_ai_32(void); void m68000_suba_pi_32(void); void m68000_suba_pd_32(void); void m68000_suba_di_32(void); void m68000_suba_ix_32(void); void m68000_suba_aw_32(void); void m68000_suba_al_32(void); void m68000_suba_pcdi_32(void); void m68000_suba_pcix_32(void); void m68000_suba_i_32(void); void m68000_subi_d_8(void); void m68000_subi_ai_8(void); void m68000_subi_pi_8(void); void m68000_subi_pi7_8(void); void m68000_subi_pd_8(void); void m68000_subi_pd7_8(void); void m68000_subi_di_8(void); void m68000_subi_ix_8(void); void m68000_subi_aw_8(void); void m68000_subi_al_8(void); void m68000_subi_d_16(void); void m68000_subi_ai_16(void); void m68000_subi_pi_16(void); void m68000_subi_pd_16(void); void m68000_subi_di_16(void); void m68000_subi_ix_16(void); void m68000_subi_aw_16(void); void m68000_subi_al_16(void); void m68000_subi_d_32(void); void m68000_subi_ai_32(void); void m68000_subi_pi_32(void); void m68000_subi_pd_32(void); void m68000_subi_di_32(void); void m68000_subi_ix_32(void); void m68000_subi_aw_32(void); void m68000_subi_al_32(void); void m68000_subq_d_8(void); void m68000_subq_ai_8(void); void m68000_subq_pi_8(void); void m68000_subq_pi7_8(void); void m68000_subq_pd_8(void); void m68000_subq_pd7_8(void); void m68000_subq_di_8(void); void m68000_subq_ix_8(void); void m68000_subq_aw_8(void); void m68000_subq_al_8(void); void m68000_subq_d_16(void); void m68000_subq_a_16(void); void m68000_subq_ai_16(void); void m68000_subq_pi_16(void); void m68000_subq_pd_16(void); void m68000_subq_di_16(void); void m68000_subq_ix_16(void); void m68000_subq_aw_16(void); void m68000_subq_al_16(void); void m68000_subq_d_32(void); void m68000_subq_a_32(void); void m68000_subq_ai_32(void); void m68000_subq_pi_32(void); void m68000_subq_pd_32(void); void m68000_subq_di_32(void); void m68000_subq_ix_32(void); void m68000_subq_aw_32(void); void m68000_subq_al_32(void); void m68000_subx_rr_8(void); void m68000_subx_rr_16(void); void m68000_subx_rr_32(void); void m68000_subx_mm_8_ax7(void); void m68000_subx_mm_8_ay7(void); void m68000_subx_mm_8_axy7(void); void m68000_subx_mm_8(void); void m68000_subx_mm_16(void); void m68000_subx_mm_32(void); void m68000_swap(void); void m68000_tas_d(void); void m68000_tas_ai(void); void m68000_tas_pi(void); void m68000_tas_pi7(void); void m68000_tas_pd(void); void m68000_tas_pd7(void); void m68000_tas_di(void); void m68000_tas_ix(void); void m68000_tas_aw(void); void m68000_tas_al(void); void m68000_trap(void); void m68020_trapt_0(void); void m68020_trapt_16(void); void m68020_trapt_32(void); void m68020_trapf_0(void); void m68020_trapf_16(void); void m68020_trapf_32(void); void m68020_traphi_0(void); void m68020_traphi_16(void); void m68020_traphi_32(void); void m68020_trapls_0(void); void m68020_trapls_16(void); void m68020_trapls_32(void); void m68020_trapcc_0(void); void m68020_trapcc_16(void); void m68020_trapcc_32(void); void m68020_trapcs_0(void); void m68020_trapcs_16(void); void m68020_trapcs_32(void); void m68020_trapne_0(void); void m68020_trapne_16(void); void m68020_trapne_32(void); void m68020_trapeq_0(void); void m68020_trapeq_16(void); void m68020_trapeq_32(void); void m68020_trapvc_0(void); void m68020_trapvc_16(void); void m68020_trapvc_32(void); void m68020_trapvs_0(void); void m68020_trapvs_16(void); void m68020_trapvs_32(void); void m68020_trappl_0(void); void m68020_trappl_16(void); void m68020_trappl_32(void); void m68020_trapmi_0(void); void m68020_trapmi_16(void); void m68020_trapmi_32(void); void m68020_trapge_0(void); void m68020_trapge_16(void); void m68020_trapge_32(void); void m68020_traplt_0(void); void m68020_traplt_16(void); void m68020_traplt_32(void); void m68020_trapgt_0(void); void m68020_trapgt_16(void); void m68020_trapgt_32(void); void m68020_traple_0(void); void m68020_traple_16(void); void m68020_traple_32(void); void m68000_trapv(void); void m68000_tst_d_8(void); void m68000_tst_ai_8(void); void m68000_tst_pi_8(void); void m68000_tst_pi7_8(void); void m68000_tst_pd_8(void); void m68000_tst_pd7_8(void); void m68000_tst_di_8(void); void m68000_tst_ix_8(void); void m68000_tst_aw_8(void); void m68000_tst_al_8(void); void m68020_tst_pcdi_8(void); void m68020_tst_pcix_8(void); void m68020_tst_imm_8(void); void m68000_tst_d_16(void); void m68020_tst_a_16(void); void m68000_tst_ai_16(void); void m68000_tst_pi_16(void); void m68000_tst_pd_16(void); void m68000_tst_di_16(void); void m68000_tst_ix_16(void); void m68000_tst_aw_16(void); void m68000_tst_al_16(void); void m68020_tst_pcdi_16(void); void m68020_tst_pcix_16(void); void m68020_tst_imm_16(void); void m68000_tst_d_32(void); void m68020_tst_a_32(void); void m68000_tst_ai_32(void); void m68000_tst_pi_32(void); void m68000_tst_pd_32(void); void m68000_tst_di_32(void); void m68000_tst_ix_32(void); void m68000_tst_aw_32(void); void m68000_tst_al_32(void); void m68020_tst_pcdi_32(void); void m68020_tst_pcix_32(void); void m68020_tst_imm_32(void); void m68000_unlk_a7(void); void m68000_unlk(void); void m68020_unpk_rr(void); void m68020_unpk_mm_ax7(void); void m68020_unpk_mm_ay7(void); void m68020_unpk_mm_axy7(void); void m68020_unpk_mm(void); #endif /* M68KOPS__HEADER */ dgen-sdl-1.23/mz80/Makefile.in 644 1750 1750 17022 7320415002 11133 # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # DGen/SDL v1.20+ # Automakefile for mz80 # Tell how to make assembler files SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_alias = @build_alias@ build_triplet = @build@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ AWK = @AWK@ CC = @CC@ CHOP_ = @CHOP_@ CPP = @CPP@ CPUDIRS = @CPUDIRS@ CXX = @CXX@ CXXCPP = @CXXCPP@ EXTRAOBJS = @EXTRAOBJS@ INTERFACE = @INTERFACE@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ MUSA = @MUSA@ MZ80 = @MZ80@ NASM = @NASM@ NASM_FMT = @NASM_FMT@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STAR = @STAR@ VERSION = @VERSION@ SUFFIXES = .asmu .asm INCLUDES = -I.. EXTRA_DIST = mz80.txt noinst_LIBRARIES = libmz80.a libmz80_a_SOURCES = libmz80_a_LIBADD = mz80.o libmz80_a_DEPENDENCIES = mz80.o EXTRA_libmz80_a_SOURCES = makez80.c DISTCLEANFILES = mz80.asm makez80 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ libmz80_a_OBJECTS = AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(libmz80_a_SOURCES) $(EXTRA_libmz80_a_SOURCES) OBJECTS = $(libmz80_a_OBJECTS) all: all-redirect .SUFFIXES: .SUFFIXES: .S .asm .asmu .c .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.asm.am cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps mz80/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status mostlyclean-noinstLIBRARIES: clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: libmz80.a: $(libmz80_a_OBJECTS) $(libmz80_a_DEPENDENCIES) -rm -f libmz80.a $(AR) cru libmz80.a $(libmz80_a_OBJECTS) $(libmz80_a_LIBADD) $(RANLIB) libmz80.a tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = mz80 distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done info-am: info: info-am dvi-am: dvi: dvi-am check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am install-exec-am: install-exec: install-exec-am install-data-am: install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am uninstall-am: uninstall: uninstall-am all-am: Makefile $(LIBRARIES) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ mostlyclean-tags mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ mostlyclean-am clean: clean-am distclean-am: distclean-noinstLIBRARIES distclean-compile \ distclean-tags distclean-generic clean-am distclean: distclean-am maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean-compile maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-am .PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile tags mostlyclean-tags distclean-tags \ clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ check-am installcheck-am installcheck install-exec-am install-exec \ install-data-am install-data install-am install uninstall-am uninstall \ all-redirect all-am all installdirs mostlyclean-generic \ distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean distclean maintainer-clean .asm.o: @NASM@ -f @NASM_FMT@ $< .asmu.o: @@CHOP_@ $< > .$< @NASM@ -f @NASM_FMT@ -o $@ .$< @rm -f .$< # Since the chop_ script flakes on mz80, we use mz80's builtin facility @NO_USCORE_TRUE@ plain = -l @NO_USCORE_FALSE@ plain = makez80: makez80.c $(CC) -o makez80 makez80.c mz80.asm: makez80 ./makez80 $(plain) -s -x86 mz80.asm # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: dgen-sdl-1.23/mz80/Makefile.am 644 1750 1750 1016 7176134543 11117 # DGen/SDL v1.20+ # Automakefile for mz80 include $(top_srcdir)/Makefile.asm.am # Since the chop_ script flakes on mz80, we use mz80's builtin facility if NO_USCORE plain = -l else plain = endif INCLUDES += -I.. EXTRA_DIST = mz80.txt noinst_LIBRARIES = libmz80.a makez80: makez80.c $(CC) -o makez80 makez80.c mz80.asm: makez80 ./makez80 $(plain) -s -x86 mz80.asm libmz80_a_SOURCES = libmz80_a_LIBADD = mz80.o libmz80_a_DEPENDENCIES = mz80.o EXTRA_libmz80_a_SOURCES = makez80.c DISTCLEANFILES = mz80.asm makez80 dgen-sdl-1.23/mz80/makez80.c 644 1750 1750 1106646 7065023744 10603 /* Multi-Z80 32 Bit emulator */ /* Copyright 1996, 1997, 1998, 1999, 2000 Neil Bradley, All rights reserved * * License agreement: * * (MZ80 Refers to both the assembly and C code emitted by makeZ80.c and * makeZ80.c itself) * * MZ80 May be distributed in unmodified form to any medium. * * MZ80 May not be sold, or sold as a part of a commercial package without * the express written permission of Neil Bradley (neil@synthcom.com). This * includes shareware. * * Modified versions of MZ80 may not be publicly redistributed without author * approval (neil@synthcom.com). This includes distributing via a publicly * accessible LAN. You may make your own source modifications and distribute * MZ80 in source or object form, but if you make modifications to MZ80 * then it should be noted in the top as a comment in makeZ80.c. * * MZ80 Licensing for commercial applications is available. Please email * neil@synthcom.com for details. * * Synthcom Systems, Inc, and Neil Bradley will not be held responsible for * any damage done by the use of MZ80. It is purely "as-is". * * If you use MZ80 in a freeware application, credit in the following text: * * "Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)" * * must accompany the freeware application within the application itself or * in the documentation. * * Legal stuff aside: * * If you find problems with MZ80, please email the author so they can get * resolved. If you find a bug and fix it, please also email the author so * that those bug fixes can be propogated to the installed base of MZ80 * users. If you find performance improvements or problems with MZ80, please * email the author with your changes/suggestions and they will be rolled in * with subsequent releases of MZ80. * * The whole idea of this emulator is to have the fastest available 32 bit * Multi-Z80 emulator for the PC, giving maximum performance. * */ #include #include #include #include #define VERSION "3.4" #define TRUE 0xff #define FALSE 0x0 #define INVALID 0xff #define UINT32 unsigned long int #define UINT8 unsigned char #define TIMING_REGULAR 0x00 #define TIMING_XXCB 0x01 #define TIMING_CB 0xcb #define TIMING_DDFD 0xdd #define TIMING_ED 0xed #define TIMING_EXCEPT 0x02 FILE *fp = NULL; char string[150]; char cpubasename[150]; static char mz80Index[50]; static char mz80IndexHalfHigh[50]; static char mz80IndexHalfLow[50]; char majorOp[50]; char procname[150]; UINT32 dwGlobalLabel = 0; enum { MZ80_ASSEMBLY_X86, MZ80_C, MZ80_UNKNOWN }; UINT8 bPlain = FALSE; UINT8 bNoTiming = FALSE; UINT8 bUseStack = 0; UINT8 bCurrentMode = TIMING_REGULAR; // Current timing mode UINT8 b16BitIo = FALSE; UINT8 bThroughCallHandler = FALSE; UINT8 bOS2 = FALSE; UINT8 bWhat = MZ80_UNKNOWN; void ProcBegin(UINT32 dwOpcode); UINT8 *pbLocalReg[8] = { "ch", "cl", "dh", "dl", "bh", "bl", "dl", "al" }; UINT8 *pbLocalRegC[8] = { "cpu.z80B", "cpu.z80C", "cpu.z80D", "cpu.z80E", "cpu.z80H", "cpu.z80L", "barf", "cpu.z80A" }; UINT8 *pbPushReg[8] = { "cl", "ch", "byte [_z80de]", "byte [_z80de + 1]", "bl", "bh", "ah", "al" }; UINT8 *pbFlags[8] = { "nz", "z", "nc", "c", "po", "pe", "ns", "s" }; UINT8 *pbRegPairC[] = { "cpu.z80BC", "cpu.z80DE", "cpu.z80HL", "cpu.z80sp" }; UINT8 *pbFlagsC[8] = { "(!(cpu.z80F & Z80_FLAG_ZERO))", "(cpu.z80F & Z80_FLAG_ZERO)", "(!(cpu.z80F & Z80_FLAG_CARRY))", "(cpu.z80F & Z80_FLAG_CARRY)", "(!(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY))", "(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY)", "(!(cpu.z80F & Z80_FLAG_SIGN))", "(cpu.z80F & Z80_FLAG_SIGN)" }; UINT8 *pbMathReg[8] = { "ch", "cl", "byte [_z80de + 1]", "byte [_z80de]", "bh", "bl", "INVALID", "al" }; UINT8 *pbMathRegC[8] = { "cpu.z80B", "cpu.z80C", "cpu.z80D", "cpu.z80E", "cpu.z80H", "cpu.z80L", "bTemp", "cpu.z80A" }; UINT8 *pbRegPairs[4] = { "cx", // BC "word [_z80de]", // DE "bx", // HL "word [_z80sp]" // SP }; UINT8 *pbRegPairsC[4] = { "cpu.z80BC", // BC "cpu.z80DE", // DE "cpu.z80HL", // HL "cpu.z80sp" // SP }; UINT8 *pbPopRegPairs[4] = { "cx", // BC "word [_z80de]", // DE "bx", // HL "ax" // SP }; UINT8 *pbPopRegPairC[4] = { "cpu.z80BC", "cpu.z80DE", "cpu.z80HL", "cpu.z80AF" }; UINT8 *pbIndexedRegPairs[4] = { "cx", // BC "word [_z80de]", // DE "di", // IX/IY "word [_z80sp]" // SP }; // Timing tables UINT8 bTimingRegular[0x100] = { 0x04, 0x0a, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x04, 0x0b, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x08, 0x0a, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x0c, 0x0b, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x07, 0x0a, 0x10, 0x06, 0x04, 0x04, 0x07, 0x04, 0x07, 0x0b, 0x10, 0x06, 0x04, 0x04, 0x07, 0x04, 0x07, 0x0a, 0x0d, 0x06, 0x0b, 0x0b, 0x0a, 0x04, 0x07, 0x0b, 0x0d, 0x06, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x00, 0x0a, 0x11, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x0b, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x04, 0x0a, 0x0b, 0x0a, 0x00, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x13, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x04, 0x0a, 0x04, 0x0a, 0x00, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x04, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x06, 0x0a, 0x04, 0x0a, 0x00, 0x07, 0x0b }; UINT8 bTimingCB[0x100] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08 }; UINT8 bTimingXXCB[0x100] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00 }; UINT8 bTimingDDFD[0x100] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x14, 0x0a, 0x09, 0x09, 0x09, 0x00, 0x00, 0x0f, 0x14, 0x0a, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x13, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x13, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x13, 0x09, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; UINT8 bTimingED[0x100] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x0e, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x0e, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x12, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x12, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void EDHandler(UINT32 dwOpcode); void DDHandler(UINT32 dwOpcode); void FDHandler(UINT32 dwOpcode); void CBHandler(UINT32 dwOpcode); void PushPopOperations(UINT32 dwOpcode); void AddRegpairOperations(UINT32 dwOpcode); void CallHandler(UINT32 dwOpcode); void MiscHandler(UINT32 dwOpcode); void IMHandler(UINT32 dwOpcode); void IRHandler(UINT32 dwOpcode); void LdRegPairImmediate(UINT32 dwOpcode); void LoadImmediate(UINT32 dwOpcode); void LdRegpairPtrByte(UINT32 dwOpcode); void MathOperation(UINT32 dwOpcode); void RegIntoMemory(UINT32 dwOpcode); void JpHandler(UINT32 dwOpcode); void LdRegImmediate(UINT32 dwOpcode); void IncRegister(UINT32 dwOpcode); void DecRegister(UINT32 dwOpcode); void IncDecRegpair(UINT32 dwOpcode); void LdRegReg(UINT32 dwOpcode); void MathOperationDirect(UINT32 dwOpcode); void JrHandler(UINT32 dwOpcode); void RetHandler(UINT32 dwOpcode); void RestartHandler(UINT32 dwOpcode); void ToRegFromHl(UINT32); void RraRlaHandler(UINT32); void LdByteRegpair(UINT32); void IncDecHLPtr(UINT32 dwOpcode); void InOutHandler(UINT32 dwOpcode); void RLCRRCRLRRSLASRASRLHandler(UINT32 dwOpcode); void BITHandler(UINT32 dwOpcode); void RESSETHandler(UINT32 dwOpcode); void PushPopOperationsIndexed(UINT32 dwOpcode); void LDILDRLDIRLDDRHandler(UINT32); void LdRegpair(UINT32 dwOpcode); void ExtendedRegIntoMemory(UINT32 dwOpcode); void NegHandler(UINT32 dwOpcode); void ExtendedInHandler(UINT32 dwOpcode); void ExtendedOutHandler(UINT32 dwOpcode); void RetIRetNHandler(UINT32 dwOcode); void AdcSbcRegpair(UINT32 dwOpcode); void CPICPDCPIRCPDRHandler(UINT32 dwOpcode); void RRDRLDHandler(UINT32 dwOpcode); void UndocRegToIndex(UINT32 dwOpcode); void UndocIndexToReg(UINT32 dwOpcode); void MathOperationIndexed(UINT32 dwOpcode); void IncDecIndexed(UINT32 dwOpcode); void DDFDCBHandler(UINT32 dwOpcode); void JPIXIYHandler(UINT32 dwOpcode); void AddIndexHandler(UINT32 dwOpcode); void SPToIndex(UINT32 dwOpcode); void LdByteToIndex(UINT32 dwOpcode); void LdRegIndexOffset(UINT32 dwOpcode); void IncDecIndexReg(UINT32 dwOpcode); void ExIndexed(UINT32 dwOpcode); void UndocIncDecIndexReg(UINT32 dwOpcode); void UndocLoadHalfIndexReg(UINT32 dwOpcode); void UndocMathIndex(UINT32 dwOpcode); void ddcbBitWise(UINT32 dwOpcode); void LdIndexPtrReg(UINT32 dwOpcode); void StoreIndexReg(UINT32 dwOpcode); void LoadIndexReg(UINT32 dwOpcode); void OTIROTDROUTIOUTDHandler(UINT32 dwOpcode); void INIRINDRINIINDHandler(UINT32 dwOpcode); struct sOp { UINT32 bOpCode; void (*Emitter)(UINT32); }; struct sOp StandardOps[] = { {0xd3, InOutHandler}, // V {0xdb, InOutHandler}, // V {0x0a, LdByteRegpair}, // V {0x1a, LdByteRegpair}, // V {0x17, RraRlaHandler}, // V {0x1f, RraRlaHandler}, // V {0x05, DecRegister}, // V {0x0d, DecRegister}, // V {0x15, DecRegister}, // V {0x1d, DecRegister}, // V {0x25, DecRegister}, // V {0x2d, DecRegister}, // V {0x3d, DecRegister}, // V {0x04, IncRegister}, // V {0x0c, IncRegister}, // V {0x14, IncRegister}, // V {0x1c, IncRegister}, // V {0x24, IncRegister}, // V {0x2c, IncRegister}, // V {0x3c, IncRegister}, // V {0x32, RegIntoMemory}, // V {0x22, RegIntoMemory}, // V {0xc3, JpHandler}, // V {0xc2, JpHandler}, // V {0xca, JpHandler}, // V {0xd2, JpHandler}, // V {0xda, JpHandler}, // V {0xe2, JpHandler}, // V {0xea, JpHandler}, // V {0xf2, JpHandler}, // V {0xfa, JpHandler}, // V {0x06, LdRegImmediate}, // V {0x0e, LdRegImmediate}, // V {0x16, LdRegImmediate}, // V {0x1e, LdRegImmediate}, // V {0x26, LdRegImmediate}, // V {0x2e, LdRegImmediate}, // V {0x3e, LdRegImmediate}, // V {0x0b, IncDecRegpair}, // V {0x1b, IncDecRegpair}, // V {0x2b, IncDecRegpair}, // V {0x3b, IncDecRegpair}, // V {0x03, IncDecRegpair}, // V {0x13, IncDecRegpair}, // V {0x23, IncDecRegpair}, // V {0x33, IncDecRegpair}, // V {0x34, IncDecHLPtr}, // V {0x35, IncDecHLPtr}, // V {0xcb, CBHandler}, {0xdd, DDHandler}, {0xed, EDHandler}, {0xfd, FDHandler}, {0x01, LdRegPairImmediate}, // V {0x11, LdRegPairImmediate}, // V {0x21, LdRegPairImmediate}, // V {0x31, LdRegPairImmediate}, // V {0xe3, MiscHandler}, // V {0x2a, MiscHandler}, // V {0xfb, MiscHandler}, // V {0xf9, MiscHandler}, // V {0xd9, MiscHandler}, // V {0x76, MiscHandler}, // V {0x3f, MiscHandler}, // V {0x37, MiscHandler}, // V {0x27, MiscHandler}, // V {0x07, MiscHandler}, // V {0x08, MiscHandler}, // V {0x00, MiscHandler}, // V {0xe9, MiscHandler}, // V {0xeb, MiscHandler}, // V {0xf3, MiscHandler}, // V {0x3a, MiscHandler}, // V {0x10, MiscHandler}, // V {0x2f, MiscHandler}, // V {0x0f, MiscHandler}, // V {0x02, LdRegpairPtrByte}, // V {0x12, LdRegpairPtrByte}, // V {0x70, LdRegpairPtrByte}, // V {0x71, LdRegpairPtrByte}, // V {0x72, LdRegpairPtrByte}, // V {0x73, LdRegpairPtrByte}, // V {0x74, LdRegpairPtrByte}, // V {0x75, LdRegpairPtrByte}, // V {0x77, LdRegpairPtrByte}, // V {0x36, LdRegpairPtrByte}, // V {0x80, MathOperation}, // V {0x81, MathOperation}, // V {0x82, MathOperation}, // V {0x83, MathOperation}, // V {0x84, MathOperation}, // V {0x85, MathOperation}, // V {0x86, MathOperation}, // V {0x87, MathOperation}, // V {0x88, MathOperation}, // V {0x89, MathOperation}, // V {0x8a, MathOperation}, // V {0x8b, MathOperation}, // V {0x8c, MathOperation}, // V {0x8d, MathOperation}, // V {0x8e, MathOperation}, // V {0x8f, MathOperation}, // V {0x90, MathOperation}, // V {0x91, MathOperation}, // V {0x92, MathOperation}, // V {0x93, MathOperation}, // V {0x94, MathOperation}, // V {0x95, MathOperation}, // V {0x96, MathOperation}, // V {0x97, MathOperation}, // V {0x98, MathOperation}, // V {0x99, MathOperation}, // V {0x9a, MathOperation}, // V {0x9b, MathOperation}, // V {0x9c, MathOperation}, // V {0x9d, MathOperation}, // V {0x9e, MathOperation}, // V {0x9f, MathOperation}, // V {0xa0, MathOperation}, // V {0xa1, MathOperation}, // V {0xa2, MathOperation}, // V {0xa3, MathOperation}, // V {0xa4, MathOperation}, // V {0xa5, MathOperation}, // V {0xa6, MathOperation}, // V {0xa7, MathOperation}, // V {0xa8, MathOperation}, // V {0xa9, MathOperation}, // V {0xaa, MathOperation}, // V {0xab, MathOperation}, // V {0xac, MathOperation}, // V {0xad, MathOperation}, // V {0xae, MathOperation}, // V {0xaf, MathOperation}, // V {0xb0, MathOperation}, // V {0xb1, MathOperation}, // V {0xb2, MathOperation}, // V {0xb3, MathOperation}, // V {0xb4, MathOperation}, // V {0xb5, MathOperation}, // V {0xb6, MathOperation}, // V {0xb7, MathOperation}, // V {0xb8, MathOperation}, // V {0xb9, MathOperation}, // V {0xba, MathOperation}, // V {0xbb, MathOperation}, // V {0xbc, MathOperation}, // V {0xbd, MathOperation}, // V {0xbe, MathOperation}, // V {0xbf, MathOperation}, // V {0x40, LdRegReg}, // V {0x41, LdRegReg}, // V {0x42, LdRegReg}, // V {0x43, LdRegReg}, // V {0x44, LdRegReg}, // V {0x45, LdRegReg}, // V {0x47, LdRegReg}, // V {0x48, LdRegReg}, // V {0x49, LdRegReg}, // V {0x4a, LdRegReg}, // V {0x4b, LdRegReg}, // V {0x4c, LdRegReg}, // V {0x4d, LdRegReg}, // V {0x4f, LdRegReg}, // V {0x50, LdRegReg}, // V {0x51, LdRegReg}, // V {0x52, LdRegReg}, // V {0x53, LdRegReg}, // V {0x54, LdRegReg}, // V {0x55, LdRegReg}, // V {0x57, LdRegReg}, // V {0x58, LdRegReg}, // V {0x59, LdRegReg}, // V {0x5a, LdRegReg}, // V {0x5b, LdRegReg}, // V {0x5c, LdRegReg}, // V {0x5d, LdRegReg}, // V {0x5f, LdRegReg}, // V {0x60, LdRegReg}, // V {0x61, LdRegReg}, // V {0x62, LdRegReg}, // V {0x63, LdRegReg}, // V {0x64, LdRegReg}, // V {0x65, LdRegReg}, // V {0x67, LdRegReg}, // V {0x68, LdRegReg}, // V {0x69, LdRegReg}, // V {0x6a, LdRegReg}, // V {0x6b, LdRegReg}, // V {0x6c, LdRegReg}, // V {0x6d, LdRegReg}, // V {0x6f, LdRegReg}, // V {0x78, LdRegReg}, // V {0x79, LdRegReg}, // V {0x7a, LdRegReg}, // V {0x7b, LdRegReg}, // V {0x7c, LdRegReg}, // V {0x7d, LdRegReg}, // V {0x7f, LdRegReg}, // V {0xc6, MathOperationDirect}, // V {0xce, MathOperationDirect}, // V {0xd6, MathOperationDirect}, // V {0xde, MathOperationDirect}, // V {0xe6, MathOperationDirect}, // V {0xee, MathOperationDirect}, // V {0xf6, MathOperationDirect}, // V {0xfe, MathOperationDirect}, // V {0x18, JrHandler}, // V {0x20, JrHandler}, // V {0x28, JrHandler}, // V {0x30, JrHandler}, // V {0x38, JrHandler}, {0xc4, CallHandler}, // V {0xcc, CallHandler}, // V {0xcd, CallHandler}, // V {0xd4, CallHandler}, // V {0xdc, CallHandler}, // V {0xe4, CallHandler}, // V {0xec, CallHandler}, // V {0xf4, CallHandler}, // V {0xfc, CallHandler}, // V {0xc9, RetHandler}, // V {0xc0, RetHandler}, // V {0xc8, RetHandler}, // V {0xd0, RetHandler}, // V {0xd8, RetHandler}, // V {0xe0, RetHandler}, // V {0xe8, RetHandler}, // V {0xf0, RetHandler}, // V {0xf8, RetHandler}, // V {0xc7, RestartHandler}, // V {0xcf, RestartHandler}, // V {0xd7, RestartHandler}, // V {0xdf, RestartHandler}, // V {0xe7, RestartHandler}, // V {0xef, RestartHandler}, // V {0xf7, RestartHandler}, // V {0xff, RestartHandler}, // V {0x46, ToRegFromHl}, // V {0x4e, ToRegFromHl}, // V {0x56, ToRegFromHl}, // V {0x5e, ToRegFromHl}, // V {0x66, ToRegFromHl}, // V {0x6e, ToRegFromHl}, // V {0x7e, ToRegFromHl}, {0x09, AddRegpairOperations}, // V {0x19, AddRegpairOperations}, // V {0x29, AddRegpairOperations}, // V {0x39, AddRegpairOperations}, // V {0xc5, PushPopOperations}, // V {0xd5, PushPopOperations}, // V {0xe5, PushPopOperations}, // V {0xf5, PushPopOperations}, // V {0xc1, PushPopOperations}, // V {0xd1, PushPopOperations}, // V {0xe1, PushPopOperations}, // V {0xf1, PushPopOperations}, // V // Terminator {0xffffffff, NULL} }; struct sOp CBOps[] = { {0x00, RLCRRCRLRRSLASRASRLHandler}, {0x01, RLCRRCRLRRSLASRASRLHandler}, {0x02, RLCRRCRLRRSLASRASRLHandler}, {0x03, RLCRRCRLRRSLASRASRLHandler}, {0x04, RLCRRCRLRRSLASRASRLHandler}, {0x05, RLCRRCRLRRSLASRASRLHandler}, {0x06, RLCRRCRLRRSLASRASRLHandler}, {0x07, RLCRRCRLRRSLASRASRLHandler}, {0x08, RLCRRCRLRRSLASRASRLHandler}, {0x09, RLCRRCRLRRSLASRASRLHandler}, {0x0a, RLCRRCRLRRSLASRASRLHandler}, {0x0b, RLCRRCRLRRSLASRASRLHandler}, {0x0c, RLCRRCRLRRSLASRASRLHandler}, {0x0d, RLCRRCRLRRSLASRASRLHandler}, {0x0e, RLCRRCRLRRSLASRASRLHandler}, {0x0f, RLCRRCRLRRSLASRASRLHandler}, {0x10, RLCRRCRLRRSLASRASRLHandler}, {0x11, RLCRRCRLRRSLASRASRLHandler}, {0x12, RLCRRCRLRRSLASRASRLHandler}, {0x13, RLCRRCRLRRSLASRASRLHandler}, {0x14, RLCRRCRLRRSLASRASRLHandler}, {0x15, RLCRRCRLRRSLASRASRLHandler}, {0x16, RLCRRCRLRRSLASRASRLHandler}, {0x17, RLCRRCRLRRSLASRASRLHandler}, {0x18, RLCRRCRLRRSLASRASRLHandler}, {0x19, RLCRRCRLRRSLASRASRLHandler}, {0x1a, RLCRRCRLRRSLASRASRLHandler}, {0x1b, RLCRRCRLRRSLASRASRLHandler}, {0x1c, RLCRRCRLRRSLASRASRLHandler}, {0x1d, RLCRRCRLRRSLASRASRLHandler}, {0x1e, RLCRRCRLRRSLASRASRLHandler}, {0x1f, RLCRRCRLRRSLASRASRLHandler}, {0x20, RLCRRCRLRRSLASRASRLHandler}, {0x21, RLCRRCRLRRSLASRASRLHandler}, {0x22, RLCRRCRLRRSLASRASRLHandler}, {0x23, RLCRRCRLRRSLASRASRLHandler}, {0x24, RLCRRCRLRRSLASRASRLHandler}, {0x25, RLCRRCRLRRSLASRASRLHandler}, {0x26, RLCRRCRLRRSLASRASRLHandler}, {0x27, RLCRRCRLRRSLASRASRLHandler}, {0x28, RLCRRCRLRRSLASRASRLHandler}, {0x29, RLCRRCRLRRSLASRASRLHandler}, {0x2a, RLCRRCRLRRSLASRASRLHandler}, {0x2b, RLCRRCRLRRSLASRASRLHandler}, {0x2c, RLCRRCRLRRSLASRASRLHandler}, {0x2d, RLCRRCRLRRSLASRASRLHandler}, {0x2e, RLCRRCRLRRSLASRASRLHandler}, {0x2f, RLCRRCRLRRSLASRASRLHandler}, {0x30, RLCRRCRLRRSLASRASRLHandler}, {0x31, RLCRRCRLRRSLASRASRLHandler}, {0x32, RLCRRCRLRRSLASRASRLHandler}, {0x33, RLCRRCRLRRSLASRASRLHandler}, {0x34, RLCRRCRLRRSLASRASRLHandler}, {0x35, RLCRRCRLRRSLASRASRLHandler}, {0x36, RLCRRCRLRRSLASRASRLHandler}, {0x37, RLCRRCRLRRSLASRASRLHandler}, {0x38, RLCRRCRLRRSLASRASRLHandler}, {0x39, RLCRRCRLRRSLASRASRLHandler}, {0x3a, RLCRRCRLRRSLASRASRLHandler}, {0x3b, RLCRRCRLRRSLASRASRLHandler}, {0x3c, RLCRRCRLRRSLASRASRLHandler}, {0x3d, RLCRRCRLRRSLASRASRLHandler}, {0x3e, RLCRRCRLRRSLASRASRLHandler}, {0x3f, RLCRRCRLRRSLASRASRLHandler}, {0x40, BITHandler}, {0x41, BITHandler}, {0x42, BITHandler}, {0x43, BITHandler}, {0x44, BITHandler}, {0x45, BITHandler}, {0x46, BITHandler}, {0x47, BITHandler}, {0x48, BITHandler}, {0x49, BITHandler}, {0x4a, BITHandler}, {0x4b, BITHandler}, {0x4c, BITHandler}, {0x4d, BITHandler}, {0x4e, BITHandler}, {0x4f, BITHandler}, {0x50, BITHandler}, {0x51, BITHandler}, {0x52, BITHandler}, {0x53, BITHandler}, {0x54, BITHandler}, {0x55, BITHandler}, {0x56, BITHandler}, {0x57, BITHandler}, {0x58, BITHandler}, {0x59, BITHandler}, {0x5a, BITHandler}, {0x5b, BITHandler}, {0x5c, BITHandler}, {0x5d, BITHandler}, {0x5e, BITHandler}, {0x5f, BITHandler}, {0x60, BITHandler}, {0x61, BITHandler}, {0x62, BITHandler}, {0x63, BITHandler}, {0x64, BITHandler}, {0x65, BITHandler}, {0x66, BITHandler}, {0x67, BITHandler}, {0x68, BITHandler}, {0x69, BITHandler}, {0x6a, BITHandler}, {0x6b, BITHandler}, {0x6c, BITHandler}, {0x6d, BITHandler}, {0x6e, BITHandler}, {0x6f, BITHandler}, {0x70, BITHandler}, {0x71, BITHandler}, {0x72, BITHandler}, {0x73, BITHandler}, {0x74, BITHandler}, {0x75, BITHandler}, {0x76, BITHandler}, {0x77, BITHandler}, {0x78, BITHandler}, {0x79, BITHandler}, {0x7a, BITHandler}, {0x7b, BITHandler}, {0x7c, BITHandler}, {0x7d, BITHandler}, {0x7e, BITHandler}, {0x7f, BITHandler}, // RES {0x80, RESSETHandler}, {0x81, RESSETHandler}, {0x82, RESSETHandler}, {0x83, RESSETHandler}, {0x84, RESSETHandler}, {0x85, RESSETHandler}, {0x86, RESSETHandler}, {0x87, RESSETHandler}, {0x88, RESSETHandler}, {0x89, RESSETHandler}, {0x8a, RESSETHandler}, {0x8b, RESSETHandler}, {0x8c, RESSETHandler}, {0x8d, RESSETHandler}, {0x8e, RESSETHandler}, {0x8f, RESSETHandler}, {0x90, RESSETHandler}, {0x91, RESSETHandler}, {0x92, RESSETHandler}, {0x93, RESSETHandler}, {0x94, RESSETHandler}, {0x95, RESSETHandler}, {0x96, RESSETHandler}, {0x97, RESSETHandler}, {0x98, RESSETHandler}, {0x99, RESSETHandler}, {0x9a, RESSETHandler}, {0x9b, RESSETHandler}, {0x9c, RESSETHandler}, {0x9d, RESSETHandler}, {0x9e, RESSETHandler}, {0x9f, RESSETHandler}, {0xa0, RESSETHandler}, {0xa1, RESSETHandler}, {0xa2, RESSETHandler}, {0xa3, RESSETHandler}, {0xa4, RESSETHandler}, {0xa5, RESSETHandler}, {0xa6, RESSETHandler}, {0xa7, RESSETHandler}, {0xa8, RESSETHandler}, {0xa9, RESSETHandler}, {0xaa, RESSETHandler}, {0xab, RESSETHandler}, {0xac, RESSETHandler}, {0xad, RESSETHandler}, {0xae, RESSETHandler}, {0xaf, RESSETHandler}, {0xb0, RESSETHandler}, {0xb1, RESSETHandler}, {0xb2, RESSETHandler}, {0xb3, RESSETHandler}, {0xb4, RESSETHandler}, {0xb5, RESSETHandler}, {0xb6, RESSETHandler}, {0xb7, RESSETHandler}, {0xb8, RESSETHandler}, {0xb9, RESSETHandler}, {0xba, RESSETHandler}, {0xbb, RESSETHandler}, {0xbc, RESSETHandler}, {0xbd, RESSETHandler}, {0xbe, RESSETHandler}, {0xbf, RESSETHandler}, // SET {0xc0, RESSETHandler}, {0xc1, RESSETHandler}, {0xc2, RESSETHandler}, {0xc3, RESSETHandler}, {0xc4, RESSETHandler}, {0xc5, RESSETHandler}, {0xc6, RESSETHandler}, {0xc7, RESSETHandler}, {0xc8, RESSETHandler}, {0xc9, RESSETHandler}, {0xca, RESSETHandler}, {0xcb, RESSETHandler}, {0xcc, RESSETHandler}, {0xcd, RESSETHandler}, {0xce, RESSETHandler}, {0xcf, RESSETHandler}, {0xd0, RESSETHandler}, {0xd1, RESSETHandler}, {0xd2, RESSETHandler}, {0xd3, RESSETHandler}, {0xd4, RESSETHandler}, {0xd5, RESSETHandler}, {0xd6, RESSETHandler}, {0xd7, RESSETHandler}, {0xd8, RESSETHandler}, {0xd9, RESSETHandler}, {0xda, RESSETHandler}, {0xdb, RESSETHandler}, {0xdc, RESSETHandler}, {0xdd, RESSETHandler}, {0xde, RESSETHandler}, {0xdf, RESSETHandler}, {0xe0, RESSETHandler}, {0xe1, RESSETHandler}, {0xe2, RESSETHandler}, {0xe3, RESSETHandler}, {0xe4, RESSETHandler}, {0xe5, RESSETHandler}, {0xe6, RESSETHandler}, {0xe7, RESSETHandler}, {0xe8, RESSETHandler}, {0xe9, RESSETHandler}, {0xea, RESSETHandler}, {0xeb, RESSETHandler}, {0xec, RESSETHandler}, {0xed, RESSETHandler}, {0xee, RESSETHandler}, {0xef, RESSETHandler}, {0xf0, RESSETHandler}, {0xf1, RESSETHandler}, {0xf2, RESSETHandler}, {0xf3, RESSETHandler}, {0xf4, RESSETHandler}, {0xf5, RESSETHandler}, {0xf6, RESSETHandler}, {0xf7, RESSETHandler}, {0xf8, RESSETHandler}, {0xf9, RESSETHandler}, {0xfa, RESSETHandler}, {0xfb, RESSETHandler}, {0xfc, RESSETHandler}, {0xfd, RESSETHandler}, {0xfe, RESSETHandler}, {0xff, RESSETHandler}, // Terminator {0xffffffff, NULL} }; struct sOp EDOps[] = { {0x67, RRDRLDHandler}, {0x6f, RRDRLDHandler}, {0x42, AdcSbcRegpair}, {0x4a, AdcSbcRegpair}, {0x52, AdcSbcRegpair}, {0x5a, AdcSbcRegpair}, {0x62, AdcSbcRegpair}, {0x6a, AdcSbcRegpair}, {0x72, AdcSbcRegpair}, {0x7a, AdcSbcRegpair}, {0x45, RetIRetNHandler}, {0x4d, RetIRetNHandler}, {0x44, NegHandler}, {0xa0, LDILDRLDIRLDDRHandler}, {0xa8, LDILDRLDIRLDDRHandler}, {0xb0, LDILDRLDIRLDDRHandler}, {0xb8, LDILDRLDIRLDDRHandler}, {0x57, IRHandler}, {0x5F, IRHandler}, {0x47, IRHandler}, {0x4F, IRHandler}, {0x46, IMHandler}, {0x56, IMHandler}, {0x5e, IMHandler}, {0x4b, LdRegpair}, {0x5b, LdRegpair}, {0x7b, LdRegpair}, {0x43, ExtendedRegIntoMemory}, {0x53, ExtendedRegIntoMemory}, {0x63, ExtendedRegIntoMemory}, {0x73, ExtendedRegIntoMemory}, {0x40, ExtendedInHandler}, {0x48, ExtendedInHandler}, {0x50, ExtendedInHandler}, {0x58, ExtendedInHandler}, {0x60, ExtendedInHandler}, {0x68, ExtendedInHandler}, {0x78, ExtendedInHandler}, {0x41, ExtendedOutHandler}, {0x49, ExtendedOutHandler}, {0x51, ExtendedOutHandler}, {0x59, ExtendedOutHandler}, {0x61, ExtendedOutHandler}, {0x69, ExtendedOutHandler}, {0x79, ExtendedOutHandler}, {0xa1, CPICPDCPIRCPDRHandler}, {0xa9, CPICPDCPIRCPDRHandler}, {0xb1, CPICPDCPIRCPDRHandler}, {0xb9, CPICPDCPIRCPDRHandler}, {0xbb, OTIROTDROUTIOUTDHandler}, // OTDR {0xb3, OTIROTDROUTIOUTDHandler}, // OTIR {0xab, OTIROTDROUTIOUTDHandler}, // OUTD {0xa3, OTIROTDROUTIOUTDHandler}, // OUTI {0xb2, INIRINDRINIINDHandler}, // INIR {0xba, INIRINDRINIINDHandler}, // INDR {0xa2, INIRINDRINIINDHandler}, // INI {0xaa, INIRINDRINIINDHandler}, // IND // Terminator {0xffffffff, NULL} }; struct sOp DDFDOps[] = { {0x35, IncDecIndexed}, {0x34, IncDecIndexed}, {0xcb, DDFDCBHandler}, {0x86, MathOperationIndexed}, {0x8e, MathOperationIndexed}, {0x96, MathOperationIndexed}, {0x9e, MathOperationIndexed}, {0xa6, MathOperationIndexed}, {0xae, MathOperationIndexed}, {0xb6, MathOperationIndexed}, {0xbe, MathOperationIndexed}, {0xe1, PushPopOperationsIndexed}, {0xe5, PushPopOperationsIndexed}, {0x21, LoadImmediate}, {0xe9, JPIXIYHandler}, {0x09, AddIndexHandler}, {0x19, AddIndexHandler}, {0x29, AddIndexHandler}, {0x39, AddIndexHandler}, {0xf9, SPToIndex}, {0x36, LdByteToIndex}, {0x46, LdRegIndexOffset}, {0x4e, LdRegIndexOffset}, {0x56, LdRegIndexOffset}, {0x5e, LdRegIndexOffset}, {0x66, LdRegIndexOffset}, {0x6e, LdRegIndexOffset}, {0x7e, LdRegIndexOffset}, {0x70, LdIndexPtrReg}, {0x71, LdIndexPtrReg}, {0x72, LdIndexPtrReg}, {0x73, LdIndexPtrReg}, {0x74, LdIndexPtrReg}, {0x75, LdIndexPtrReg}, {0x77, LdIndexPtrReg}, {0x23, IncDecIndexReg}, {0x2b, IncDecIndexReg}, {0x22, StoreIndexReg}, {0x2a, LoadIndexReg}, {0xe3, ExIndexed}, {0x44, UndocRegToIndex}, {0x45, UndocRegToIndex}, {0x4c, UndocRegToIndex}, {0x4d, UndocRegToIndex}, {0x54, UndocRegToIndex}, {0x55, UndocRegToIndex}, {0x5c, UndocRegToIndex}, {0x5d, UndocRegToIndex}, {0x7c, UndocRegToIndex}, {0x7d, UndocRegToIndex}, {0x60, UndocIndexToReg}, {0x61, UndocIndexToReg}, {0x62, UndocIndexToReg}, {0x63, UndocIndexToReg}, {0x64, UndocIndexToReg}, {0x65, UndocIndexToReg}, {0x67, UndocIndexToReg}, {0x68, UndocIndexToReg}, {0x69, UndocIndexToReg}, {0x6a, UndocIndexToReg}, {0x6b, UndocIndexToReg}, {0x6c, UndocIndexToReg}, {0x6d, UndocIndexToReg}, {0x6f, UndocIndexToReg}, {0x24, UndocIncDecIndexReg}, {0x25, UndocIncDecIndexReg}, {0x2c, UndocIncDecIndexReg}, {0x2d, UndocIncDecIndexReg}, {0x26, UndocLoadHalfIndexReg}, {0x2e, UndocLoadHalfIndexReg}, {0x84, UndocMathIndex}, {0x85, UndocMathIndex}, {0x8c, UndocMathIndex}, {0x8d, UndocMathIndex}, {0x94, UndocMathIndex}, {0x95, UndocMathIndex}, {0x9c, UndocMathIndex}, {0x9d, UndocMathIndex}, {0xa4, UndocMathIndex}, {0xa5, UndocMathIndex}, {0xac, UndocMathIndex}, {0xad, UndocMathIndex}, {0xb4, UndocMathIndex}, {0xb5, UndocMathIndex}, {0xbc, UndocMathIndex}, {0xbd, UndocMathIndex}, // Terminator {0xffffffff, NULL} }; struct sOp DDFDCBOps[] = { {0x06, ddcbBitWise}, {0x0e, ddcbBitWise}, {0x16, ddcbBitWise}, {0x1e, ddcbBitWise}, {0x26, ddcbBitWise}, {0x2e, ddcbBitWise}, {0x3e, ddcbBitWise}, {0x46, ddcbBitWise}, {0x4e, ddcbBitWise}, {0x56, ddcbBitWise}, {0x5e, ddcbBitWise}, {0x66, ddcbBitWise}, {0x6e, ddcbBitWise}, {0x76, ddcbBitWise}, {0x7e, ddcbBitWise}, {0x86, ddcbBitWise}, {0x8e, ddcbBitWise}, {0x96, ddcbBitWise}, {0x9e, ddcbBitWise}, {0xa6, ddcbBitWise}, {0xae, ddcbBitWise}, {0xb6, ddcbBitWise}, {0xbe, ddcbBitWise}, {0xc6, ddcbBitWise}, {0xce, ddcbBitWise}, {0xd6, ddcbBitWise}, {0xde, ddcbBitWise}, {0xe6, ddcbBitWise}, {0xee, ddcbBitWise}, {0xf6, ddcbBitWise}, {0xfe, ddcbBitWise}, // Terminator {0xffffffff, NULL} }; void InvalidInstructionC(UINT32 dwCount) { fprintf(fp, " InvalidInstruction(%ld);\n", dwCount); } UINT32 Timing(UINT8 bWho, UINT32 dwOpcode) { UINT32 dwTiming = 0; assert(dwOpcode < 0x100); if (TIMING_REGULAR == bWho) // Regular? dwTiming = bTimingRegular[dwOpcode]; else if (TIMING_CB == bWho) dwTiming = bTimingCB[dwOpcode]; else if (TIMING_DDFD == bWho) dwTiming = bTimingDDFD[dwOpcode]; else if (TIMING_ED == bWho) dwTiming = bTimingED[dwOpcode]; else if (TIMING_XXCB == bWho) dwTiming = bTimingXXCB[dwOpcode]; else if (TIMING_EXCEPT == bWho) dwTiming = dwOpcode; else assert(0); if (0 == dwTiming) { fprintf(stderr, "Opcode: %.2x:%.2x - Not zero!\n", bWho, dwOpcode); fclose(fp); exit(1); } return(dwTiming); } void IndexedOffset(UINT8 *Localmz80Index) { fprintf(fp, " mov dl, [esi] ; Fetch our offset\n"); fprintf(fp, " inc esi ; Move past the offset\n"); fprintf(fp, " or dl, dl ; Is this bad boy signed?\n"); fprintf(fp, " jns notSigned%ld ; Nope!\n", dwGlobalLabel); fprintf(fp, " dec dh ; Make it FFable\n"); fprintf(fp, "notSigned%ld:\n", dwGlobalLabel); fprintf(fp, " add dx, [_z80%s] ; Our offset!\n", Localmz80Index); ++dwGlobalLabel; } void CBHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all CBxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixCB+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " CBHandler();\n"); } else { assert(0); } } void EDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all EDxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixED+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " EDHandler();\n"); } else { assert(0); } } void DDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all DDxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixDD+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " DDHandler();\n"); } else { assert(0); } } void FDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all FDxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixFD+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " FDHandler();\n"); } else { assert(0); } } StandardHeader() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp,"; For assembly by NASM only\n"); fprintf(fp,"bits 32\n\n"); fprintf(fp,"; Theory of operation\n\n"); fprintf(fp,"; EDI=General purpose\n"); fprintf(fp,"; ESI=Program counter + base address\n"); fprintf(fp,"; EBP=z80Base\n"); fprintf(fp,"; AX=AF\n"); fprintf(fp,"; BX=HL\n"); fprintf(fp,"; CX=BC\n"); fprintf(fp,"; DX=General purpose\n\n"); if (bUseStack) fprintf(fp, "; Using stack calling conventions\n"); else fprintf(fp, "; Using register calling conventions\n"); if (b16BitIo) fprintf(fp, "; Extended input/output instructions treat (BC) as I/O address\n"); else fprintf(fp, "; Extended input/output instructions treat (C) as I/O address\n\n"); fprintf(fp, "IFF1 equ 01h\n"); fprintf(fp, "IFF2 equ 02h\n"); fprintf(fp, "CPUREG_PC equ 00h\n"); fprintf(fp, "CPUREG_SP equ 01h\n"); fprintf(fp, "CPUREG_AF equ 02h\n"); fprintf(fp, "CPUREG_BC equ 03h\n"); fprintf(fp, "CPUREG_DE equ 04h\n"); fprintf(fp, "CPUREG_HL equ 05h\n"); fprintf(fp, "CPUREG_AFPRIME equ 06h\n"); fprintf(fp, "CPUREG_BCPRIME equ 07h\n"); fprintf(fp, "CPUREG_DEPRIME equ 08h\n"); fprintf(fp, "CPUREG_HLPRIME equ 09h\n"); fprintf(fp, "CPUREG_IX equ 0ah\n"); fprintf(fp, "CPUREG_IY equ 0bh\n"); fprintf(fp, "CPUREG_I equ 0ch\n"); fprintf(fp, "CPUREG_A equ 0dh\n"); fprintf(fp, "CPUREG_F equ 0eh\n"); fprintf(fp, "CPUREG_B equ 0fh\n"); fprintf(fp, "CPUREG_C equ 10h\n"); fprintf(fp, "CPUREG_D equ 11h\n"); fprintf(fp, "CPUREG_E equ 12h\n"); fprintf(fp, "CPUREG_H equ 13h\n"); fprintf(fp, "CPUREG_L equ 14h\n"); fprintf(fp, "CPUREG_IFF1 equ 15h\n"); fprintf(fp, "CPUREG_IFF2 equ 16h\n"); fprintf(fp, "CPUREG_CARRY equ 17h\n"); fprintf(fp, "CPUREG_NEGATIVE equ 18h\n"); fprintf(fp, "CPUREG_PARITY equ 19h\n"); fprintf(fp, "CPUREG_OVERFLOW equ 1ah\n"); fprintf(fp, "CPUREG_HALFCARRY equ 1bh\n"); fprintf(fp, "CPUREG_ZERO equ 1ch\n"); fprintf(fp, "CPUREG_SIGN equ 1dh\n"); fprintf(fp, "CPUREG_MAXINDEX equ 1eh\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Multi-Z80 32 Bit emulator */\n"); fprintf(fp, "\n"); fprintf(fp, "/* Copyright 1996-2000 Neil Bradley, All rights reserved\n"); fprintf(fp, " *\n"); fprintf(fp, " * License agreement:\n"); fprintf(fp, " *\n"); fprintf(fp, " * (MZ80 Refers to both the assembly code emitted by makeZ80.c and makeZ80.c\n"); fprintf(fp, " * itself)\n"); fprintf(fp, " *\n"); fprintf(fp, " * MZ80 May be distributed in unmodified form to any medium.\n"); fprintf(fp, " *\n"); fprintf(fp, " * MZ80 May not be sold, or sold as a part of a commercial package without\n"); fprintf(fp, " * the express written permission of Neil Bradley (neil@synthcom.com). This\n"); fprintf(fp, " * includes shareware.\n"); fprintf(fp, " *\n"); fprintf(fp, " * Modified versions of MZ80 may not be publicly redistributed without author\n"); fprintf(fp, " * approval (neil@synthcom.com). This includes distributing via a publicly\n"); fprintf(fp, " * accessible LAN. You may make your own source modifications and distribute\n"); fprintf(fp, " * MZ80 in source or object form, but if you make modifications to MZ80\n"); fprintf(fp, " * then it should be noted in the top as a comment in makeZ80.c.\n"); fprintf(fp, " *\n"); fprintf(fp, " * MZ80 Licensing for commercial applications is available. Please email\n"); fprintf(fp, " * neil@synthcom.com for details.\n"); fprintf(fp, " *\n"); fprintf(fp, " * Synthcom Systems, Inc, and Neil Bradley will not be held responsible for\n"); fprintf(fp, " * any damage done by the use of MZ80. It is purely \"as-is\".\n"); fprintf(fp, " *\n"); fprintf(fp, " * If you use MZ80 in a freeware application, credit in the following text:\n"); fprintf(fp, " *\n"); fprintf(fp, " * \"Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)\"\n"); fprintf(fp, " *\n"); fprintf(fp, " * must accompany the freeware application within the application itself or\n"); fprintf(fp, " * in the documentation.\n"); fprintf(fp, " *\n"); fprintf(fp, " * Legal stuff aside:\n"); fprintf(fp, " *\n"); fprintf(fp, " * If you find problems with MZ80, please email the author so they can get\n"); fprintf(fp, " * resolved. If you find a bug and fix it, please also email the author so\n"); fprintf(fp, " * that those bug fixes can be propogated to the installed base of MZ80\n"); fprintf(fp, " * users. If you find performance improvements or problems with MZ80, please\n"); fprintf(fp, " * email the author with your changes/suggestions and they will be rolled in\n"); fprintf(fp, " * with subsequent releases of MZ80.\n"); fprintf(fp, " *\n"); fprintf(fp, " * The whole idea of this emulator is to have the fastest available 32 bit\n"); fprintf(fp, " * Multi-Z80 emulator for the PC, giving maximum performance. \n"); fprintf(fp, " */\n\n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \"mz80.h\"\n"); // HACK HACK fprintf(fp, "UINT32 z80intAddr;\n"); fprintf(fp, "UINT32 z80pc;\n"); } else { // Whoops. Unknown emission type. assert(0); } fprintf(fp, "\n\n"); } Alignment() { fprintf(fp, "\ntimes ($$-$) & 3 nop ; pad with NOPs to 4-byte boundary\n\n"); } void ProcBegin(UINT32 dwOpcode) { Alignment(); fprintf(fp, "%s:\n", procname); } void SetSubFlagsSZHVC(UINT8 *pszLeft, UINT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbSubSbcTable[((UINT32) %s << 8) | %s];\n", pszLeft, pszRight); } void SetSbcFlagsSZHVC(UINT8 *pszLeft, UINT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbSubSbcTable[((UINT32) %s << 8) | %s | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)];\n", pszLeft, pszRight); } void SetAddFlagsSZHVC(UINT8 *pszLeft, UINT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbAddAdcTable[((UINT32) %s << 8) | %s];\n", pszLeft, pszRight); } void SetAdcFlagsSZHVC(UINT8 *pszLeft, UINT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbAddAdcTable[((UINT32) %s << 8) | %s | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)];\n", pszLeft, pszRight); } UINT32 dwOverflowCount = 0; SetOverflow() { fprintf(fp, " seto dl\n"); fprintf(fp, " and ah, 0fbh ; Knock out parity/overflow\n"); fprintf(fp, " shl dl, 2\n"); fprintf(fp, " or ah, dl\n"); } void FetchNextInstruction(UINT32 dwOpcode) { if (0xffffffff != dwOpcode) { fprintf(fp, " sub edi, byte %ld\n", Timing(bCurrentMode, dwOpcode)); if (bCurrentMode == TIMING_REGULAR) fprintf(fp, " js near noMoreExec\n"); else fprintf(fp, " js near noMoreExec\n"); } fprintf(fp, " mov dl, byte [esi] ; Get our next instruction\n"); fprintf(fp, " inc esi ; Increment PC\n"); fprintf(fp, " jmp dword [z80regular+edx*4]\n\n"); } void WriteValueToMemory(UINT8 *pszAddress, UINT8 *pszValue) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov [_z80af], ax ; Store AF\n"); // First off, load our byte to write into al after we've saved AF if (strcmp(pszValue, "al") != 0) fprintf(fp, " mov al, %s ; And our data to write\n", pszValue); if (strcmp(pszValue, "[esi]") == 0) // Immediate value? fprintf(fp, " inc esi ; Increment our program counter\n"); // Now get the address in DX - regardless of what it is if (strcmp(pszAddress, "[_z80de]") == 0 || strcmp(pszAddress, "[_orgval]") == 0 || strcmp(pszAddress, "[_z80ix]") == 0 || strcmp(pszAddress, "[_z80iy]") == 0) fprintf(fp, " mov dx, %s\n", pszAddress); fprintf(fp, " mov edi, [_z80MemWrite] ; Point to the write array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je memoryWrite%ld ; Yes - go write it!\n", dwGlobalLabel); if (strcmp(pszAddress, "[_z80de]") == 0 || strcmp(pszAddress, "[_orgval]") == 0 || strcmp(pszAddress, "[_z80ix]") == 0 || strcmp(pszAddress, "[_z80iy]") == 0) fprintf(fp, " cmp dx, [edi] ; Are we smaller?\n", pszAddress); else fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%ld ; Yes... go to the next addr\n", dwGlobalLabel); if (strcmp(pszAddress, "[_z80de]") == 0 || strcmp(pszAddress, "[_orgval]") == 0 || strcmp(pszAddress, "[_z80ix]") == 0 || strcmp(pszAddress, "[_z80iy]") == 0) fprintf(fp, " cmp dx, [edi+4] ; Are we smaller?\n", pszAddress); else fprintf(fp, " cmp %s, [edi+4] ; Are we smaller?\n", pszAddress); fprintf(fp, " jbe callRoutine%ld ; If not, go call it!\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); // Save off our registers! if ((strcmp(pszAddress, "dx") != 0) && (strcmp(pszAddress, "[_z80de]") != 0) && (strcmp(pszAddress, "[_z80ix]") != 0) && (strcmp(pszAddress, "[_orgval]") != 0) && (strcmp(pszAddress, "[_z80iy]") != 0)) fprintf(fp, " mov dx, %s ; Get our address to target\n", pszAddress); fprintf(fp, " call WriteMemoryByte ; Go write the data!\n"); fprintf(fp, " jmp short WriteMacroExit%ld\n", dwGlobalLabel); fprintf(fp, "memoryWrite%ld:\n", dwGlobalLabel); if (strcmp(pszValue, "[esi]") == 0) fprintf(fp, " mov [ebp + e%s], al ; Store our direct value\n", pszAddress); else { if (pszValue[0] == 'b' && pszValue[1] == 'y' && pszValue[2] == 't') { fprintf(fp, " mov edi, edx\n"); assert(strcmp(pszValue, "dl") != 0); fprintf(fp, " mov dl, %s\n", pszValue); if (strcmp(pszAddress, "dx") == 0) fprintf(fp, " mov [ebp + edi], dl\n"); else fprintf(fp, " mov [ebp + e%s], dl\n", pszAddress); fprintf(fp, " mov edx, edi\n"); } else { if (strcmp(pszAddress, "[_z80de]") != 0 && strcmp(pszAddress, "[_orgval]") != 0 && strcmp(pszAddress, "[_z80ix]") != 0 && strcmp(pszAddress, "[_z80iy]") != 0) fprintf(fp, " mov [ebp + e%s], %s\n", pszAddress, pszValue); else fprintf(fp, " mov [ebp + edx], al\n"); } } fprintf(fp, " mov ax, [_z80af] ; Get our accumulator and flags\n"); fprintf(fp, "WriteMacroExit%ld:\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); ++dwGlobalLabel; } else if (MZ80_C == bWhat) { fprintf(fp, " psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemWrite->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemWrite->lowAddr) && (%s <= psMemWrite->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " if (psMemWrite->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " psMemWrite->memoryCall(%s, %s, psMemWrite);\n", pszAddress, pszValue); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " *((UINT8 *) psMemWrite->pUserArea + (%s - psMemWrite->lowAddr)) = %s;\n", pszAddress, pszValue); fprintf(fp, " }\n"); fprintf(fp, " psMemWrite = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemWrite;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemWrite)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80Base[%s] = (UINT8) %s;\n", pszAddress, pszValue); fprintf(fp, " }\n\n"); } } void WriteWordToMemory(UINT8 *pszAddress, UINT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80MemWrite] ; Point to the write array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je memoryWrite%ld\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%ld ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%ld\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); fprintf(fp, " push ax ; Save this for later\n"); // Write the LSB fprintf(fp, " push dx\n"); if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " mov ax, %s\n", pszTarget); } else { fprintf(fp, " xchg ah, al\n"); } fprintf(fp, " call WriteMemoryByte\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " pop ax\n"); fprintf(fp, " inc dx\n\n"); fprintf(fp, " push ax\n"); fprintf(fp, " push dx\n"); if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " mov ax, %s\n", pszTarget); fprintf(fp, " xchg ah, al\n"); } fprintf(fp, " call WriteMemoryByte\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " pop ax ; Restore us!\n"); fprintf(fp, " jmp writeExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryWrite%ld:\n", dwGlobalLabel); if (strlen(pszTarget) != 2) { fprintf(fp, " mov di, %s\n", pszTarget); fprintf(fp, " mov [ebp + e%s], di ; Store our word\n", pszAddress); } else { if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " mov [ebp + e%s], %s ; Store our word\n", pszAddress, pszTarget); } else { fprintf(fp, " xchg ah, al ; Swap for later\n"); fprintf(fp, " mov [ebp + e%s], %s ; Store our word\n", pszAddress, pszTarget); fprintf(fp, " xchg ah, al ; Restore\n"); } } fprintf(fp, "writeExit%ld:\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); dwGlobalLabel++; } else if (MZ80_C == bWhat) { fprintf(fp, " psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemWrite->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemWrite->lowAddr) && (%s <= psMemWrite->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " if (psMemWrite->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " psMemWrite->memoryCall(%s, (%s & 0xff), psMemWrite);\n", pszAddress, pszTarget); fprintf(fp, " psMemWrite->memoryCall(%s + 1, (%s >> 8), psMemWrite);\n", pszAddress, pszTarget); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " *((UINT8 *) psMemWrite->pUserArea + (%s - psMemWrite->lowAddr)) = %s;\n", pszAddress, pszTarget); fprintf(fp, " *((UINT8 *) psMemWrite->pUserArea + (%s - psMemWrite->lowAddr) + 1) = %s >> 8;\n", pszAddress, pszTarget); fprintf(fp, " }\n"); fprintf(fp, " psMemWrite = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemWrite;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemWrite)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80Base[%s] = (UINT8) %s;\n", pszAddress, pszTarget); fprintf(fp, " cpu.z80Base[%s + 1] = (UINT8) ((UINT32) %s >> 8);\n", pszAddress, pszTarget); fprintf(fp, " }\n\n"); } else { assert(0); } } void WriteValueToIo(UINT8 *pszIoAddress, UINT8 *pszValue) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov [_z80af], ax ; Store AF\n"); if (strcmp(pszValue, "al") != 0) fprintf(fp, " mov al, %s ; And our data to write\n", pszValue); if (strcmp(pszValue, "[esi]") == 0) // Immediate value? fprintf(fp, " inc esi ; Increment our program counter\n"); fprintf(fp, " mov edi, [_z80IoWrite] ; Point to the I/O write array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je WriteMacroExit%ld ; Yes - ignore it!\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszIoAddress); fprintf(fp, " jb nextAddr%ld ; Yes... go to the next addr\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+2] ; Are we bigger?\n", pszIoAddress); fprintf(fp, " jbe callRoutine%ld ; If not, go call it!\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 0ch ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); // Save off our registers! if (strcmp(pszIoAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address to target\n", pszIoAddress); fprintf(fp, " call WriteIOByte ; Go write the data!\n"); fprintf(fp, "WriteMacroExit%ld:\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */\n"); fprintf(fp, " while (psIoWrite->lowIoAddr != 0xffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psIoWrite->lowIoAddr) && (%s <= psIoWrite->highIoAddr))\n", pszIoAddress, pszIoAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " psIoWrite->IOCall(%s, %s, psIoWrite);\n", pszIoAddress, pszValue); fprintf(fp, " psIoWrite = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psIoWrite;\n"); fprintf(fp, " }\n\n"); } else { assert(0); } ++dwGlobalLabel; } void ReadValueFromMemory(UINT8 *pszAddress, UINT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80MemRead] ; Point to the read array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je memoryRead%ld\n", dwGlobalLabel); fprintf(fp, " cmp e%s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%ld ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp e%s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%ld\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); if (strcmp(pszAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address\n", pszAddress); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); // Yes, these are intentionally reversed! if (strcmp(pszTarget, "al") == 0) fprintf(fp, " mov [_z80af], al ; Save our new accumulator\n"); else if (strcmp(pszTarget, "ah") == 0) fprintf(fp, " mov [_z80af + 1], al ; Save our new flags\n"); else fprintf(fp, " mov %s, al ; Put our returned value here\n", pszTarget); // And are properly restored HERE: fprintf(fp, " mov ax, [_z80af] ; Get our AF back\n"); // Restore registers here... fprintf(fp, " jmp short readExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryRead%ld:\n", dwGlobalLabel); if (pszTarget[0] == 'b' && pszTarget[1] == 'y' && pszTarget[2] == 't') { fprintf(fp, " mov di, dx\n"); fprintf(fp, " mov dl, [ebp + e%s]\n", pszAddress); fprintf(fp, " mov %s, dl\n", pszTarget); fprintf(fp, " mov dx, di\n"); } else fprintf(fp, " mov %s, [ebp + e%s] ; Get our data\n\n", pszTarget, pszAddress); fprintf(fp, "readExit%ld:\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); dwGlobalLabel++; } else if (MZ80_C == bWhat) { fprintf(fp, " psMemRead = cpu.z80MemRead; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemRead->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemRead->lowAddr) && (%s <= psMemRead->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " if (psMemRead->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = psMemRead->memoryCall(%s, psMemRead);\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = *((UINT8 *) psMemRead->pUserArea + (%s - psMemRead->lowAddr));\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " psMemRead = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemRead;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemRead)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = cpu.z80Base[%s];\n", pszTarget, pszAddress); fprintf(fp, " }\n\n"); } else { assert(0); } } void ReadWordFromMemory(UINT8 *pszAddress, UINT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80MemRead] ; Point to the read array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je memoryRead%ld\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%ld ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%ld\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); if (strcmp(pszAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address\n", pszAddress); if (strcmp(pszTarget, "ax") != 0) fprintf(fp, " push ax ; Save this for later\n"); fprintf(fp, " push dx ; Save address\n"); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); fprintf(fp, " pop dx ; Restore our address\n"); fprintf(fp, " inc dx ; Next byte, please\n"); fprintf(fp, " push ax ; Save returned byte\n"); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); fprintf(fp, " xchg ah, al ; Swap for endian's sake\n"); fprintf(fp, " pop dx ; Restore LSB\n"); fprintf(fp, " mov dh, ah ; Our word is now in DX\n"); // DX Now has our data and our address is toast if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " pop ax ; Restore this\n"); if (strcmp(pszTarget, "dx") != 0) { fprintf(fp, " mov %s, dx ; Store our word\n", pszTarget); } } else fprintf(fp, " mov ax, dx\n"); if (strcmp(pszTarget, "ax") == 0) { fprintf(fp, " xchg ah, al\n"); } fprintf(fp, " jmp readExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryRead%ld:\n", dwGlobalLabel); if (strlen(pszTarget) == 2) { fprintf(fp, " mov %s, [ebp + e%s]\n", pszTarget, pszAddress); if (strcmp(pszTarget, "ax") == 0) { fprintf(fp, " xchg ah, al\n"); } } else { fprintf(fp, " mov dx, [ebp + e%s]\n", pszAddress); fprintf(fp, " mov %s, dx\n", pszTarget); } fprintf(fp, "readExit%ld:\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " psMemRead = cpu.z80MemRead; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemRead->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemRead->lowAddr) && (%s <= psMemRead->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " if (psMemRead->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = psMemRead->memoryCall(%s, psMemRead);\n", pszTarget, pszAddress); fprintf(fp, " %s |= (UINT32) ((UINT32) psMemRead->memoryCall(%s + 1, psMemRead) << 8);\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = *((UINT8 *) psMemRead->pUserArea + (%s - psMemRead->lowAddr));\n", pszTarget, pszAddress); fprintf(fp, " %s |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (%s - psMemRead->lowAddr + 1)) << 8);\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " psMemRead = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemRead;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemRead)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = cpu.z80Base[%s];\n", pszTarget, pszAddress); fprintf(fp, " %s |= (UINT32) ((UINT32) cpu.z80Base[%s + 1] << 8);\n", pszTarget, pszAddress); fprintf(fp, " }\n\n"); } else { assert(0); } dwGlobalLabel++; } void ReadValueFromIo(UINT8 *pszIoAddress, UINT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80IoRead] ; Point to the read array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je ioRead%ld\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszIoAddress); fprintf(fp, " jb nextAddr%ld ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+2] ; Are we bigger?\n", pszIoAddress); fprintf(fp, " jbe callRoutine%ld\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 0ch ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); if (strcmp(pszIoAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address\n", pszIoAddress); fprintf(fp, " call ReadIOByte ; Standard read routine\n"); // Yes, these are intentionally reversed! if (strcmp(pszTarget, "al") == 0) fprintf(fp, " mov [_z80af], al ; Save our new accumulator\n"); else if (strcmp(pszTarget, "ah") == 0) fprintf(fp, " mov [_z80af + 1], ah ; Save our new flags\n"); else if (strcmp(pszTarget, "dl") == 0) fprintf(fp, " mov [_z80de], al ; Put it in E\n"); else if (strcmp(pszTarget, "dh") == 0) fprintf(fp, " mov [_z80de + 1], al ; Put it in D\n"); else if (strcmp(pszTarget, "*dl") == 0) fprintf(fp, " mov dl, al ; Put it in DL for later consumption\n"); else fprintf(fp, " mov %s, al ; Put our returned value here\n", pszTarget); // And are properly restored HERE: fprintf(fp, " mov ax, [_z80af] ; Get our AF back\n"); // Restore registers here... fprintf(fp, " jmp short readExit%ld\n\n", dwGlobalLabel); fprintf(fp, "ioRead%ld:\n", dwGlobalLabel); if (strcmp(pszTarget, "*dl") == 0) fprintf(fp, " mov dl, 0ffh ; An unreferenced read\n"); else fprintf(fp, " mov %s, 0ffh ; An unreferenced read\n", pszTarget); fprintf(fp, "readExit%ld:\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " psIoRead = cpu.z80IoRead; /* Beginning of our handler */\n"); fprintf(fp, " while (psIoRead->lowIoAddr != 0xffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psIoRead->lowIoAddr) && (%s <= psIoRead->highIoAddr))\n", pszIoAddress, pszIoAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " %s = psIoRead->IOCall(%s, psIoRead);\n", pszTarget, pszIoAddress); fprintf(fp, " psIoRead = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psIoRead;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psIoRead)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = 0xff; /* Unclaimed I/O read */\n", pszTarget); fprintf(fp, " }\n\n"); } else { assert(0); } dwGlobalLabel++; } // Basic instruction set area void MiscHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0xe3) { if (bThroughCallHandler) { fprintf(fp, " call PopWord\n"); fprintf(fp, " xchg bx, [_wordval]\n"); fprintf(fp, " call PushWord\n"); } else { fprintf(fp, " mov dx, word [_z80sp]\n"); fprintf(fp, " xchg bx, [ebp+edx]\n"); fprintf(fp, " xor edx, edx\n"); } } if (dwOpcode == 0x2a) { fprintf(fp, " mov dx, [esi] ; Get address to load\n"); fprintf(fp, " add esi, 2 ; Skip over it so we don't execute it\n"); ReadWordFromMemory("dx", "bx"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode == 0xfb) { fprintf(fp, " or dword [_z80iff], IFF1 ; Indicate interrupts are enabled now\n"); fprintf(fp, " sub edi, 4 ; Takes 4 cycles!\n"); fprintf(fp, " mov [dwEITiming], edi ; Snapshot our current timing\n"); fprintf(fp, " mov [bEIExit], byte 1 ; Indicate we're exiting because of an EI\n"); fprintf(fp, " xor edi, edi ; Force next instruction to exit\n"); fprintf(fp, " mov dl, byte [esi] ; Get our next instruction\n"); fprintf(fp, " inc esi ; Next PC\n"); fprintf(fp, " jmp dword [z80regular+edx*4]\n\n"); } if (dwOpcode == 0xf9) fprintf(fp, " mov word [_z80sp], bx\n"); if (dwOpcode == 0xd9) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, [_z80de]\n"); fprintf(fp, " xchg cx, [_z80bcprime]\n"); fprintf(fp, " xchg di, [_z80deprime]\n"); fprintf(fp, " xchg bx, [_z80hlprime]\n"); fprintf(fp, " mov [_z80de], di\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } if (dwOpcode == 0x76) { fprintf(fp, " mov dword [_z80halted], 1 ; We've halted the chip!\n"); if (FALSE == bNoTiming) { fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); } fprintf(fp, " jmp noMoreExec\n"); return; } if (dwOpcode == 0x3f) { fprintf(fp, " mov dl, ah\n"); fprintf(fp, " and dl, 01h\n"); fprintf(fp, " shl dl, 4\n"); fprintf(fp, " xor ah, 01h\n"); fprintf(fp, " and ah, 0edh\n"); fprintf(fp, " or ah, dl\n"); } if (dwOpcode == 0x37) { fprintf(fp, " or ah, 1\n"); fprintf(fp, " and ah,0edh\n"); } if (dwOpcode == 0x27) { fprintf(fp, " mov dh, ah\n"); fprintf(fp, " and dh, 02ah\n"); fprintf(fp, " test ah, 02h ; Were we doing a subtraction?\n"); fprintf(fp, " jnz handleNeg ; Nope!\n"); fprintf(fp, " sahf\n"); fprintf(fp, " daa\n"); fprintf(fp, " lahf\n"); fprintf(fp, " jmp short endDaa\n"); fprintf(fp, "handleNeg:\n"); fprintf(fp, " sahf\n"); fprintf(fp, " das\n"); fprintf(fp, " lahf\n"); fprintf(fp, "endDaa:\n"); fprintf(fp, " and ah, 0d5h\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode == 0x08) { fprintf(fp, " xchg ah, al\n"); fprintf(fp, " xchg ax, [_z80afprime]\n"); fprintf(fp, " xchg ah, al\n"); } if (dwOpcode == 0x07) { fprintf(fp, " sahf\n"); fprintf(fp, " rol al, 1\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0edh\n"); } if (dwOpcode == 0x0f) { fprintf(fp, " sahf\n"); fprintf(fp, " ror al, 1\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0edh\n"); } if (dwOpcode == 0xe9) { fprintf(fp, " mov si, bx\n"); fprintf(fp, " and esi, 0ffffh\n"); fprintf(fp, " add esi, ebp\n"); } if (dwOpcode == 0xeb) fprintf(fp, " xchg [_z80de], bx ; Exchange DE & HL\n"); if (dwOpcode == 0x2f) { fprintf(fp, " not al\n"); fprintf(fp, " or ah, 012h ; N And H are now on!\n"); } if (dwOpcode == 0x10) // DJNZ { fprintf(fp, " mov dl, [esi] ; Get our relative offset\n"); fprintf(fp, " inc esi ; Next instruction, please!\n"); fprintf(fp, " dec ch ; Decrement B\n"); fprintf(fp, " jz noJump ; Don't take the jump if it's done!\n"); fprintf(fp, "; Otherwise, take the jump\n"); fprintf(fp, " sub edi, 5\n"); fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " cbw\n"); fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " add si, dx\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, "noJump:\n"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode == 0x3a) // LD A,(xxxx) { fprintf(fp, " mov dx, [esi] ; Get our address\n"); fprintf(fp, " add esi, 2 ; Skip past the address\n"); ReadValueFromMemory("dx", "al"); fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); } if (dwOpcode == 0xf3) // DI { fprintf(fp, " and dword [_z80iff], (~IFF1) ; Not in an interrupt\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode == 0x76) // HALT! { fprintf(fp, " cpu.z80halted = 1;\n"); fprintf(fp, " dwElapsedTicks += sdwCyclesRemaining;\n"); fprintf(fp, " sdwCyclesRemaining = 0;\n"); } else if (dwOpcode == 0x2f) // CPL { fprintf(fp, " cpu.z80A ^= 0xff;\n"); fprintf(fp, " cpu.z80F |= (Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); } else if (dwOpcode == 0xd9) // EXX { fprintf(fp, " dwTemp = cpu.z80DE;\n"); fprintf(fp, " cpu.z80DE = cpu.z80deprime;\n"); fprintf(fp, " cpu.z80deprime = dwTemp;\n"); fprintf(fp, " dwTemp = cpu.z80BC;\n"); fprintf(fp, " cpu.z80BC = cpu.z80bcprime;\n"); fprintf(fp, " cpu.z80bcprime = dwTemp;\n"); fprintf(fp, " dwTemp = cpu.z80HL;\n"); fprintf(fp, " cpu.z80HL = cpu.z80hlprime;\n"); fprintf(fp, " cpu.z80hlprime = dwTemp;\n"); } else if (dwOpcode == 0xf9) // LD SP, HL { fprintf(fp, " cpu.z80sp = cpu.z80HL;\n"); } else if (dwOpcode == 0x27) // DAA { fprintf(fp, " dwAddr = (((cpu.z80F & Z80_FLAG_CARRY) | \n"); fprintf(fp, " ((cpu.z80F & Z80_FLAG_HALF_CARRY) >> 3) | \n"); fprintf(fp, " ((cpu.z80F & Z80_FLAG_NEGATIVE) << 1)) << 8) | cpu.z80A;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= (wDAATable[dwAddr] >> 8);\n"); fprintf(fp, " cpu.z80A = wDAATable[dwAddr] & 0xff;\n"); } else if (dwOpcode == 0x2a) { fprintf(fp, " dwAddr = *pbPC++;\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8);\n"); ReadWordFromMemory("dwAddr", "cpu.z80HL"); } else if (dwOpcode == 0xe3) // EX (SP), HL { ReadWordFromMemory("cpu.z80sp", "dwAddr"); WriteWordToMemory("cpu.z80sp", "cpu.z80HL"); fprintf(fp, " cpu.z80HL = dwAddr;\n"); } else if (dwOpcode == 0xe9) // JP (HL) { fprintf(fp, " pbPC = cpu.z80Base + cpu.z80HL;\n"); } else if (0x08 == dwOpcode) // EX AF, AF' { fprintf(fp, " dwAddr = (UINT32) cpu.z80AF;\n"); fprintf(fp, " cpu.z80AF = cpu.z80afprime;\n"); fprintf(fp, " cpu.z80afprime = dwAddr;\n"); } else if (0xeb == dwOpcode) // EX DE, HL { fprintf(fp, " dwAddr = cpu.z80DE;\n"); fprintf(fp, " cpu.z80DE = cpu.z80HL;\n"); fprintf(fp, " cpu.z80HL = dwAddr;\n"); } else if (0x10 == dwOpcode) // DJNZ { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " if (--cpu.z80B)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks += 5; /* 5 More for jump taken */\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff;\n"); fprintf(fp, " pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else if (0x37 == dwOpcode) // SCF { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_CARRY;\n"); } else if (0x3f == dwOpcode) // CCF { fprintf(fp, " bTemp = (cpu.z80F & Z80_FLAG_CARRY) << 4;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F ^= Z80_FLAG_CARRY;\n"); } else if (0x07 == dwOpcode) // RLCA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " cpu.z80F |= (cpu.z80A >> 7);\n"); fprintf(fp, " cpu.z80A = (cpu.z80A << 1) | (cpu.z80A >> 7);\n"); } else if (0x0f == dwOpcode) // RRCA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80A = (cpu.z80A >> 1) | (cpu.z80A << 7);\n"); } else if (0x3a == dwOpcode) // LD A, (xxxxh) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= (((UINT32) *pbPC++) << 8);\n"); ReadValueFromMemory("dwTemp", "cpu.z80A"); } else if (0xf3 == dwOpcode) // DI { fprintf(fp, " cpu.z80iff &= (~IFF1);\n"); } else if (0xfb == dwOpcode) // EI { fprintf(fp, " cpu.z80iff |= IFF1;\n"); } else if (0x00 == dwOpcode) // NOP { fprintf(fp, " /* Intentionally not doing anything - NOP! */\n"); } else { InvalidInstructionC(1); } } else { assert(0); } } void LdRegPairImmediate(UINT32 dwOpcode) { UINT8 bOp = 0; bOp = (dwOpcode >> 4) & 0x3; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bOp == 0) fprintf(fp, " mov cx, [esi] ; Get our immediate value of BC\n"); else if (bOp == 2) fprintf(fp, " mov bx, [esi] ; Get our immediate value of HL\n"); else if (bOp == 1) { fprintf(fp, " mov dx, [esi] ; Get our immediate value of DE\n"); fprintf(fp, " mov word [_z80de], dx ; Store DE\n"); fprintf(fp, " xor edx, edx\n"); } else if (bOp == 3) { fprintf(fp, " mov dx, [esi] ; Get our immediate value of SP\n"); fprintf(fp, " mov word [_z80sp], dx ; Store it!\n"); fprintf(fp, " xor edx, edx\n"); } fprintf(fp, " add esi, 2\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " %s = *pbPC++; /* LSB First */\n", pbRegPairC[bOp]); fprintf(fp, " %s |= (((UINT32) *pbPC++ << 8)); /* Now the MSB */\n", pbRegPairC[bOp]); } else { assert(0); } } void LdRegpairPtrByte(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x36) // Immediate into (HL) WriteValueToMemory("bx", "[esi]"); if (dwOpcode == 0x12) WriteValueToMemory("[_z80de]", "al"); // (DE), A if (dwOpcode == 0x2) // (BC), A WriteValueToMemory("cx", "al"); if (dwOpcode >= 0x70 && dwOpcode < 0x78) WriteValueToMemory("bx", pbMathReg[dwOpcode & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode == 0x36) WriteValueToMemory("cpu.z80HL", "*pbPC++"); if (dwOpcode == 0x12) WriteValueToMemory("cpu.z80DE", "cpu.z80A"); if (dwOpcode == 0x02) WriteValueToMemory("cpu.z80BC", "cpu.z80A"); if (dwOpcode >= 0x70 && dwOpcode < 0x78) WriteValueToMemory("cpu.z80HL", pbMathRegC[dwOpcode & 0x07]); } else { assert(0); } } void MathOperation(UINT32 dwOrgOpcode) { UINT8 bRegister; UINT32 dwOpcode; UINT8 tempstr[150]; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOrgOpcode); dwOpcode = dwOrgOpcode; bRegister = dwOpcode & 0x07; dwOpcode &= 0xf8; if (dwOpcode == 0x80) strcpy(tempstr, "add"); if (dwOpcode == 0x88) strcpy(tempstr, "adc"); if (dwOpcode == 0x90) strcpy(tempstr, "sub"); if (dwOpcode == 0x98) strcpy(tempstr, "sbb"); if (dwOpcode == 0xa0) strcpy(tempstr, "and"); if (dwOpcode == 0xa8) strcpy(tempstr, "xor"); if (dwOpcode == 0xb0) strcpy(tempstr, "or"); if (dwOpcode == 0xb8) strcpy(tempstr, "cmp"); // Let's see if we have to deal with (HL) or #xxh if (bRegister == 0x6) { // We have to deal with (HL) ReadValueFromMemory("bx", "dl"); } if (bRegister != 0x06 && bRegister < 0xff) { fprintf(fp, " sahf\n"); fprintf(fp, " %s al, %s\n", tempstr, pbMathReg[bRegister]); fprintf(fp, " lahf\n"); } else // If it's (HL).... { fprintf(fp, " sahf\n"); fprintf(fp, " %s al, dl\n", tempstr); fprintf(fp, " lahf\n"); } if (dwOpcode != 0xa8 && dwOpcode != 0xa0 && dwOpcode != 0xb0) SetOverflow(); if (dwOpcode == 0xa8) fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); if (dwOpcode == 0xa0) { fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); fprintf(fp, " or ah, 010h ; Half carry gets set\n"); } if (dwOpcode == 0xb0) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); if (dwOpcode == 0xb8) fprintf(fp, " or ah, 02h ; Set N for compare!\n"); if (dwOpcode == 0x80 || dwOpcode == 0x88) fprintf(fp, " and ah, 0fdh ; No N!\n"); if (dwOpcode == 0x90 || dwOpcode == 0x98) fprintf(fp, " or ah, 02h ; N Gets set!\n"); if (bRegister == 0x6) fprintf(fp, " xor edx, edx ; Zero this...\n"); FetchNextInstruction(dwOrgOpcode); } else if (MZ80_C == bWhat) { dwOpcode = dwOrgOpcode; bRegister = dwOpcode & 0x07; dwOpcode &= 0xf8; if (6 == bRegister) // Deal with (HL) { ReadValueFromMemory("cpu.z80HL", "bTemp"); } if (dwOpcode == 0xa0) { fprintf(fp, " cpu.z80A &= %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0xa8) { fprintf(fp, " cpu.z80A ^= %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0xb0) { fprintf(fp, " cpu.z80A |= %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0xb8) { // Don't do anything. We just do flags! } else if (dwOpcode == 0x88) // ADC { fprintf(fp, " bTemp2 = cpu.z80A + %s + (cpu.z80F & Z80_FLAG_CARRY);\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0x90) // SUB { fprintf(fp, " bTemp2 = cpu.z80A - %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0x80) // ADD { fprintf(fp, " bTemp2 = cpu.z80A + %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0x98) // SBC { fprintf(fp, " bTemp2 = cpu.z80A - %s - (cpu.z80F & Z80_FLAG_CARRY);\n", pbMathRegC[bRegister]); } else { InvalidInstructionC(1); } // Now do flag fixup if (0xb0 == dwOpcode || 0xa8 == dwOpcode) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } if (0xa0 == dwOpcode) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } if (0xb8 == dwOpcode || 0x90 == dwOpcode) { SetSubFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); if (0x90 == dwOpcode) { fprintf(fp, " cpu.z80A = bTemp2;\n"); } } if (0x80 == dwOpcode) // Add fixup { SetAddFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); fprintf(fp, " cpu.z80A = bTemp2;\n"); } if (0x88 == dwOpcode) // Adc fixup { SetAdcFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); fprintf(fp, " cpu.z80A = bTemp2;\n"); } if (0x98 == dwOpcode) // Sbc fixup { SetSbcFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); fprintf(fp, " cpu.z80A = bTemp2;\n"); } } else { assert(0); } } void RegIntoMemory(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address to write to\n"); fprintf(fp, " add esi, 2 ; Next address, please...\n"); if (0x32 == dwOpcode) // LD (xxxx), A WriteValueToMemory("dx", "al"); if (0x22 == dwOpcode) // LD (xxxx), HL { WriteWordToMemory("dx", "bx"); } fprintf(fp, " xor edx, edx ; Zero our upper byte\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= ((UINT32) *pbPC++ << 8);\n"); if (0x32 == dwOpcode) WriteValueToMemory("dwTemp", "cpu.z80A"); if (0x22 == dwOpcode) WriteWordToMemory("dwTemp", "cpu.z80HL"); return; } else { assert(0); } } void JpHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (0xc3 == dwOpcode) // If it's a straight jump... { fprintf(fp, " mov si, [esi] ; Get our new address\n"); fprintf(fp, " and esi, 0ffffh ; Only the lower 16 bits\n"); fprintf(fp, " add esi, ebp ; Our new address!\n"); } else // It's a conditional handler... { fprintf(fp, " sahf ; Restore our flags\n"); fprintf(fp, " j%s takeJump%ld ; We're going to take a jump\n", pbFlags[(dwOpcode >> 3) & 0x07], dwGlobalLabel); fprintf(fp, " add esi, 2 ; Skip past the address\n"); fprintf(fp, " jmp short nextInst%ld ; Go execute the next instruction\n", dwGlobalLabel); fprintf(fp, "takeJump%ld:\n", dwGlobalLabel); fprintf(fp, " mov si, [esi] ; Get our new offset\n"); fprintf(fp, " and esi, 0ffffh ; Only the lower WORD is valid\n"); fprintf(fp, " add esi, ebp ; Our new address!\n"); fprintf(fp, "nextInst%ld:\n", dwGlobalLabel); ++dwGlobalLabel; } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */\n"); if (0xc3 != dwOpcode) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x07]); fprintf(fp, " {\n"); fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else // Regular jump here { fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); } } else { assert(0); } } void LdRegImmediate(UINT32 dwOpcode) { UINT8 bOp; bOp = (dwOpcode >> 3) & 0x7; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bOp != 2 && bOp != 3) fprintf(fp, " mov %s, [esi] ; Get our immediate value\n", pbMathReg[bOp]); else { fprintf(fp, " mov dl, [esi] ; Get our immediate value\n"); fprintf(fp, " mov %s, dl ; Store our new value\n", pbMathReg[bOp]); } fprintf(fp, " inc esi\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " %s = *pbPC++; /* Get immediate byte into register */\n", pbMathRegC[bOp]); } else { assert(0); } } void IncRegister(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = (dwOpcode >> 3) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); fprintf(fp, " inc %s\n", pbMathReg[dwOpcode1]); fprintf(fp, " lahf\n"); SetOverflow(); fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp ," cpu.z80F |= bPostIncFlags[%s++];\n", pbMathRegC[dwOpcode1]); } else { assert(0); } } void DecRegister(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = (dwOpcode >> 3) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); fprintf(fp, " dec %s\n", pbMathReg[dwOpcode1]); fprintf(fp, " lahf\n"); SetOverflow(); fprintf(fp, " or ah, 02h ; Set negative!\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY);\n"); fprintf(fp ," cpu.z80F |= bPostDecFlags[%s--];\n", pbMathRegC[dwOpcode1]); } else { assert(0); } } void IncDecRegpair(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x0f) == 3) // Increment? fprintf(fp, " inc %s\n", pbRegPairs[(dwOpcode >> 4) & 0x03]); else fprintf(fp, " dec %s\n", pbRegPairs[(dwOpcode >> 4) & 0x03]); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if ((dwOpcode & 0x0f) == 3) // Increment fprintf(fp, " %s++;\n", pbRegPairC[(dwOpcode >> 4) & 0x03]); else fprintf(fp, " %s--;\n", pbRegPairC[(dwOpcode >> 4) & 0x03]); fprintf(fp, " %s &= 0xffff;\n", pbRegPairC[(dwOpcode >> 4) & 0x03]); } else { assert(0); } } void LdRegReg(UINT32 dwOpcode) { UINT8 bDestination; UINT8 bSource; bDestination = (dwOpcode >> 3) & 0x07; bSource = (dwOpcode) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bSource != bDestination) { if (bSource == 2 && bDestination == 3) { fprintf(fp, " mov dl, byte [_z80de + 1]\n"); fprintf(fp, " mov [_z80de], dl\n"); } else if (bSource == 3 && bDestination == 2) { fprintf(fp, " mov dl, byte [_z80de]\n"); fprintf(fp, " mov [_z80de + 1], dl\n"); } else fprintf(fp, " mov %s, %s\n", pbMathReg[bDestination], pbMathReg[bSource]); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (bDestination != bSource) { fprintf(fp, " %s = %s;\n", pbMathRegC[bDestination], pbMathRegC[bSource]); } } else { assert(0); } } void MathOperationDirect(UINT32 dwOpcode) { UINT8 tempstr[4]; if (MZ80_ASSEMBLY_X86 == bWhat) { if (dwOpcode == 0xc6) strcpy(tempstr, "add"); if (dwOpcode == 0xce) strcpy(tempstr, "adc"); if (dwOpcode == 0xd6) strcpy(tempstr, "sub"); if (dwOpcode == 0xde) strcpy(tempstr, "sbb"); if (dwOpcode == 0xe6) strcpy(tempstr, "and"); if (dwOpcode == 0xee) strcpy(tempstr, "xor"); if (dwOpcode == 0xf6) strcpy(tempstr, "or"); if (dwOpcode == 0xfe) strcpy(tempstr, "cmp"); ProcBegin(dwOpcode); // Let's see if we have to deal with (HL) or #xxh fprintf(fp, " sahf\n"); fprintf(fp, " %s al, [esi]\n", tempstr); fprintf(fp, " lahf\n"); if (dwOpcode != 0xee && dwOpcode != 0xe6 && dwOpcode != 0xf6) { SetOverflow(); } if (dwOpcode == 0xe6) { fprintf(fp, " and ah, 0ech ; Only parity, half carry, sign, zero\n"); fprintf(fp, " or ah, 10h ; Half carry\n"); } if (dwOpcode == 0xc6 || dwOpcode == 0xce) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); if (dwOpcode == 0xd6 || dwOpcode == 0xde || dwOpcode == 0xfe) fprintf(fp, " or ah, 02h ; Set negative!\n"); if (dwOpcode == 0xf6 || dwOpcode == 0xee) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); fprintf(fp, " inc esi\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xfe == dwOpcode) // Cp { SetSubFlagsSZHVC("cpu.z80A", "*pbPC++"); } else if (0xe6 == dwOpcode) // And { fprintf(fp, " cpu.z80A &= *pbPC++;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } else if (0xf6 == dwOpcode) // Or { fprintf(fp, " cpu.z80A |= *pbPC++;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xc6 == dwOpcode) // Add { fprintf(fp, " bTemp = *pbPC++;\n"); SetAddFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp;\n"); } else if (0xce == dwOpcode) // Adc { fprintf(fp, " bTemp = *pbPC++ + (cpu.z80F & Z80_FLAG_CARRY);\n"); SetAdcFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp;\n"); } else if (0xd6 == dwOpcode) // Sub { fprintf(fp, " bTemp = *pbPC++;\n"); SetSubFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A -= bTemp;\n"); } else if (0xde == dwOpcode) // Sbc { fprintf(fp, " bTemp = *pbPC++ + (cpu.z80F & Z80_FLAG_CARRY);\n"); SetSbcFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A = cpu.z80A - bTemp;\n"); } else if (0xee == dwOpcode) // Xor { fprintf(fp, " cpu.z80A ^= *pbPC++;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else InvalidInstructionC(1); } else { assert(0); } } // JR cc, addr void JrHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " and esi, 0ffffh\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, " mov dl, [esi] ; Get our relative offset\n"); fprintf(fp, " inc esi ; Next instruction, please!\n"); if (dwOpcode != 0x18) { fprintf(fp, " sahf\n"); fprintf(fp, " j%s takeJump%ld\n", pbFlags[(dwOpcode >> 3) & 0x3], dwGlobalLabel); fprintf(fp, " jmp short noJumpMan%ld\n", dwGlobalLabel); fprintf(fp, "takeJump%ld:\n", dwGlobalLabel); if (FALSE == bNoTiming) { fprintf(fp, " sub edi, 5\n"); } } else // It's a JR { fprintf(fp, " cmp dl, 0feh ; Jump to self?\n"); fprintf(fp, " je yesJrMan ; Yup! Bail out!\n"); } fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " cbw\n"); fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " add si, dx\n"); fprintf(fp, " and esi, 0ffffh ; Only the lower 16 bits\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, " xor dh, dh\n"); fprintf(fp, "noJumpMan%ld:\n", dwGlobalLabel++); FetchNextInstruction(dwOpcode); if (0x18 == dwOpcode) { fprintf(fp,"yesJrMan:\n"); fprintf(fp, " xor edx, edx ; Zero me for later\n"); fprintf(fp, " mov edi, edx\n"); fprintf(fp, " mov [cyclesRemaining], edx\n"); fprintf(fp, " sub esi, 2 ; Back to the instruction again\n"); fprintf(fp, " jmp noMoreExec\n\n"); } } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff;\n"); if (0x18 != dwOpcode) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x03]); } fprintf(fp, " {\n"); fprintf(fp, " sdwCyclesRemaining -= 5;\n"); fprintf(fp, " pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else { assert(0); } } void CallHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode != 0xcd) { fprintf(fp, " sahf ; Restore our flags\n"); fprintf(fp, " j%s takeJump%ld ; We're going call in this case\n", pbFlags[(dwOpcode >> 3) & 0x07], dwGlobalLabel); fprintf(fp, " add esi, 2 ; Skip past the address\n"); fprintf(fp, " jmp short noCallTaken%ld ; Go execute the next instruction\n", dwGlobalLabel); fprintf(fp, "takeJump%ld:\n", dwGlobalLabel); fprintf(fp, " sub edi, 7\n"); } if (bThroughCallHandler) { fprintf(fp, " mov dx, [esi] ; Get our call to address\n"); fprintf(fp, " mov [_z80pc], dx ; Store our new program counter\n"); fprintf(fp, " add esi, 2 ; Skip to our new address to be pushed\n"); fprintf(fp, " sub esi, ebp ; Value to push onto the \"stack\"\n"); fprintf(fp, " mov [_wordval], si ; Store our return address on the stack\n"); fprintf(fp, " mov si, dx ; Our new address\n"); fprintf(fp, " add esi, ebp ; And our base address\n"); fprintf(fp, " call PushWord ; Go push our orgval to the stack\n"); } else { fprintf(fp, " mov dx, [esi] ; Get our call to address\n"); fprintf(fp, " mov [_z80pc], dx ; Store our new program counter\n"); fprintf(fp, " add esi, 2 ; Skip to our new address to be pushed\n"); fprintf(fp, " sub esi, ebp ; Value to push onto the \"stack\"\n"); fprintf(fp, " mov dx, word [_z80sp] ; Get the current stack pointer\n"); fprintf(fp, " sub dx, 2 ; Back up two bytes\n"); fprintf(fp, " mov [ebp+edx], si ; PUSH It!\n"); fprintf(fp, " mov word [_z80sp], dx ; Store our new stack pointer\n"); fprintf(fp, " mov si, [_z80pc] ; Get our new program counter\n"); fprintf(fp, " add esi, ebp ; Naturalize it!\n"); } if (dwOpcode != 0xcd) fprintf(fp, "noCallTaken%ld:\n", dwGlobalLabel++); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */\n"); if (0xcd != dwOpcode) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x07]); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* MSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* LSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else // Just a regular call { fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); } } else { assert(0); } } void RetHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode != 0xc9) { fprintf(fp, " sahf\n"); fprintf(fp, " j%s takeReturn%ld\n", pbFlags[(dwOpcode >> 3) & 0x07], dwGlobalLabel); fprintf(fp, " jmp short retNotTaken%ld\n", dwGlobalLabel); fprintf(fp, "takeReturn%ld:\n", dwGlobalLabel); if (FALSE == bNoTiming) { fprintf(fp, " sub edi, byte 6\n"); } } if (bThroughCallHandler) { fprintf(fp, " call PopWord\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, dx\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, " xor edx, edx\n"); } else { fprintf(fp, " mov dx, word [_z80sp] ; Get our current stack pointer\n"); fprintf(fp, " mov si, [edx+ebp] ; Get our return address\n"); fprintf(fp, " and esi, 0ffffh ; Only within 64K!\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " add word [_z80sp], 02h ; Remove our two bytes from the stack\n"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode != 0xc9) fprintf(fp, "retNotTaken%ld:\n", dwGlobalLabel++); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode != 0xc9) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x07]); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks += 6;\n"); } fprintf(fp, " pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */\n"); fprintf(fp, " dwAddr = *pbSP++; /* Pop LSB */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */\n"); fprintf(fp, " cpu.z80sp += 2; /* Pop the word off */\n"); fprintf(fp, " pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */\n"); if (dwOpcode != 0xc9) { fprintf(fp, " }\n"); } } else { assert(0); } } void RestartHandler(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = dwOpcode & 0x38; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bThroughCallHandler) { fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " mov [_wordval], si ; Store our return address\n"); fprintf(fp, " call PushWord\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, %.4lxh\n", dwOpcode1); fprintf(fp, " add esi, ebp\n"); } else { fprintf(fp, " mov dx, word [_z80sp] ; Get our stack pointer\n"); fprintf(fp, " sub dx, 2 ; Make room for the new value!\n"); fprintf(fp, " mov word [_z80sp], dx ; Store our new stack pointer\n"); fprintf(fp, " sub esi, ebp ; Get our real PC\n"); fprintf(fp, " mov [ebp+edx], si ; Our return address\n"); fprintf(fp, " mov si, 0%.2xh ; Our new call address\n", dwOpcode1); fprintf(fp, " add esi, ebp ; Back to the base!\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " pbPC = cpu.z80Base + 0x%.2x; /* Normalize the address */\n", dwOpcode1); } else { assert(0); } } void ToRegFromHl(UINT32 dwOpcode) { UINT8 bReg; bReg = (dwOpcode >> 3) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bReg != 2 && bReg != 3) ReadValueFromMemory("bx", pbMathReg[bReg]); else { ReadValueFromMemory("bx", pbLocalReg[bReg]); fprintf(fp, " mov %s, %s\n", pbMathReg[bReg], pbLocalReg[bReg]); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { ReadValueFromMemory("cpu.z80HL", pbLocalRegC[bReg]); } else { assert(0); } } void AddRegpairOperations(UINT32 dwOpcode) { UINT8 bRegpair; bRegpair = (dwOpcode >> 4) & 0x3; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " and dh, 0ech ; Preserve the top three and bits 2 & 3\n"); fprintf(fp, " mov [_orgval], bx ; Store our original value\n"); fprintf(fp, " add bx, %s\n", pbRegPairs[bRegpair]); fprintf(fp, " lahf\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, [_orgval] ; Get original\n"); fprintf(fp, " xor di, bx ; XOR It with our computed value\n"); fprintf(fp, " xor di, %s\n", pbRegPairs[bRegpair]); fprintf(fp, " and di, 1000h ; Just our half carry\n"); fprintf(fp, " or dx, di ; Or in our flags\n"); fprintf(fp, " and ah, 01h ; Just carry\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " dwTemp = cpu.z80HL + %s;\n", pbRegPairsC[bRegpair]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80HL ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", pbRegPairsC[bRegpair]); fprintf(fp, " cpu.z80HL = dwTemp & 0xffff;\n"); return; } else { assert(0); } } void PushPopOperations(UINT32 dwOpcode) { UINT8 bRegPair; bRegPair = ((dwOpcode >> 4) & 0x3) << 1; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0xcf) == 0xc5) // Push { fprintf(fp, " sub word [_z80sp], 2\n"); fprintf(fp, " mov dx, [_z80sp]\n"); WriteWordToMemory("dx", pbPopRegPairs[bRegPair >> 1]); } else // Pop { fprintf(fp, " mov dx, [_z80sp]\n"); ReadWordFromMemory("dx", pbPopRegPairs[bRegPair >> 1]); fprintf(fp, " add word [_z80sp], 2\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if ((dwOpcode & 0xcf) == 0xc5) // Push? { fprintf(fp, " cpu.z80sp -= 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); WriteWordToMemory("cpu.z80sp", pbPopRegPairC[bRegPair >> 1]); return; } else { ReadWordFromMemory("cpu.z80sp", pbPopRegPairC[bRegPair >> 1]); fprintf(fp, " cpu.z80sp += 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); return; } InvalidInstructionC(1); } else { assert(0); } } void RraRlaHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); if (dwOpcode == 0x1f) fprintf(fp, " rcr al, 1\n"); else fprintf(fp, " rcl al, 1\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0edh\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x1f == dwOpcode) // RRA { fprintf(fp, " bTemp = (cpu.z80F & Z80_FLAG_CARRY) << 7;\n"); fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY)) | (cpu.z80A & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80A = ((cpu.z80A >> 1) | bTemp);\n"); } else // RLA { fprintf(fp, " bTemp = cpu.z80A >> 7;\n"); fprintf(fp, " cpu.z80A = (cpu.z80A << 1) | (cpu.z80F & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY)) | bTemp;\n"); } } else { assert(0); } } void LdByteRegpair(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x0a) ReadValueFromMemory("cx", "al"); if (dwOpcode == 0x1a) { fprintf(fp, " mov dx, [_z80de]\n"); ReadValueFromMemory("dx", "al"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode == 0x0a) ReadValueFromMemory("cpu.z80BC", "cpu.z80A"); if (dwOpcode == 0x1a) ReadValueFromMemory("cpu.z80DE", "cpu.z80A"); } else { assert(0); } } void IncDecHLPtr(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); ReadValueFromMemory("bx", "dl"); fprintf(fp, " sahf\n"); if (dwOpcode == 0x34) fprintf(fp, " inc dl\n"); else fprintf(fp, " dec dl\n"); fprintf(fp, " lahf\n"); fprintf(fp, " o16 pushf\n"); fprintf(fp, " shl edx, 16\n"); fprintf(fp, " and ah, 0fbh ; Knock out parity/overflow\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " and dh, 08h ; Just the overflow\n"); fprintf(fp, " shr dh, 1 ; Shift it into position\n"); fprintf(fp, " or ah, dh ; OR It in with the real flags\n"); fprintf(fp, " shr edx, 16\n"); if (dwOpcode == 0x34) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); else fprintf(fp, " or ah, 02h ; Make it N!\n"); WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); if (0x34 == dwOpcode) fprintf(fp ," cpu.z80F |= bPostIncFlags[bTemp];\n"); else fprintf(fp ," cpu.z80F |= bPostDecFlags[bTemp];\n"); if (0x34 == dwOpcode) fprintf(fp, " bTemp++;\n"); else fprintf(fp, " bTemp--;\n"); WriteValueToMemory("cpu.z80HL", "bTemp"); return; } else { assert(0); } } void InOutHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dl, [esi] ; Get our address to 'out' to\n"); fprintf(fp, " inc esi ; Next address\n"); if (b16BitIo) { fprintf(fp, " mov dh, al ; Upper 8 bits are the A register for 16 bit addressing\n"); } if (0xd3 == dwOpcode) WriteValueToIo("dx", "al"); else ReadValueFromIo("dx", "al"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp ," dwTemp = *pbPC++;\n"); if (0xd3 == dwOpcode) WriteValueToIo("dwTemp", "cpu.z80A"); else ReadValueFromIo("dwTemp", "cpu.z80A"); // Not supposed to set flags for immediate instruction! return; } else { assert(0); } } // CB Area void RESSETHandler(UINT32 dwOpcode) { UINT8 op = 0; op = dwOpcode & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((2 == op) || (3 == op)) fprintf(fp, " mov dx, [_z80de] ; Move DE into something half usable\n"); if ((dwOpcode & 0x07) == 6) // (HL)? ReadValueFromMemory("bx", "dl"); if ((dwOpcode & 0xc0) == 0x80) fprintf(fp, " and %s, 0%.2xh ; Reset a bit\n", pbLocalReg[op], 0xff - (1 << ((dwOpcode >> 3) & 0x7))); if ((dwOpcode & 0xc0) == 0xc0) fprintf(fp, " or %s, 0%.2xh ; Set a bit\n", pbLocalReg[op], (1 << ((dwOpcode >> 3) & 0x7))); if ((2 == op) || (3 == op)) { fprintf(fp, " mov [_z80de], dx ; Once modified, put it back\n"); fprintf(fp, " xor edx, edx\n"); } if ((dwOpcode & 0x07) == 6) // (HL)? { WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (6 == op) // (HL)? ReadValueFromMemory("cpu.z80HL", "bTemp"); if ((dwOpcode & 0xc0) == 0x80) // RES fprintf(fp, " %s &= 0x%.2x;\n", pbMathRegC[op], (UINT8) ~((UINT8) 1 << ((dwOpcode >> 3) & 0x07))); else // SET fprintf(fp, " %s |= 0x%.2x;\n", pbMathRegC[op], 1 << ((dwOpcode >> 3) & 0x07)); if (6 == op) // (HL)? WriteValueToMemory("cpu.z80HL", "bTemp"); } else assert(0); } void BITHandler(UINT32 dwOpcode) { UINT8 op = 0; UINT8 bBitVal = 0; op = dwOpcode & 0x07; bBitVal = 1 << ((dwOpcode >> 3) & 0x07); if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x07) == 6) // (HL)? ReadValueFromMemory("bx", "dl"); fprintf(fp, " mov byte [_z80af], ah ; Store F\n"); fprintf(fp, " sahf\n"); if ((dwOpcode & 0x07) == 6) fprintf(fp, " test dl, 0%.2xh ; Do a bitwise check\n", 1 << ((dwOpcode >> 3) & 0x7)); else fprintf(fp, " test %s, 0%.2xh ; Do a bitwise check\n", pbMathReg[op], 1 << ((dwOpcode >> 3) & 0x7)); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c0h ; Only care about Z and S\n"); fprintf(fp, " or ah, 10h ; Set half carry to 1\n"); fprintf(fp, " and byte [_z80af], 029h ; Only zero/non-zero!\n"); fprintf(fp, " or ah, byte [_z80af] ; Put it in with the real flags\n"); if (6 == (dwOpcode & 0x07)) // (HL)? fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (6 == op) // (HL)? ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO);\n"); fprintf(fp, " cpu.z80F |= (Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " if (!(%s & 0x%.2lx))\n", pbMathRegC[op], bBitVal); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); } else assert(0); } void RLCRRCRLRRSLASRASRLHandler(UINT32 dwOpcode) { UINT8 op = 0; op = dwOpcode & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((2 == op) || (3 == op)) fprintf(fp, " mov dx, [_z80de] ; Move DE into something half usable\n"); if ((dwOpcode & 0x07) == 6) // (HL)? ReadValueFromMemory("bx", "dl"); fprintf(fp, " sahf\n"); if ((dwOpcode & 0xf8) == 0) fprintf(fp, " rol %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x08) fprintf(fp, " ror %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x10) fprintf(fp, " rcl %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x18) fprintf(fp, " rcr %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x20 || (dwOpcode & 0xf8) == 0x30) fprintf(fp, " shl %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x28) fprintf(fp, " sar %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x38) fprintf(fp, " shr %s, 1\n", pbLocalReg[op]); else assert(0); fprintf(fp, " lahf\n"); if ((dwOpcode & 0xf8) >= 0x20) { if ((dwOpcode & 0xf8) == 0x30) fprintf(fp, " or %s, 1 ; Slide in a 1 bit (SLIA)\n", pbLocalReg[op]); fprintf(fp, " and ah, 0edh ; Clear H and N\n"); } else { fprintf(fp, " and ah, 029h ; Clear H and N\n"); fprintf(fp, " mov byte [_z80af], ah\n"); fprintf(fp, " or %s, %s\n", pbLocalReg[op], pbLocalReg[op]); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c4h ; Sign, zero, and parity\n"); fprintf(fp, " or ah, byte [_z80af]\n"); } if ((2 == op) || (3 == op)) { fprintf(fp, " mov [_z80de], dx ; Once modified, put it back\n"); fprintf(fp, " xor edx, edx\n"); } if ((dwOpcode & 0x07) == 6) // (HL)? { WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (6 == op) // (HL)? ReadValueFromMemory("cpu.z80HL", "bTemp"); dwOpcode &= 0xf8; // Just the instruction if (0 == dwOpcode) // RLC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp2 = (%s >> 7);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s << 1) | bTemp2;\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bTemp2 | bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x08 == dwOpcode) // RRC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1) | (%s << 7);\n", pbMathRegC[op], pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x10 == dwOpcode) // RL { fprintf(fp, " bTemp2 = cpu.z80F & Z80_FLAG_CARRY;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s >> 7);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s << 1) | bTemp2;\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x18 == dwOpcode) // RR { fprintf(fp, " bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1) | bTemp2;\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if ((0x20 == dwOpcode) || (0x30 == dwOpcode)) // SLA/SRL { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s >> 7);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s << 1);\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x28 == dwOpcode) // SRA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1) | (%s & 0x80);\n", pbMathRegC[op], pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x38 == dwOpcode) // SRL { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1);\n", pbMathRegC[op], pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else { InvalidInstructionC(2); } if (6 == op) // (HL)? WriteValueToMemory("cpu.z80HL", "bTemp"); } else assert(0); } // ED Area void RRDRLDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); ReadValueFromMemory("bx", "dl"); // Get (HL) fprintf(fp, " mov dh, dl ; Put a copy in DH\n"); if (0x6f == dwOpcode) // RLD { fprintf(fp, " shr dh, 4 ; Get our upper nibble in position\n"); fprintf(fp, " shl dl, 4 ; Get our lower nibble into the higher position\n"); fprintf(fp, " shl ecx, 16 ; Save this for later\n"); fprintf(fp, " mov cl, al\n"); fprintf(fp, " and cl, 0fh\n ; Only the lower nibble\n"); fprintf(fp, " or dl, cl ; OR In A->(HL) transfer\n"); fprintf(fp, " and al, 0f0h ; Only the upper 4 bits remain\n"); fprintf(fp, " or al, dh ; OR It in to our accumulator\n"); fprintf(fp, " shr ecx, 16 ; Restore this\n"); } else // RRD if (0x67 == dwOpcode) { fprintf(fp, " shr dl, 4 ; Upper nibble to lower nibble\n"); fprintf(fp, " shl ecx, 16 ; Save this\n"); fprintf(fp, " mov cl, al\n"); fprintf(fp, " shl cl, 4\n"); fprintf(fp, " or dl, cl ; OR In what was in A\n"); fprintf(fp, " and al, 0f0h ; Knock out lower part\n"); fprintf(fp, " and dh, 0fh ; Only the lower nibble\n"); fprintf(fp, " or al, dh ; OR In our nibble\n"); fprintf(fp, " shr ecx, 16 ; Restore this\n"); } else // Whoops! assert(0); // This routine assumes that the new value to be placed at (HL) is in DL fprintf(fp, " and ah, 29h ; Retain carry & two undefined bits\n"); fprintf(fp, " mov dh, ah ; Store our flags away for later\n"); fprintf(fp, " or al, al ; Get our flags\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah,0c4h ; Only partiy, zero, and sign\n"); fprintf(fp, " or ah, dh ; OR In our old flags\n"); // Now go write the value back WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx ; Zero out this for later\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x67 == dwOpcode) // RRD { ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " bTemp2 = (cpu.z80A & 0x0f) << 4;\n"); fprintf(fp, " cpu.z80A = (cpu.z80A & 0xf0) | (bTemp & 0x0f);\n"); fprintf(fp, " bTemp = (bTemp >> 4) | bTemp2;\n"); WriteValueToMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n"); } else if (0x6f == dwOpcode) // RLD { ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " bTemp2 = (cpu.z80A & 0x0f);\n"); fprintf(fp, " cpu.z80A = (cpu.z80A & 0xf0) | (bTemp >> 4);\n"); fprintf(fp, " bTemp = (bTemp << 4) | bTemp2;\n"); WriteValueToMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n"); } else InvalidInstructionC(2); } else assert(0); } void CPICPDCPIRCPDRHandler(UINT32 dwOpcode) { UINT32 dwRepeatOb = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0xb1 || dwOpcode == 0xb9) { fprintf(fp, "cpRepeat%ld:\n", dwGlobalLabel); dwRepeatOb = dwGlobalLabel; ++dwGlobalLabel; } // Now go get the data from the source ReadValueFromMemory("bx", "dl"); // Target data is in DL fprintf(fp, " mov byte [_z80af], ah\n"); fprintf(fp, " sahf\n"); fprintf(fp, " cmp al, dl ; Do our comparison\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0fah ; No P/V or carry!\n"); fprintf(fp, " dec cx ; Dec BC\n"); fprintf(fp, " jz notBcZero%ld\n", dwGlobalLabel); fprintf(fp, " or ah, 04h ; P/V set when BC not zero\n"); fprintf(fp, "notBcZero%ld:\n", dwGlobalLabel); fprintf(fp, " or ah, 02h ; N Gets set when we do compares\n"); fprintf(fp, " mov dl, byte [_z80af]\n"); fprintf(fp, " and dl, 01h\n"); fprintf(fp, " or ah, dl ; Preserve carry!\n"); if (dwOpcode == 0xa1 || dwOpcode == 0xb1) fprintf(fp, " inc bx ; Increment!\n"); if (dwOpcode == 0xa9 || dwOpcode == 0xb9) fprintf(fp, " dec bx ; Decrement!\n"); // Let's see if we repeat... if (dwOpcode == 0xb1 || dwOpcode == 0xb9) { fprintf(fp, " sahf\n"); fprintf(fp, " jz BCDone%ld\n", dwRepeatOb); fprintf(fp, " jnp BCDone%ld\n", dwRepeatOb); if (FALSE == bNoTiming) { fprintf(fp, " sub edi, dword 21\n"); fprintf(fp, " js BCDoneExit%ld\n", dwRepeatOb); } fprintf(fp, " jmp cpRepeat%ld\n", dwRepeatOb); fprintf(fp, "BCDoneExit%ld:\n", dwRepeatOb); fprintf(fp, " sub esi, 2 ; Back up to the instruction again\n"); fprintf(fp, " jmp noMoreExec\n\n"); fprintf(fp, "BCDone%ld:\n", dwRepeatOb); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xb1 == dwOpcode || 0xb9 == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining >= 0) && (cpu.z80BC))\n"); } fprintf(fp, " {\n"); ReadValueFromMemory("cpu.z80HL", "bTemp"); if (0xb1 == dwOpcode || 0xa1 == dwOpcode) { fprintf(fp, " cpu.z80HL++;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } else { fprintf(fp, " cpu.z80HL--;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } fprintf(fp, " cpu.z80BC--;\n"); fprintf(fp, " cpu.z80BC &= 0xffff;\n"); if (0xb1 == dwOpcode || 0xb9 == dwOpcode) // Repeat? { fprintf(fp, " sdwCyclesRemaining -= 16;\n"); fprintf(fp, " if (cpu.z80A == bTemp)\n"); fprintf(fp, " {\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); } fprintf(fp, " }\n"); // Now figure out what's going on fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= (pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO));\n"); fprintf(fp, " if (cpu.z80BC)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); } else assert(0); } void INIRINDRINIINDHandler(UINT32 dwOpcode) { UINT32 dwTempLabel = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); dwTempLabel = dwGlobalLabel; dwGlobalLabel++; if (0xba == dwOpcode || 0xb2 == dwOpcode) fprintf(fp, "loopIt%ld:\n", dwTempLabel); // Fetch what's at (C) and put it in (HL) fprintf(fp, " push cx ; Save BC\n"); if (b16BitIo == FALSE) fprintf(fp, " xor ch, ch ; We want 8 bit ports\n"); ReadValueFromIo("cx", "*dl"); // Put our value in DL fprintf(fp, " pop cx ; Restore BC\n"); WriteValueToMemory("bx", "dl"); if (0xa2 == dwOpcode || 0xb2 == dwOpcode) fprintf(fp, " inc bx ; Increment HL\n"); else if (0xaa == dwOpcode || 0xba == dwOpcode) fprintf(fp, " dec bx ; Decrement HL\n"); // Now we decrement B fprintf(fp, " dec ch ; Decrement B (of C)\n"); // Emit this instruction if we repeat if (0xba == dwOpcode || 0xb2 == dwOpcode) { fprintf(fp, " jz near finalExit%ld\n", dwTempLabel); // Otherwise, we need to loop again if (FALSE == bNoTiming) { fprintf(fp, " sub edi, dword 21\n"); fprintf(fp, " js loopExit%ld\n", dwTempLabel); } fprintf(fp, " jmp loopIt%ld\n\n", dwTempLabel); fprintf(fp, "loopExit%ld:\n", dwTempLabel); fprintf(fp, " sub esi, 2\n"); fprintf(fp, " jmp noMoreExec\n\n"); } // Now let's fix up the flags fprintf(fp, "finalExit%ld:\n", dwTempLabel); fprintf(fp, " jnz clearFlag%ld\n", dwTempLabel); fprintf(fp, " or ah, 040h ; Set the Zero flag!\n"); fprintf(fp, " jmp short continue%ld\n", dwTempLabel); fprintf(fp, "clearFlag%ld:\n", dwTempLabel); fprintf(fp, " and ah, 0bfh ; Clear the zero flag\n"); fprintf(fp, "continue%ld:\n", dwTempLabel); fprintf(fp, " or ah, 02h ; Set negative!\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xb2 == dwOpcode || 0xba == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining > 0) && (cpu.z80B))\n"); } fprintf(fp, " {\n"); ReadValueFromIo("cpu.z80B", "bTemp"); WriteValueToMemory("cpu.z80HL", "bTemp"); if (0xb2 == dwOpcode || 0xa2 == dwOpcode) { fprintf(fp, " cpu.z80HL++;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } else { fprintf(fp, " cpu.z80HL--;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } fprintf(fp, " sdwCyclesRemaining -= 16;\n"); fprintf(fp, " cpu.z80B--;\n"); fprintf(fp, " }\n"); // Now figure out what's going on fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY));\n"); fprintf(fp, " if (cpu.z80B)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " pbPC -= 2;\n"); fprintf(fp, " }\n"); } else assert(0); } void OTIROTDROUTIOUTDHandler(UINT32 dwOpcode) { UINT32 dwTempLabel = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); dwTempLabel = dwGlobalLabel; dwGlobalLabel++; if (0xbb == dwOpcode || 0xb3 == dwOpcode) fprintf(fp, "loopIt%ld:\n", dwTempLabel); // Fetch what's at (HL) and put it in DL ReadValueFromMemory("bx", "dl"); fprintf(fp, " push cx ; Save BC\n"); if (b16BitIo == FALSE) fprintf(fp, " xor ch, ch ; No 16 bit for this instruction!\n"); WriteValueToIo("cx", "dl"); fprintf(fp, " pop cx ; Restore BC now that it has been \"OUT\"ed\n"); if (0xa3 == dwOpcode || 0xb3 == dwOpcode) fprintf(fp, " inc bx ; Increment HL\n"); else if (0xab == dwOpcode || 0xbb == dwOpcode) fprintf(fp, " dec bx ; Decrement HL\n"); // Now we decrement B fprintf(fp, " dec ch ; Decrement B (of C)\n"); // Emit this instruction if we repeat if (0xbb == dwOpcode || 0xb3 == dwOpcode) { fprintf(fp, " jz near finalExit%ld\n", dwTempLabel); // Otherwise, we need to loop again if (FALSE == bNoTiming) { fprintf(fp, " sub edi, dword 21\n"); fprintf(fp, " js loopExit%ld\n", dwTempLabel); } fprintf(fp, " jmp loopIt%ld\n\n", dwTempLabel); fprintf(fp, "loopExit%ld:\n", dwTempLabel); fprintf(fp, " sub esi, 2\n"); fprintf(fp, " jmp noMoreExec\n\n"); } // Now let's fix up the flags fprintf(fp, "finalExit%ld:\n", dwTempLabel); fprintf(fp, " jnz clearFlag%ld\n", dwTempLabel); fprintf(fp, " or ah, 040h ; Set the Zero flag!\n"); fprintf(fp, " jmp short continue%ld\n", dwTempLabel); fprintf(fp, "clearFlag%ld:\n", dwTempLabel); fprintf(fp, " and ah, 0bfh ; Clear the zero flag\n"); fprintf(fp, "continue%ld:\n", dwTempLabel); fprintf(fp, " or ah, 02h ; Set negative!\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xb3 == dwOpcode || 0xbb == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining > 0) && (cpu.z80B))\n"); } fprintf(fp, " {\n"); ReadValueFromMemory("cpu.z80HL", "bTemp"); WriteValueToIo("cpu.z80BC", "bTemp"); if (0xb3 == dwOpcode || 0xa3 == dwOpcode) { fprintf(fp, " cpu.z80HL++;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } else { fprintf(fp, " cpu.z80HL--;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } fprintf(fp, " sdwCyclesRemaining -= 16;\n"); fprintf(fp, " cpu.z80B--;\n"); fprintf(fp, " }\n"); // Now figure out what's going on fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY));\n"); fprintf(fp, " if (cpu.z80B)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); } else assert(0); } void AdcSbcRegpair(UINT32 dwOpcode) { UINT8 bOp = 0; bOp = (dwOpcode >> 4) & 0x03; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, %s ; Get our original register\n", pbRegPairs[bOp]); fprintf(fp, " mov [_orgval], dx ; Store this for later half carry computation\n"); fprintf(fp, " mov [_orgval2], bx ; Store this, too\n"); fprintf(fp, " sahf ; Restore our flags\n"); if ((dwOpcode & 0xcf) == 0x4a) fprintf(fp, " adc bx, dx ; Do the operation!\n"); else fprintf(fp, " sbb bx, dx ; Do the operation!\n"); fprintf(fp, " lahf ; Get our new flags\n"); if ((dwOpcode & 0xcf) != 0x4a) { SetOverflow(); fprintf(fp, " and ah, 0edh ; Knock out negative & half carry flags\n"); fprintf(fp, " or ah, 02h ; Negative!\n"); fprintf(fp, " mov [_z80hl], bx\n"); fprintf(fp, " xor bx, [_orgval]\n"); fprintf(fp, " xor bx, [_orgval2]\n"); fprintf(fp, " and bh, 10h ; Half carry?\n"); fprintf(fp, " or ah, bh ; OR It in if so\n"); fprintf(fp, " mov bx, [_z80hl]\n"); } else { SetOverflow(); fprintf(fp, " and ah, 0edh ; Knock out negative & half carry flags\n"); fprintf(fp, " mov [_z80hl], bx\n"); fprintf(fp, " xor bx, [_orgval]\n"); fprintf(fp, " xor bx, [_orgval2]\n"); fprintf(fp, " and bh, 10h ; Half carry?\n"); fprintf(fp, " or ah, bh ; OR It in if so\n"); fprintf(fp, " mov bx, [_z80hl]\n"); } fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if ((dwOpcode & 0xcf) == 0x4a) // ADC { fprintf(fp, " dwTemp = cpu.z80HL + %s + (cpu.z80F & Z80_FLAG_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN);\n"); fprintf(fp, " if (0 == (dwTemp & 0xffff))\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((((%s ^ cpu.z80HL ^ 0x8000) & (%s ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY);\n", pbRegPairsC[bOp], pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80HL = dwTemp & 0xffff;\n"); return; } else // SBC { fprintf(fp, " dwTemp = cpu.z80HL - %s - (cpu.z80F & Z80_FLAG_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN);\n"); fprintf(fp, " if (0 == (dwTemp & 0xffff))\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((((%s ^ cpu.z80HL) & (%s ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY);\n", pbRegPairsC[bOp], pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80HL = dwTemp & 0xffff;\n"); return; } } else assert(0); } void RetIRetNHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bThroughCallHandler) { fprintf(fp, " call PopWord\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, dx\n"); fprintf(fp, " add esi, ebp\n"); } else { fprintf(fp, " mov dx, word [_z80sp] ; Get our current stack pointer\n"); fprintf(fp, " mov si, [edx+ebp] ; Get our return address\n"); fprintf(fp, " and esi, 0ffffh ; Only within 64K!\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " add word [_z80sp], 02h ; Remove our two bytes from the stack\n"); } if (dwOpcode == 0x45) { fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov dl, [_z80iff] ; Get interrupt flags\n"); fprintf(fp, " shr dl, 1 ; Move IFF2->IFF1\n"); fprintf(fp, " and [_z80iff], dword (~IFF1) ; Get rid of IFF 1\n"); fprintf(fp, " and dl, IFF1 ; Just want the IFF 1 value now\n"); fprintf(fp, " or dword [_z80iff], edx\n"); } fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x4d == dwOpcode) // RETI { fprintf(fp, " pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */\n"); fprintf(fp, " dwAddr = *pbSP++; /* Pop LSB */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */\n"); fprintf(fp, " cpu.z80sp += 2; /* Pop the word off */\n"); fprintf(fp, " pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */\n"); } else if (0x45 == dwOpcode) // RETN { fprintf(fp, " pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */\n"); fprintf(fp, " dwAddr = *pbSP++; /* Pop LSB */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */\n"); fprintf(fp, " cpu.z80sp += 2; /* Pop the word off */\n"); fprintf(fp, " pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */\n"); fprintf(fp, " cpu.z80iff &= ~(IFF1); /* Keep IFF2 around */\n"); fprintf(fp, " cpu.z80iff |= ((cpu.z80iff >> 1) & IFF1); /* IFF2->IFF1 */\n"); } else { InvalidInstructionC(2); } } else assert(0); } void ExtendedOutHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (b16BitIo == FALSE) fprintf(fp, " mov dl, cl ; Address in DX... (C)\n"); else fprintf(fp, " mov dx, cx ; Address in DX... (BC)\n"); WriteValueToIo("dx", pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (b16BitIo == FALSE) fprintf(fp, " dwAddr = cpu.z80C;\n"); else fprintf(fp, " dwAddr = cpu.z80BC;\n"); WriteValueToIo("dwAddr", pbMathRegC[(dwOpcode >> 3) & 0x07]); } else assert(0); } void ExtendedInHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (b16BitIo == FALSE) fprintf(fp, " mov dl, cl ; Address in DX... (C)\n"); else fprintf(fp, " mov dx, cx ; Address in DX... (BC)\n"); ReadValueFromIo("dx", pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, ";\n; Remember, this variant of the IN instruction modifies the flags\n;\n\n"); fprintf(fp, " sahf ; Restore our flags\n"); fprintf(fp, " mov dh, ah ; Save flags for later\n"); if (0x50 == dwOpcode || 0x58 == dwOpcode) { fprintf(fp, " mov dl, %s\n", pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, " or dl, dl\n"); } else fprintf(fp, " or %s, %s;\n", pbMathReg[(dwOpcode >> 3) & 0x07], pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, " lahf\n"); fprintf(fp, " and dh, 029h ; Only keep carry and two unused flags\n"); fprintf(fp, " and ah, 0d4h\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (b16BitIo == FALSE) fprintf(fp, " dwAddr = cpu.z80C;\n"); else fprintf(fp, " dwAddr = cpu.z80BC;\n"); ReadValueFromIo("dwAddr", pbMathRegC[(dwOpcode >> 3) & 0x07]); // Set flags! fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[(dwOpcode >> 3) & 0x07]); } else assert(0); } void NegHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); fprintf(fp, " sub dh, al\n"); fprintf(fp, " lahf\n"); fprintf(fp, " mov al, dh\n"); SetOverflow(); fprintf(fp, " or ah, 02h\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { SetSubFlagsSZHVC("0", "cpu.z80A"); fprintf(fp, " cpu.z80A = 0 - cpu.z80A;\n"); } else assert(0); } void ExtendedRegIntoMemory(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address to write to\n"); fprintf(fp, " add esi, 2 ; Next address, please...\n"); if (dwOpcode == 0x43) WriteValueToMemory("dx", "cl"); if (dwOpcode == 0x53) WriteValueToMemory("dx", "byte [_z80de]"); if (dwOpcode == 0x63) WriteValueToMemory("dx", "bl"); if (dwOpcode == 0x73) WriteValueToMemory("dx", "byte [_z80sp]"); fprintf(fp, " inc dx\n"); if (dwOpcode == 0x43) WriteValueToMemory("dx", "ch"); if (dwOpcode == 0x53) WriteValueToMemory("dx", "byte [_z80de + 1]"); if (dwOpcode == 0x63) WriteValueToMemory("dx", "bh"); if (dwOpcode == 0x73) WriteValueToMemory("dx", "byte [_z80sp + 1]"); fprintf(fp, " xor edx, edx ; Zero our upper word\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= ((UINT32) *pbPC++ << 8);\n"); if (0x43 == dwOpcode) // LD (xxxxh), BC WriteWordToMemory("dwTemp", "cpu.z80BC"); if (0x53 == dwOpcode) // LD (xxxxh), DE WriteWordToMemory("dwTemp", "cpu.z80DE"); if (0x63 == dwOpcode) // LD (xxxxh), HL WriteWordToMemory("dwTemp", "cpu.z80HL"); if (0x73 == dwOpcode) // LD (xxxxh), SP WriteWordToMemory("dwTemp", "cpu.z80sp"); } else assert(0); } void LdRegpair(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get address to load\n"); fprintf(fp, " add esi, 2 ; Skip over it so we don't execute it\n"); if (dwOpcode == 0x4b) ReadValueFromMemory("dx", "cl"); if (dwOpcode == 0x5b) ReadValueFromMemory("dx", "byte [_z80de]"); if (dwOpcode == 0x7b) ReadValueFromMemory("dx", "byte [_z80sp]"); fprintf(fp, " inc dx\n"); if (dwOpcode == 0x4b) ReadValueFromMemory("dx", "ch"); if (dwOpcode == 0x5b) ReadValueFromMemory("dx", "byte [_z80de + 1]"); if (dwOpcode == 0x7b) ReadValueFromMemory("dx", "byte [_z80sp + 1]"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= ((UINT32) *pbPC++ << 8);\n"); if (0x4b == dwOpcode) ReadWordFromMemory("dwTemp", "cpu.z80BC"); if (0x5b == dwOpcode) ReadWordFromMemory("dwTemp", "cpu.z80DE"); if (0x7b == dwOpcode) ReadWordFromMemory("dwTemp", "cpu.z80sp"); } else assert(0); } void LDILDRLDIRLDDRHandler(UINT32 dwOpcode) { UINT32 dwOrgGlobal = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0xb0 || dwOpcode == 0xb8) { dwOrgGlobal = dwGlobalLabel; fprintf(fp, "ldRepeat%ld:\n", dwGlobalLabel); } ReadValueFromMemory("bx", "dl"); // Here we write the byte back to the target WriteValueToMemory("[_z80de]", "dl"); // Now we decide what to do if ((dwOpcode & 0x0f) == 0) { fprintf(fp, " inc bx ; Increment HL\n"); fprintf(fp, " inc word [_z80de] ; Increment DE\n"); } else { fprintf(fp, " dec bx ; Decrement HL\n"); fprintf(fp, " dec word [_z80de] ; Decrement DE\n"); } fprintf(fp, " dec cx ; Decrement BC\n"); if (dwOpcode == 0xb0 || dwOpcode == 0xb8) { if (FALSE == bNoTiming) { fprintf(fp, " jz noMore%ld\n", dwGlobalLabel); fprintf(fp, " sub edi, dword 16 ; 16 T-States per iteration\n"); fprintf(fp, " js noMore%ld\n", dwGlobalLabel); } else { fprintf(fp, " jz noMore%ld\n", dwGlobalLabel); } fprintf(fp, " jmp ldRepeat%ld ; Loop until we're done!\n", dwOrgGlobal); fprintf(fp, "noMore%ld:\n", dwGlobalLabel); } fprintf(fp, " and ah, 0e9h ; Knock out H & N and P/V\n"); fprintf(fp, " or cx, cx ; Flag BC\n"); fprintf(fp, " jz atZero%ld ; We're done!\n", dwGlobalLabel); if (dwOpcode == 0xb0 || dwOpcode == 0xb8) { // It's a repeat, so let's readjust ESI, shall we? fprintf(fp, " or ah, 04h ; Non-zero - we're still going!\n"); fprintf(fp, " sub esi, 2 ; Adjust back to the beginning of the instruction\n"); fprintf(fp, " jmp noMoreExec\n\n"); } else if (dwOpcode == 0xa0 || dwOpcode == 0xa8) { fprintf(fp, " or ah, 04h ; Non-zero - we're still going!\n"); } fprintf(fp, "atZero%ld:\n", dwGlobalLabel); ++dwGlobalLabel; fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { // This is the actual move if (0xb0 == dwOpcode || 0xb8 == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining > 0) && (cpu.z80BC))\n"); fprintf(fp, " {\n"); } ReadValueFromMemory("cpu.z80HL", "bTemp"); WriteValueToMemory("cpu.z80DE", "bTemp"); if ((dwOpcode & 0x0f) == 0) { fprintf(fp, " ++cpu.z80HL;\n"); fprintf(fp, " ++cpu.z80DE;\n"); } else { fprintf(fp, " --cpu.z80HL;\n"); fprintf(fp, " --cpu.z80DE;\n"); } fprintf(fp, " --cpu.z80BC;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); fprintf(fp, " cpu.z80DE &= 0xffff;\n"); fprintf(fp, " cpu.z80BC &= 0xffff;\n"); if (0xb0 == dwOpcode || 0xb8 == dwOpcode) // Repeat instruction? { fprintf(fp, " sdwCyclesRemaining -= 21;\n"); fprintf(fp, " }\n"); } // Time for a flag fixup! fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY);\n"); fprintf(fp, " if (cpu.z80BC)\n"); fprintf(fp, " {\n"); if (0xb0 == dwOpcode || 0xb8 == dwOpcode) { fprintf(fp, " pbPC -= 2; /* Back up so we hit this instruction again */\n"); } fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); if (0xb0 == dwOpcode || 0xb8 == dwOpcode) // Repeat instruction? { fprintf(fp, " sdwCyclesRemaining -= 16;\n"); } } else assert(0); } void IMHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x46) fprintf(fp, " mov dword [_z80interruptMode], 0 ; IM 0\n"); if (dwOpcode == 0x56) { fprintf(fp, " mov dword [_z80interruptMode], 1 ; Interrupt mode 1\n"); fprintf(fp, " mov word [_z80intAddr], 038h ; Interrupt mode 1 cmd!\n"); } if (dwOpcode == 0x5e) fprintf(fp, " mov dword [_z80interruptMode], 2 ; IM 2\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x46 == dwOpcode) // IM 0 fprintf(fp, " cpu.z80interruptMode = 0;\n"); if (0x56 == dwOpcode) // IM 1 { fprintf(fp, " cpu.z80interruptMode = 1;\n"); fprintf(fp, " cpu.z80intAddr = 0x38;\n"); } if (0x5e == dwOpcode) // IM 2 fprintf(fp, " cpu.z80interruptMode = 2;\n"); } else assert(0); } void IRHandler(UINT32 dwOpcode) { char *src, *dst; if (MZ80_ASSEMBLY_X86 == bWhat) { switch(dwOpcode) { case 0x57: dst = "al"; src="[_z80i]"; break; case 0x5F: dst = "al"; src="[_z80r]"; break; case 0x47: dst = "[_z80i]"; src="al"; break; case 0x4F: dst = "[_z80r]"; src="al"; break; } ProcBegin(dwOpcode); fprintf(fp, " mov %s, %s\n",dst,src); if (dwOpcode == 0x5f) { fprintf(fp, " and ah, 029h ; No N, H, Z, or S!\n"); fprintf(fp, " or al,al ; Get appropriate flags\n"); fprintf(fp, " o16 pushf\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " and dl, 0c0h\n"); fprintf(fp, " or ah, dl ; OR In our S & Z flags\n"); fprintf(fp, " mov dl, [_z80iff]\n"); fprintf(fp, " and dl, IFF2\n"); fprintf(fp, " shl dl, 1\n"); fprintf(fp, " or ah, dl\n"); // Randomize R fprintf(fp, " mov edx, [dwLastRSample]\n"); fprintf(fp, " sub edx, edi\n"); fprintf(fp, " add edx, [_z80rCounter]\n"); fprintf(fp, " shr edx, 2\n"); fprintf(fp, " and edx, 07fh\n"); fprintf(fp, " and byte [_z80r], 80h\n"); fprintf(fp, " or byte [_z80r], dl\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov [dwLastRSample], edi\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x5f == dwOpcode) // LD A, R { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80r];\n"); fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_OVERFLOW_PARITY)) | ((cpu.z80iff & IFF2) << 1);\n"); fprintf(fp, " cpu.z80A = cpu.z80r;\n"); // Now randomize a little fprintf(fp, " bTemp = (cpu.z80r + (cpu.z80B + sdwCyclesRemaining + 1 + cpu.z80H)) ^ cpu.z80A;\n"); fprintf(fp, " cpu.z80r = (cpu.z80r & 0x80) | (bTemp & 0x7f);\n"); } else if (0x47 == dwOpcode) // LD I, A { fprintf(fp, " cpu.z80i = cpu.z80A;\n"); } else if (0x57 == dwOpcode) // LD A, I { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= ((cpu.z80iff & IFF2) << 1);\n"); fprintf(fp, " cpu.z80A = cpu.z80i;\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n"); } else if (0x4f == dwOpcode) // LD R, A { fprintf(fp, " cpu.z80r = cpu.z80A;\n"); } else { InvalidInstructionC(2); } } else assert(0); } // DD/FD Area void DDFDCBHandler(UINT32 dwOpcode) { UINT32 dwData = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, "%sInst%.2x:\n", majorOp, dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our instruction (and offset)\n"); fprintf(fp, " add esi, 2 ; Increment our PC\n"); fprintf(fp, " mov byte [_orgval], dl ; Store our value\n"); fprintf(fp, " or dl, dl\n"); fprintf(fp, " js notNeg%ld\n", dwGlobalLabel); fprintf(fp, " mov byte [_orgval + 1], 00h;\n"); fprintf(fp, " jmp short jumpHandler%ld\n", dwGlobalLabel); fprintf(fp, "notNeg%ld:\n", dwGlobalLabel); fprintf(fp, " mov byte [_orgval + 1], 0ffh; It's negative\n"); fprintf(fp, "jumpHandler%ld:\n", dwGlobalLabel++); fprintf(fp, " shl ebx, 16 ; Save BX away\n"); fprintf(fp, " mov bx, [_z80%s]\n", mz80Index); fprintf(fp, " add [_orgval], bx\n"); fprintf(fp, " shr ebx, 16 ; Restore BX\n"); fprintf(fp, " mov dl, dh ; Get our instruction\n"); fprintf(fp, " xor dh, dh ; Zero this\n"); fprintf(fp, " jmp dword [z80ddfdcbInstructions+edx*4]\n\n"); } else if (MZ80_C == bWhat) { if (strcmp("cpu.z80IX", mz80Index) == 0) dwData = 0; else dwData = 1; fprintf(fp, " DDFDCBHandler(%d);\n", dwData); } else assert(0); } void LoadIndexReg(UINT32 dwOpcode) { UINT8 string[150]; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); sprintf(string, "[_z80%s]", mz80Index); fprintf(fp, " mov dx, [esi] ; Get our address to store\n"); fprintf(fp, " add esi, 2\n"); ReadWordFromMemory("dx", string); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++;\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8);\n"); ReadWordFromMemory("dwAddr", mz80Index); } else assert(0); } void StoreIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address to store\n"); fprintf(fp, " add esi, 2\n"); fprintf(fp, " mov [_orgval], dx\n"); fprintf(fp, " mov dl, [_z80%s]\n", mz80Index); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " inc word [_orgval]\n"); fprintf(fp, " mov dl, [_z80%s + 1]\n", mz80Index); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++;\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8);\n"); WriteWordToMemory("dwAddr", mz80Index); } else assert(0); } void LdIndexPtrReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); // DX Contains the address WriteValueToMemory("dx", pbMathReg[dwOpcode & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; // Get the offset\n"); fprintf(fp, " sdwAddr = ((INT32) %s + sdwAddr) & 0xffff;\n", mz80Index); WriteValueToMemory("sdwAddr", pbMathRegC[dwOpcode & 0x07]); } else assert(0); } void UndocMathIndex(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; UINT8 *pbIndexReg = NULL; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode & 1) fprintf(fp, " mov dl, byte [_z80%s]\n", mz80Index); else fprintf(fp, " mov dl, byte [_z80%s + 1]\n", mz80Index); // Info is in DL - let's do the math operation fprintf(fp, " sahf ; Store our flags in x86 flag reg\n"); dwOpcode1 = (dwOpcode & 0xf8); // Only the operation if (dwOpcode1 == 0x80) fprintf(fp, " add al, dl\n"); else if (dwOpcode1 == 0x88) fprintf(fp, " adc al, dl\n"); else if (dwOpcode1 == 0x90) fprintf(fp, " sub al, dl\n"); else if (dwOpcode1 == 0x98) fprintf(fp, " sbb al, dl\n"); else if (dwOpcode1 == 0xa0) fprintf(fp, " and al, dl\n"); else if (dwOpcode1 == 0xa8) fprintf(fp, " xor al, dl\n"); else if (dwOpcode1 == 0xb0) fprintf(fp, " or al, dl\n"); else if (dwOpcode1 == 0xb8) fprintf(fp, " cmp al, dl\n"); else assert(0); fprintf(fp, " lahf ; Get flags back into AH\n"); if (dwOpcode1 != 0xa8 && dwOpcode1 != 0xa0 && dwOpcode1 != 0xb0) { SetOverflow(); } if (dwOpcode1 == 0xa8) fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); if (dwOpcode1 == 0xa0) { fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); fprintf(fp, " or ah, 010h ; Half carry gets set\n"); } if (dwOpcode1 == 0xb0) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); if (dwOpcode1 == 0xb8) fprintf(fp, " or ah, 02h ; Negative gets set on a compare\n"); if (dwOpcode1 == 0x80 || dwOpcode1 == 0x88) fprintf(fp, " and ah, 0fdh ; No N!\n"); if (dwOpcode1 == 0x90 || dwOpcode1 == 0x98) fprintf(fp, " or ah, 02h ; N Gets set!\n"); if (dwOpcode1 == 0xb0) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode & 1) pbIndexReg = mz80IndexHalfLow; else pbIndexReg = mz80IndexHalfHigh; dwOpcode1 = (dwOpcode & 0xf8); // Only the operation if (0x80 == dwOpcode1) // ADD { fprintf(fp, " bTemp2 = cpu.z80A + %s;\n", pbIndexReg); SetAddFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0x88 == dwOpcode1) // ADC { fprintf(fp, " bTemp2 = cpu.z80A + %s + (cpu.z80F & Z80_FLAG_CARRY);\n", pbIndexReg); SetAdcFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0x90 == dwOpcode1) // SUB { fprintf(fp, " bTemp2 = cpu.z80A - %s;\n", pbIndexReg); SetSubFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0x98 == dwOpcode1) // SBC { fprintf(fp, " bTemp2 = cpu.z80A - %s - (cpu.z80F & Z80_FLAG_CARRY);\n", pbIndexReg); SetSbcFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0xa0 == dwOpcode1) // AND { fprintf(fp, " cpu.z80A &= %s;\n", pbIndexReg); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } else if (0xa8 == dwOpcode1) // XOR { fprintf(fp, " cpu.z80A ^= %s;\n", pbIndexReg); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xb0 == dwOpcode1) // OR { fprintf(fp, " cpu.z80A |= %s;\n", pbIndexReg); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xb8 == dwOpcode1) // CP - Don't do anything! Just flags! { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else { assert(0); } InvalidInstructionC(2); } else assert(0); } void UndocLoadHalfIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dl, [esi] ; Get immediate byte to load\n"); fprintf(fp, " inc esi ; Next byte\n"); if (dwOpcode == 0x26) fprintf(fp, " mov byte [_z80%s + 1], dl\n", mz80Index); if (dwOpcode == 0x2e) fprintf(fp, " mov byte [_z80%s], dl\n", mz80Index); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode & 0x08) fprintf(fp, " %s = *pbPC++;\n", mz80IndexHalfLow); else fprintf(fp, " %s = *pbPC++;\n", mz80IndexHalfHigh); } else assert(0); } void UndocIncDecIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); if (dwOpcode == 0x24) fprintf(fp, " inc byte [_z80%s + 1]\n", mz80Index); if (dwOpcode == 0x25) fprintf(fp, " dec byte [_z80%s + 1]\n", mz80Index); if (dwOpcode == 0x2c) fprintf(fp, " inc byte [_z80%s]\n", mz80Index); if (dwOpcode == 0x2d) fprintf(fp, " dec byte [_z80%s]\n", mz80Index); fprintf(fp, " lahf\n"); SetOverflow(); if ((0x24 == dwOpcode) || (0x2c == dwOpcode)) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); else fprintf(fp, " or ah, 02h ; Set negative!\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); if (0x24 == dwOpcode || 0x2c == dwOpcode) { if (dwOpcode & 0x08) fprintf(fp, " cpu.z80F |= bPostIncFlags[%s++];\n", mz80IndexHalfLow); else fprintf(fp, " cpu.z80F |= bPostIncFlags[%s++];\n", mz80IndexHalfHigh); } else { if (dwOpcode & 0x08) fprintf(fp, " cpu.z80F |= bPostDecFlags[%s--];\n", mz80IndexHalfLow); else fprintf(fp, " cpu.z80F |= bPostDecFlags[%s--];\n", mz80IndexHalfHigh); } } else assert(0); } void ExIndexed(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if( bThroughCallHandler ) { fprintf(fp, " mov dx, word [_z80%s]\n", mz80Index); fprintf(fp, " push dx\n"); fprintf(fp, " call PopWord\n"); fprintf(fp, " mov [_z80%s], dx\n", mz80Index); fprintf(fp, " pop dx\n"); fprintf(fp, " mov [_wordval], dx\n" ); fprintf(fp, " call PushWord\n" ); } else { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov dx, word [_z80sp]\n"); fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, [_z80%s]\n", mz80Index); fprintf(fp, " xchg di, [ebp+edx]\n"); fprintf(fp, " mov [_z80%s], di\n", mz80Index); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { ReadWordFromMemory("cpu.z80sp", "dwAddr"); WriteWordToMemory("cpu.z80sp", mz80Index); fprintf(fp, " %s = dwAddr;\n", mz80Index); } else assert(0); } void IncDecIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x23) fprintf(fp, " inc word [_z80%s] ; Increment our mz80Index register\n", mz80Index); else fprintf(fp, " dec word [_z80%s] ; Increment our mz80Index register\n", mz80Index); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x23 == dwOpcode) { fprintf(fp, " %s++;\n", mz80Index); } else { fprintf(fp, " %s--;\n", mz80Index); } fprintf(fp, " %s &= 0xffff;\n", mz80Index); } else assert(0); } void LdRegIndexOffset(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = (dwOpcode & 0x38) >> 3; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); ReadValueFromMemory("dx", pbMathReg[dwOpcode1]); fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); dwGlobalLabel++; FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; // Get the offset\n"); fprintf(fp, " sdwAddr = ((INT32) %s + sdwAddr) & 0xffff;\n", mz80Index); ReadValueFromMemory("sdwAddr", pbMathRegC[dwOpcode1]); } else assert(0); } void LdByteToIndex(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address\n"); fprintf(fp, " add esi, 2 ; Skip over our storage bytes\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, dx ; Store it here for later\n"); fprintf(fp, " xor dh, dh\n"); fprintf(fp, " or dl, dl\n"); fprintf(fp, " jns noNegate%ld\n", dwGlobalLabel); fprintf(fp, " dec dh\n"); fprintf(fp, "noNegate%ld:\n", dwGlobalLabel); fprintf(fp, " add dx, [_z80%s] ; Add in our index\n", mz80Index); fprintf(fp, " mov [_orgval], dx ; Store our address to write to\n"); fprintf(fp, " mov dx, di\n"); fprintf(fp, " xchg dh, dl\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); ++dwGlobalLabel; FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; // Get the offset\n"); fprintf(fp, " sdwAddr = ((INT32) %s + sdwAddr) & 0xffff;\n", mz80Index); WriteValueToMemory("sdwAddr", "*pbPC++"); } else assert(0); } void SPToIndex(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [_z80%s] ; Get our source register\n", mz80Index); fprintf(fp, " mov word [_z80sp], dx ; Store our new SP\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80sp = %s;\n", mz80Index); } else assert(0); } void AddIndexHandler(UINT32 dwOpcode) { UINT8 bRegPair; bRegPair = dwOpcode >> 4; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " and dh, 0ech ; Preserve the top three and bits 2 & 3\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, [_z80%s] ; Get our value\n", mz80Index); fprintf(fp, " mov [_orgval], di ; Store our original value\n"); fprintf(fp, " add di, %s\n", pbIndexedRegPairs[(dwOpcode & 0x30) >> 4]); fprintf(fp, " lahf\n"); fprintf(fp, " mov [_z80%s], di ; Store our register back\n", mz80Index); fprintf(fp, " mov di, [_orgval] ; Get original\n"); fprintf(fp, " xor di, word [_z80%s] ; XOR It with our computed value\n", mz80Index); fprintf(fp, " xor di, %s\n", pbIndexedRegPairs[(dwOpcode & 0x30) >> 4]); fprintf(fp, " and di, 1000h ; Just our half carry\n"); fprintf(fp, " or dx, di ; Or in our flags\n"); fprintf(fp, " and ah, 01h ; Just carry\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (bRegPair != 2) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " dwTemp = %s + %s;\n", mz80Index, pbRegPairsC[bRegPair]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((%s ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", mz80Index, pbRegPairsC[bRegPair]); fprintf(fp, " %s = dwTemp & 0xffff;\n", mz80Index); } else { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " dwTemp = %s + %s;\n", mz80Index, mz80Index); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((%s ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", mz80Index, pbRegPairsC[bRegPair]); fprintf(fp, " %s = dwTemp & 0xffff;\n", mz80Index); } } else assert(0); } void JPIXIYHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [_z80%s] ; Get our value\n", mz80Index); fprintf(fp, " mov esi, edx ; New PC!\n"); fprintf(fp, " add esi, ebp ; Add in our base\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " pbPC = cpu.z80Base + %s;\n", mz80Index); } else assert(0); } void IncDecIndexed(UINT32 dwOpcode) { UINT8 szIndex[30]; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); fprintf(fp, " mov [_orgval], dx\n"); ReadValueFromMemory("dx", "dl"); fprintf(fp, " sahf\n"); if (dwOpcode == 0x34) fprintf(fp, " inc dl\n"); else fprintf(fp, " dec dl\n"); fprintf(fp, " lahf\n"); fprintf(fp, " o16 pushf\n"); fprintf(fp, " shl edx, 16\n"); fprintf(fp, " and ah, 0fbh ; Knock out parity/overflow\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " and dh, 08h ; Just the overflow\n"); fprintf(fp, " shr dh, 1 ; Shift it into position\n"); fprintf(fp, " or ah, dh ; OR It in with the real flags\n"); fprintf(fp, " shr edx, 16\n"); if (dwOpcode == 0x34) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); else fprintf(fp, " or ah, 02h ; Make it N!\n"); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr = (sdwAddr + (INT32) %s) & 0xffff;\n", mz80Index); ReadValueFromMemory("dwAddr", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); if (0x34 == dwOpcode) { fprintf(fp ," cpu.z80F |= bPostIncFlags[bTemp++];\n"); } else { fprintf(fp ," cpu.z80F |= bPostDecFlags[bTemp--];\n"); } WriteValueToMemory("dwAddr", "bTemp"); } else assert(0); } void MathOperationIndexed(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); ReadValueFromMemory("dx", "dl"); fprintf(fp, " sahf\n"); if (dwOpcode == 0x86) // Add fprintf(fp, " add al, dl\n"); if (dwOpcode == 0x8e) // Adc fprintf(fp, " adc al, dl\n"); if (dwOpcode == 0x96) // Sub fprintf(fp, " sub al, dl\n"); if (dwOpcode == 0x9e) // Sbc fprintf(fp, " sbb al, dl\n"); if (dwOpcode == 0xa6) // And fprintf(fp, " and al, dl\n"); if (dwOpcode == 0xae) // Xor fprintf(fp, " xor al, dl\n"); if (dwOpcode == 0xb6) // Or fprintf(fp, " or al, dl\n"); if (dwOpcode == 0xbe) // Cp fprintf(fp, " cmp al, dl\n"); fprintf(fp, " lahf\n"); if (dwOpcode == 0x86 || dwOpcode == 0x8e) { SetOverflow(); fprintf(fp, " and ah, 0fdh ; Knock out negative\n"); } if (dwOpcode == 0x96 || dwOpcode == 0x9e || dwOpcode == 0xbe) { SetOverflow(); fprintf(fp, " or ah, 02h ; Set negative\n"); } if (dwOpcode == 0xae || dwOpcode == 0xb6) fprintf(fp, " and ah, 0ech ; Knock out H, N, and C\n"); if (dwOpcode == 0xa6) { fprintf(fp, " and ah,0fch ; Knock out N & C\n"); fprintf(fp, " or ah, 10h ; Set half carry\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr = (sdwAddr + (INT32) %s) & 0xffff;\n", mz80Index); ReadValueFromMemory("dwAddr", "bTemp"); if (0x86 == dwOpcode) // ADD A, (IX/IY+nn) { SetAddFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp;\n"); } else if (0x8e == dwOpcode) // ADC A, (IX/IY+nn) { fprintf(fp, " bTemp2 = (cpu.z80F & Z80_FLAG_CARRY);\n"); SetAdcFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp + bTemp2;\n"); } else if (0x96 == dwOpcode) // SUB A, (IX/IY+nn) { SetSubFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A -= bTemp;\n"); } else if (0x9e == dwOpcode) // SBC A, (IX/IY+nn) { fprintf(fp, " bTemp2 = cpu.z80A;\n"); fprintf(fp, " cpu.z80A = cpu.z80A - bTemp - (cpu.z80F & Z80_FLAG_CARRY);\n"); SetSbcFlagsSZHVC("bTemp2", "bTemp"); } else if (0xa6 == dwOpcode) // AND A, (IX/IY+nn) { fprintf(fp, " cpu.z80A &= bTemp;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } else if (0xae == dwOpcode) // XOR A, (IX/IY+nn) { fprintf(fp, " cpu.z80A ^= bTemp;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xb6 == dwOpcode) // OR A, (IX/IY+nn) { fprintf(fp, " cpu.z80A |= bTemp;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xbe == dwOpcode) // CP A, (IX/IY+nn) { SetSubFlagsSZHVC("cpu.z80A", "bTemp"); } else InvalidInstructionC(2); } else assert(0); } void UndocIndexToReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x07) == 2 || (dwOpcode & 0x07) == 3) fprintf(fp, " mov dx, [_z80de] ; Get DE\n"); if ((dwOpcode & 0x07) == 4) fprintf(fp, " mov dh, byte [_z80%s + 1]\n", mz80Index); if ((dwOpcode & 0x07) == 5) fprintf(fp, " mov dl, byte [_z80%s]\n", mz80Index); fprintf(fp, " mov byte [_z80%s + %ld], %s\n", mz80Index, 1 - ((dwOpcode & 0x08) >> 3), pbLocalReg[dwOpcode & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode != 0x64 && dwOpcode != 0x65 && dwOpcode != 0x6c && dwOpcode != 0x6d) { if (dwOpcode & 0x08) fprintf(fp, " %s = %s;\n", mz80IndexHalfLow, pbLocalRegC[dwOpcode & 0x07]); else fprintf(fp, " %s = %s;\n", mz80IndexHalfHigh, pbLocalRegC[dwOpcode & 0x07]); } else // IX/IY High/low weirdness afoot... { // We don't generate any code for ld indexH, indexH and ld indexL, indexL if (0x65 == dwOpcode) // LD indexH, indexL { fprintf(fp, " %s = %s;\n", mz80IndexHalfHigh, mz80IndexHalfLow); } else if (0x6c == dwOpcode) // LD indexH, indexL { fprintf(fp, " %s = %s;\n", mz80IndexHalfLow, mz80IndexHalfHigh); } } } else assert(0); } void UndocRegToIndex(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x38) == 0x10 || (dwOpcode & 0x38) == 0x18) fprintf(fp, " mov dx, [_z80de] ; Get a usable copy of DE here\n"); fprintf(fp, " mov %s, byte [_z80%s + %ld]\n", pbLocalReg[(dwOpcode >> 3) & 0x07], mz80Index, 1 - (dwOpcode & 1)); if ((dwOpcode & 0x38) == 0x10 || (dwOpcode & 0x38) == 0x18) fprintf(fp, " mov [_z80de], dx ; Put it back!\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode & 1) fprintf(fp, " %s = %s;\n", pbLocalRegC[(dwOpcode >> 3) & 0x07], mz80IndexHalfLow); else fprintf(fp, " %s = %s;\n", pbLocalRegC[(dwOpcode >> 3) & 0x07], mz80IndexHalfHigh); } else assert(0); } void LoadImmediate(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our word to load\n"); fprintf(fp, " add esi, 2 ; Advance past the word\n"); fprintf(fp, " mov [_z80%s], dx ; Store our new value\n", mz80Index); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " %s = *pbPC++;\n", mz80Index); fprintf(fp, " %s |= ((UINT32) *pbPC++ << 8);\n", mz80Index); } else assert(0); } void PushPopOperationsIndexed(UINT32 dwOpcode) { UINT8 bRegPair; UINT8 bRegBaseLsb[25]; UINT8 bRegBaseMsb[25]; UINT8 string[150]; if (MZ80_ASSEMBLY_X86 == bWhat) { sprintf(bRegBaseLsb, "byte [_z80%s]", mz80Index); sprintf(bRegBaseMsb, "byte [_z80%s + 1]", mz80Index); sprintf(string, "[_z80%s]", mz80Index); ProcBegin(dwOpcode); if (dwOpcode == 0xe5) // Push IX/IY { fprintf(fp, " sub word [_z80sp], 2\n"); fprintf(fp, " mov dx, [_z80sp]\n"); WriteWordToMemory("dx", string); } else // Pop { fprintf(fp, " mov dx, [_z80sp]\n"); ReadWordFromMemory("dx", string); fprintf(fp, " add word [_z80sp], 2\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xe5 == dwOpcode) // Push IX/IY { fprintf(fp, " cpu.z80sp -= 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); WriteWordToMemory("cpu.z80sp", mz80Index); } else if (0xe1 == dwOpcode) // Pop IX/IY { ReadWordFromMemory("cpu.z80sp", mz80Index); fprintf(fp, " cpu.z80sp += 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); return; } } else assert(0); } // DDFD XXCB Instructions void ddcbBitWise(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); // NOTE: _orgval contains the address to get from. It includes the offset // already computed plus the mz80Index register. // Read our byte fprintf(fp, " mov dx, [_orgval] ; Get our target address\n"); ReadValueFromMemory("dx", "dl"); // Do the operation if (dwOpcode != 0x06 && dwOpcode != 0x0e && dwOpcode != 0x16 && dwOpcode != 0x1e && dwOpcode != 0x26 && dwOpcode != 0x2e && dwOpcode != 0x3e && (dwOpcode & 0xc7) != 0x86 && (dwOpcode & 0xc7) != 0xc6) { fprintf(fp, " mov dh, ah ; Store our original flags\n"); fprintf(fp, " and dh, 29h ; Keep our old flags\n"); } if ((dwOpcode & 0xc7) != 0x86 && (dwOpcode & 0xc7) != 0xc6) fprintf(fp, " sahf ; Restore our flags\n"); if (dwOpcode == 0x06) fprintf(fp, " rol dl, 1\n"); if (dwOpcode == 0x0e) fprintf(fp, " ror dl, 1\n"); if (dwOpcode == 0x16) fprintf(fp, " rcl dl, 1\n"); if (dwOpcode == 0x1e) fprintf(fp, " rcr dl, 1\n"); if (dwOpcode == 0x26) fprintf(fp, " shl dl, 1\n"); if (dwOpcode == 0x2e) fprintf(fp, " sar dl, 1\n"); if (dwOpcode == 0x3e) fprintf(fp, " shr dl, 1\n"); // BIT, AND, and OR if ((dwOpcode & 0xc7) == 0x46) fprintf(fp, " test dl, 0%.2xh ; Is it set?\n", (1 << ((dwOpcode >> 3) & 0x07))); else if ((dwOpcode & 0xc7) == 0x86) fprintf(fp, " and dl, 0%.2xh ; Reset the bit\n", 0xff - (1 << ((dwOpcode >> 3) & 0x07))); else if ((dwOpcode & 0xc7) == 0xc6) fprintf(fp, " or dl, 0%.2xh ; Set the bit\n", (1 << ((dwOpcode >> 3) & 0x07))); if ((dwOpcode & 0xc7) != 0x86 && (dwOpcode & 0xc7) != 0xc6) fprintf(fp, " lahf ; Get our flags back\n"); // Do the flag fixup (if any) if (dwOpcode == 0x26 || dwOpcode == 0x2e || ((dwOpcode & 0xc7) == 0x46)) fprintf(fp, " and ah, 0edh ; No Half carry or negative!\n"); if (dwOpcode == 0x06 || dwOpcode == 0x0e || dwOpcode == 0x16 || dwOpcode == 0x1e || dwOpcode == 0x3e) fprintf(fp, " and ah, 0edh ; Knock out H & N\n"); // BIT! if ((dwOpcode & 0xc7) == 0x46) { fprintf(fp, " or ah, 10h ; OR In our half carry\n"); fprintf(fp, " and ah, 0d0h ; New flags\n"); fprintf(fp, " or ah, dh ; OR In our old flags\n"); } // Now write our data back if it's not a BIT instruction if ((dwOpcode & 0xc7) != 0x46) // If it's not a BIT, write it back WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x06 == dwOpcode) // RLC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp2 = (bTemp >> 7);\n"); fprintf(fp, " bTemp = (bTemp << 1) | bTemp2;\n"); fprintf(fp, " cpu.z80F |= bTemp2 | bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x0e == dwOpcode) // RRC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1) | (bTemp << 7);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x16 == dwOpcode) // RL { fprintf(fp, " bTemp2 = cpu.z80F & Z80_FLAG_CARRY;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp >> 7);\n"); fprintf(fp, " bTemp = (bTemp << 1) | bTemp2;\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x1e == dwOpcode) // RR { fprintf(fp, " bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1) | bTemp2;\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x26 == dwOpcode) // SLA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp >> 7);\n"); fprintf(fp, " bTemp = (bTemp << 1);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x2e == dwOpcode) // SRA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1) | (bTemp & 0x80);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x3e == dwOpcode) // SRL { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if ((dwOpcode & 0xc0) == 0x40) // BIT { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY;\n"); fprintf(fp, " if (!(bTemp & 0x%.2x))\n", 1 << ((dwOpcode >> 3) & 0x07)); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); } else if ((dwOpcode & 0xc0) == 0x80) // RES { fprintf(fp, " bTemp &= 0x%.2x;\n", ~(1 << ((dwOpcode >> 3) & 0x07)) & 0xff); WriteValueToMemory("dwAddr", "bTemp"); } else if ((dwOpcode & 0xc0) == 0xC0) // SET { fprintf(fp, " bTemp |= 0x%.2x;\n", 1 << ((dwOpcode >> 3) & 0x07)); WriteValueToMemory("dwAddr", "bTemp"); } else InvalidInstructionC(4); } else assert(0); } GetTicksCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sGetElapsedTicks\n", cpubasename); fprintf(fp, " global %sGetElapsedTicks_\n", cpubasename); fprintf(fp, " global %sGetElapsedTicks\n", cpubasename); Alignment(); sprintf(procname, "%sGetElapsedTicks_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetElapsedTicks:\n", cpubasename); fprintf(fp, "%sGetElapsedTicks:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our context address\n"); fprintf(fp, " or eax, eax ; Should we clear it?\n"); fprintf(fp, " jz getTicks\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " xchg eax, [dwElapsedTicks]\n"); fprintf(fp, " ret\n"); fprintf(fp, "getTicks:\n"); fprintf(fp, " mov eax, [dwElapsedTicks]\n"); fprintf(fp, " ret\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* This will return the elapsed ticks */\n\n"); fprintf(fp, "UINT32 %sGetElapsedTicks(UINT32 dwClear)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " UINT32 dwTemp = dwElapsedTicks;\n\n"); fprintf(fp, " if (dwClear)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks = 0;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " return(dwTemp);\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } ReleaseTimesliceCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sReleaseTimeslice\n", cpubasename); fprintf(fp, " global %sReleaseTimeslice_\n", cpubasename); fprintf(fp, " global %sReleaseTimeslice\n", cpubasename); Alignment(); sprintf(procname, "%sReleaseTimeslice_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sReleaseTimeslice:\n", cpubasename); fprintf(fp, "%sReleaseTimeslice:\n", cpubasename); fprintf(fp, " mov eax, [cyclesRemaining]\n"); fprintf(fp, " sub [dwOriginalExec], eax\n"); fprintf(fp, " mov [cyclesRemaining], dword 0\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Releases mz80 from its current timeslice */\n\n"); fprintf(fp, "void %sReleaseTimeslice(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " dwOriginalCycles -= sdwCyclesRemaining;\n"); fprintf(fp, " sdwCyclesRemaining = 0;\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } DataSegment() { UINT32 dwLoop = 0; UINT8 bUsed[256]; if (MZ80_ASSEMBLY_X86 == bWhat) { if (bOS2) fprintf(fp, " section .DATA32 use32 flat class=data\n"); else fprintf(fp, " section .data use32 flat class=data\n"); Alignment(); fprintf(fp, " global _%scontextBegin\n", cpubasename); fprintf(fp, "_%scontextBegin:\n", cpubasename); fprintf(fp, " global _z80pc\n"); fprintf(fp, " global z80pc_\n"); if (bPlain) fprintf(fp, " global z80pc\n"); fprintf(fp, " global _z80nmiAddr\n"); fprintf(fp, " global _z80intAddr\n"); fprintf(fp, " global z80intAddr\n"); fprintf(fp, "\n"); fprintf(fp, "; DO NOT CHANGE THE ORDER OF AF, BC, DE, HL and THE PRIME REGISTERS!\n"); fprintf(fp, "\n"); fprintf(fp, "_z80Base dd 0 ; Base address for Z80 stuff\n"); fprintf(fp, "_z80MemRead dd 0 ; Offset of memory read structure array\n"); fprintf(fp, "_z80MemWrite dd 0 ; Offset of memory write structure array\n"); fprintf(fp, "_z80IoRead dd 0 ; Base address for I/O reads list\n"); fprintf(fp, "_z80IoWrite dd 0 ; Base address for I/O write list\n"); fprintf(fp, "_z80clockticks dd 0 ; # Of clock tips that have elapsed\n"); fprintf(fp, "_z80iff dd 0 ; Non-zero if we're in an interrupt\n"); fprintf(fp, "_z80interruptMode dd 0 ; Interrupt mode\n"); fprintf(fp, "_z80halted dd 0 ; 0=Not halted, 1=Halted\n"); #ifdef MZ80_TRAP fprintf(fp, "_z80trapList dd 0 ; pointer to trap list\n"); fprintf(fp, "_z80trapAddr dw 0 ; PC where trap occurred\n"); #endif fprintf(fp, "_z80af dd 0 ; A Flag & Flags\n"); fprintf(fp, "_z80bc dd 0 ; BC\n"); fprintf(fp, "_z80de dd 0 ; DE\n"); fprintf(fp, "_z80hl dd 0 ; HL\n"); fprintf(fp, "_z80afprime dd 0 ; A Flag & Flags prime\n"); fprintf(fp, "_z80bcprime dd 0 ; BC prime\n"); fprintf(fp, "_z80deprime dd 0 ; DE prime\n"); fprintf(fp, "_z80hlprime dd 0 ; HL prime\n"); fprintf(fp, "\n"); fprintf(fp, "; The order of the following registers can be changed without adverse\n"); fprintf(fp, "; effect. Keep the WORD and DWORDs on boundaries of two for faster access\n"); fprintf(fp, "\n"); fprintf(fp, "_z80ix dd 0 ; IX\n"); fprintf(fp, "_z80iy dd 0 ; IY\n"); fprintf(fp, "_z80sp dd 0 ; Stack pointer\n"); if (bPlain) fprintf(fp,"z80pc:\n"); fprintf(fp, "z80pc_:\n"); fprintf(fp, "_z80pc dd 0 ; PC\n"); fprintf(fp, "_z80nmiAddr dd 0 ; Address to jump to for NMI\n"); fprintf(fp, "z80intAddr:\n"); fprintf(fp, "_z80intAddr dd 0 ; Address to jump to for INT\n"); fprintf(fp, "_z80rCounter dd 0 ; R Register counter\n"); fprintf(fp, "_z80i db 0 ; I register\n"); fprintf(fp, "_z80r db 0 ; R register\n"); fprintf(fp, "_z80intPending db 0 ; Non-zero if an interrupt is pending\n"); fprintf(fp, "\n"); fprintf(fp, "_%scontextEnd:\n", cpubasename); Alignment(); fprintf(fp, "dwElapsedTicks dd 0 ; # Of ticks elapsed\n"); fprintf(fp, "cyclesRemaining dd 0 ; # Of cycles remaining\n"); fprintf(fp, "dwOriginalExec dd 0 ; # Of cycles originally executing\n"); fprintf(fp, "dwLastRSample dd 0 ; Last sample for R computation\n"); fprintf(fp, "dwEITiming dd 0 ; Used when we cause an interrupt\n"); fprintf(fp, "_orgval dw 0 ; Scratch area\n"); fprintf(fp, "_orgval2 dw 0 ; Scratch area\n"); fprintf(fp, "_wordval dw 0 ; Scratch area\n"); fprintf(fp, "_intData db 0 ; Interrupt data when an interrupt is pending\n"); fprintf(fp, "bEIExit db 0 ; Are we exiting because of an EI instruction?\n"); fprintf(fp, "\n"); // Debugger junk fprintf(fp, "RegTextPC db 'PC',0\n"); fprintf(fp, "RegTextAF db 'AF',0\n"); fprintf(fp, "RegTextBC db 'BC',0\n"); fprintf(fp, "RegTextDE db 'DE',0\n"); fprintf(fp, "RegTextHL db 'HL',0\n"); fprintf(fp, "RegTextAFP db 'AF',27h,0\n"); fprintf(fp, "RegTextBCP db 'BC',27h,0\n"); fprintf(fp, "RegTextDEP db 'DE',27h,0\n"); fprintf(fp, "RegTextHLP db 'HL',27h,0\n"); fprintf(fp, "RegTextIX db 'IX',0\n"); fprintf(fp, "RegTextIY db 'IY',0\n"); fprintf(fp, "RegTextSP db 'SP',0\n"); fprintf(fp, "RegTextI db 'I',0\n"); fprintf(fp, "RegTextR db 'R',0\n"); // 8 Byte textual info fprintf(fp, "RegTextA db 'A',0\n"); fprintf(fp, "RegTextB db 'B',0\n"); fprintf(fp, "RegTextC db 'C',0\n"); fprintf(fp, "RegTextD db 'D',0\n"); fprintf(fp, "RegTextE db 'E',0\n"); fprintf(fp, "RegTextH db 'H',0\n"); fprintf(fp, "RegTextL db 'L',0\n"); fprintf(fp, "RegTextF db 'F',0\n"); // Individual flags fprintf(fp, "RegTextCarry db 'Carry',0\n"); fprintf(fp, "RegTextNegative db 'Negative',0\n"); fprintf(fp, "RegTextParity db 'Parity',0\n"); fprintf(fp, "RegTextOverflow db 'Overflow',0\n"); fprintf(fp, "RegTextHalfCarry db 'HalfCarry',0\n"); fprintf(fp, "RegTextZero db 'Zero',0\n"); fprintf(fp, "RegTextSign db 'Sign',0\n"); fprintf(fp, "RegTextIFF1 db 'IFF1',0\n"); fprintf(fp, "RegTextIFF2 db 'IFF2',0\n\n"); // Timing for interrupt modes fprintf(fp, "intModeTStates:\n"); fprintf(fp, " db 13 ; IM 0 - 13 T-States\n"); fprintf(fp, " db 11 ; IM 1 - 11 T-States\n"); fprintf(fp, " db 11 ; IM 2 - 11 T-States\n\n"); // Now the master reg/flag table fprintf(fp, "\n;\n"); fprintf(fp, "; Info is in: pointer to text, address, shift value, mask value, size of data chunk\n"); fprintf(fp, ";\n\n"); fprintf(fp, "RegTable:\n"); // Pointer to text, address, shift value, mask, size fprintf(fp, " dd RegTextPC, _z80pc - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextSP, _z80sp - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextAF, _z80af - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextBC, _z80bc - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextDE, _z80de - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextHL, _z80hl - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextAFP, _z80af - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextBCP, _z80bc - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextDEP, _z80de - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextHLP, _z80hl - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextIX, _z80ix - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextIY, _z80iy - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextI, _z80i - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextR, _z80r - _%scontextBegin, 0, 0ffh\n", cpubasename); // Individual regs fprintf(fp, " dd RegTextA, (_z80af + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextF, _z80af - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextB, (_z80bc + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextC, _z80bc - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextD, (_z80de + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextE, _z80de - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextH, (_z80hl + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextL, _z80hl - _%scontextBegin, 0, 0ffh\n", cpubasename); // IFF register fprintf(fp, " dd RegTextIFF1, _z80iff - _%scontextBegin, 0, 01h\n", cpubasename); fprintf(fp, " dd RegTextIFF2, _z80iff - _%scontextBegin, 1, 01h\n", cpubasename); // Individual flags fprintf(fp, " dd RegTextCarry, _z80af - _%scontextBegin, 0, 01h\n", cpubasename); fprintf(fp, " dd RegTextNegative, _z80af - _%scontextBegin, 1, 01h\n", cpubasename); fprintf(fp, " dd RegTextParity, _z80af - _%scontextBegin, 2, 01h\n", cpubasename); fprintf(fp, " dd RegTextOverflow, _z80af - _%scontextBegin, 2, 01h\n", cpubasename); fprintf(fp, " dd RegTextHalfCarry, _z80af - _%scontextBegin, 4, 01h\n", cpubasename); fprintf(fp, " dd RegTextZero, _z80af - _%scontextBegin, 6, 01h\n", cpubasename); fprintf(fp, " dd RegTextSign, _z80af - _%scontextBegin, 7, 01h\n", cpubasename); // Now we write out our tables Alignment(); for (dwLoop = 0; dwLoop < 256; dwLoop++) bUsed[dwLoop] = 0; // Now rip through and find out what is and isn't used dwLoop = 0; while (StandardOps[dwLoop].Emitter) { assert(StandardOps[dwLoop].bOpCode < 0x100); if (bUsed[StandardOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[StandardOps[dwLoop].bOpCode] = 1; dwLoop++; } // Now that that's taken care of, emit the table fprintf(fp, "z80regular:\n"); dwLoop = 0; while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "RegInst%.2x", dwLoop); else fprintf(fp, "invalidInsByte"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (CB Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (CBOps[dwLoop].Emitter) { assert(CBOps[dwLoop].bOpCode < 0x100); if (bUsed[CBOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops CB! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[CBOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the CB prefixes fprintf(fp, "z80PrefixCB:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "CBInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (ED Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (EDOps[dwLoop].Emitter) { assert(EDOps[dwLoop].bOpCode < 0x100); if (bUsed[EDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops ED! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[EDOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the ED prefixes fprintf(fp, "z80PrefixED:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "EDInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (DD Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDOps[dwLoop].Emitter) { assert(DDFDOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops DD! %.2x\n", bUsed[DDFDOps[dwLoop].bOpCode]); fclose(fp); exit(1); } bUsed[DDFDOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the DD prefixes fprintf(fp, "z80PrefixDD:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "DDInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (FD Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDOps[dwLoop].Emitter) { assert(DDFDOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops FD! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[DDFDOps[dwLoop].bOpCode] = 1; dwLoop++; } for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; // Let's emit the DDFD prefixes for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDOps[dwLoop].Emitter) { assert(DDFDOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops FD! %.2x\n", dwLoop); exit(1); } bUsed[DDFDOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the DDFD prefixes fprintf(fp, "z80PrefixFD:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "FDInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDCBOps[dwLoop].Emitter) { assert(DDFDCBOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDCBOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops CBFDDD! %.2x\n", bUsed[DDFDCBOps[dwLoop].bOpCode]); fclose(fp); exit(1); } bUsed[DDFDCBOps[dwLoop].bOpCode] = 1; dwLoop++; } // Let's emit the DDFD prefixes dwLoop = 0; fprintf(fp, "z80ddfdcbInstructions:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "DDFDCBInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Modular global variables go here*/\n\n"); fprintf(fp, "static CONTEXTMZ80 cpu; /* CPU Context */\n"); fprintf(fp, "static UINT8 *pbPC; /* Program counter normalized */\n"); fprintf(fp, "static UINT8 *pbSP; /* Stack pointer normalized */\n"); fprintf(fp, "static struct MemoryReadByte *psMemRead; /* Read memory structure */\n"); fprintf(fp, "static struct MemoryWriteByte *psMemWrite; /* Write memory structure */\n"); fprintf(fp, "static struct z80PortRead *psIoRead; /* Read I/O structure */\n"); fprintf(fp, "static struct z80PortWrite *psIoWrite; /* Write memory structure */\n"); fprintf(fp, "static INT32 sdwCyclesRemaining; /* Used as a countdown */\n"); fprintf(fp, "static UINT32 dwReturnCode; /* Return code from exec() */\n"); fprintf(fp, "static UINT32 dwOriginalCycles; /* How many cycles did we start with? */\n"); fprintf(fp, "static UINT32 dwElapsedTicks; /* How many ticks did we elapse? */\n"); fprintf(fp, "static INT32 sdwAddr; /* Temporary address storage */\n"); fprintf(fp, "static UINT32 dwAddr; /* Temporary stack address */\n"); fprintf(fp, "static UINT8 *pbAddAdcTable; /* Pointer to add/adc flag table */\n"); fprintf(fp, "static UINT8 *pbSubSbcTable; /* Pointer to sub/sbc flag table */\n"); fprintf(fp, "static UINT32 dwTemp; /* Temporary value */\n\n"); fprintf(fp, "static UINT8 bTemp; /* Temporary value */\n\n"); fprintf(fp, "static UINT8 bTemp2; /* Temporary value */\n\n"); fprintf(fp, "/* Precomputed flag tables */\n\n"); fprintf(fp, "static UINT8 bPostIncFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x50\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT8 bPostDecFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x92,0x42,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x16,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT8 bPostORFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT8 bPostANDFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x54,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT16 wDAATable[0x800] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x5400,0x1001,0x1002,0x1403,0x1004,0x1405,0x1406,0x1007,\n"); fprintf(fp, " 0x1008,0x1409,0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,\n"); fprintf(fp, " 0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,0x1016,0x1417,\n"); fprintf(fp, " 0x1418,0x1019,0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,\n"); fprintf(fp, " 0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,0x1026,0x1427,\n"); fprintf(fp, " 0x1428,0x1029,0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,\n"); fprintf(fp, " 0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,0x1436,0x1037,\n"); fprintf(fp, " 0x1038,0x1439,0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,\n"); fprintf(fp, " 0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,0x1046,0x1447,\n"); fprintf(fp, " 0x1448,0x1049,0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,\n"); fprintf(fp, " 0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,0x1456,0x1057,\n"); fprintf(fp, " 0x1058,0x1459,0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,\n"); fprintf(fp, " 0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,0x1466,0x1067,\n"); fprintf(fp, " 0x1068,0x1469,0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,\n"); fprintf(fp, " 0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,0x1076,0x1477,\n"); fprintf(fp, " 0x1478,0x1079,0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,\n"); fprintf(fp, " 0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,0x9086,0x9487,\n"); fprintf(fp, " 0x9488,0x9089,0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,\n"); fprintf(fp, " 0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,0x9496,0x9097,\n"); fprintf(fp, " 0x9098,0x9499,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,0x1506,0x1107,\n"); fprintf(fp, " 0x1108,0x1509,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,0x1116,0x1517,\n"); fprintf(fp, " 0x1518,0x1119,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,0x1126,0x1527,\n"); fprintf(fp, " 0x1528,0x1129,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,0x1536,0x1137,\n"); fprintf(fp, " 0x1138,0x1539,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,0x1146,0x1547,\n"); fprintf(fp, " 0x1548,0x1149,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,0x1556,0x1157,\n"); fprintf(fp, " 0x1158,0x1559,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,0x1566,0x1167,\n"); fprintf(fp, " 0x1168,0x1569,0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,\n"); fprintf(fp, " 0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,0x1176,0x1577,\n"); fprintf(fp, " 0x1578,0x1179,0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,\n"); fprintf(fp, " 0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,0x9186,0x9587,\n"); fprintf(fp, " 0x9588,0x9189,0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,\n"); fprintf(fp, " 0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,0x9596,0x9197,\n"); fprintf(fp, " 0x9198,0x9599,0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,\n"); fprintf(fp, " 0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,0x95a6,0x91a7,\n"); fprintf(fp, " 0x91a8,0x95a9,0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,\n"); fprintf(fp, " 0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,0x91b6,0x95b7,\n"); fprintf(fp, " 0x95b8,0x91b9,0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,\n"); fprintf(fp, " 0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,0x95c6,0x91c7,\n"); fprintf(fp, " 0x91c8,0x95c9,0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,\n"); fprintf(fp, " 0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,0x91d6,0x95d7,\n"); fprintf(fp, " 0x95d8,0x91d9,0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,\n"); fprintf(fp, " 0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,0x91e6,0x95e7,\n"); fprintf(fp, " 0x95e8,0x91e9,0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,\n"); fprintf(fp, " 0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,0x95f6,0x91f7,\n"); fprintf(fp, " 0x91f8,0x95f9,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,0x1506,0x1107,\n"); fprintf(fp, " 0x1108,0x1509,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,0x1116,0x1517,\n"); fprintf(fp, " 0x1518,0x1119,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,0x1126,0x1527,\n"); fprintf(fp, " 0x1528,0x1129,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,0x1536,0x1137,\n"); fprintf(fp, " 0x1138,0x1539,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,0x1146,0x1547,\n"); fprintf(fp, " 0x1548,0x1149,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,0x1556,0x1157,\n"); fprintf(fp, " 0x1158,0x1559,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x1406,0x1007,0x1008,0x1409,0x140a,0x100b,0x140c,0x100d,\n"); fprintf(fp, " 0x100e,0x140f,0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,\n"); fprintf(fp, " 0x1016,0x1417,0x1418,0x1019,0x101a,0x141b,0x101c,0x141d,\n"); fprintf(fp, " 0x141e,0x101f,0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,\n"); fprintf(fp, " 0x1026,0x1427,0x1428,0x1029,0x102a,0x142b,0x102c,0x142d,\n"); fprintf(fp, " 0x142e,0x102f,0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,\n"); fprintf(fp, " 0x1436,0x1037,0x1038,0x1439,0x143a,0x103b,0x143c,0x103d,\n"); fprintf(fp, " 0x103e,0x143f,0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,\n"); fprintf(fp, " 0x1046,0x1447,0x1448,0x1049,0x104a,0x144b,0x104c,0x144d,\n"); fprintf(fp, " 0x144e,0x104f,0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,\n"); fprintf(fp, " 0x1456,0x1057,0x1058,0x1459,0x145a,0x105b,0x145c,0x105d,\n"); fprintf(fp, " 0x105e,0x145f,0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,\n"); fprintf(fp, " 0x1466,0x1067,0x1068,0x1469,0x146a,0x106b,0x146c,0x106d,\n"); fprintf(fp, " 0x106e,0x146f,0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,\n"); fprintf(fp, " 0x1076,0x1477,0x1478,0x1079,0x107a,0x147b,0x107c,0x147d,\n"); fprintf(fp, " 0x147e,0x107f,0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,\n"); fprintf(fp, " 0x9086,0x9487,0x9488,0x9089,0x908a,0x948b,0x908c,0x948d,\n"); fprintf(fp, " 0x948e,0x908f,0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,\n"); fprintf(fp, " 0x9496,0x9097,0x9098,0x9499,0x949a,0x909b,0x949c,0x909d,\n"); fprintf(fp, " 0x909e,0x949f,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x1506,0x1107,0x1108,0x1509,0x150a,0x110b,0x150c,0x110d,\n"); fprintf(fp, " 0x110e,0x150f,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1116,0x1517,0x1518,0x1119,0x111a,0x151b,0x111c,0x151d,\n"); fprintf(fp, " 0x151e,0x111f,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1126,0x1527,0x1528,0x1129,0x112a,0x152b,0x112c,0x152d,\n"); fprintf(fp, " 0x152e,0x112f,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1536,0x1137,0x1138,0x1539,0x153a,0x113b,0x153c,0x113d,\n"); fprintf(fp, " 0x113e,0x153f,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1146,0x1547,0x1548,0x1149,0x114a,0x154b,0x114c,0x154d,\n"); fprintf(fp, " 0x154e,0x114f,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1556,0x1157,0x1158,0x1559,0x155a,0x115b,0x155c,0x115d,\n"); fprintf(fp, " 0x115e,0x155f,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x1566,0x1167,0x1168,0x1569,0x156a,0x116b,0x156c,0x116d,\n"); fprintf(fp, " 0x116e,0x156f,0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,\n"); fprintf(fp, " 0x1176,0x1577,0x1578,0x1179,0x117a,0x157b,0x117c,0x157d,\n"); fprintf(fp, " 0x157e,0x117f,0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,\n"); fprintf(fp, " 0x9186,0x9587,0x9588,0x9189,0x918a,0x958b,0x918c,0x958d,\n"); fprintf(fp, " 0x958e,0x918f,0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,\n"); fprintf(fp, " 0x9596,0x9197,0x9198,0x9599,0x959a,0x919b,0x959c,0x919d,\n"); fprintf(fp, " 0x919e,0x959f,0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,\n"); fprintf(fp, " 0x95a6,0x91a7,0x91a8,0x95a9,0x95aa,0x91ab,0x95ac,0x91ad,\n"); fprintf(fp, " 0x91ae,0x95af,0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,\n"); fprintf(fp, " 0x91b6,0x95b7,0x95b8,0x91b9,0x91ba,0x95bb,0x91bc,0x95bd,\n"); fprintf(fp, " 0x95be,0x91bf,0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,\n"); fprintf(fp, " 0x95c6,0x91c7,0x91c8,0x95c9,0x95ca,0x91cb,0x95cc,0x91cd,\n"); fprintf(fp, " 0x91ce,0x95cf,0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,\n"); fprintf(fp, " 0x91d6,0x95d7,0x95d8,0x91d9,0x91da,0x95db,0x91dc,0x95dd,\n"); fprintf(fp, " 0x95de,0x91df,0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,\n"); fprintf(fp, " 0x91e6,0x95e7,0x95e8,0x91e9,0x91ea,0x95eb,0x91ec,0x95ed,\n"); fprintf(fp, " 0x95ee,0x91ef,0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,\n"); fprintf(fp, " 0x95f6,0x91f7,0x91f8,0x95f9,0x95fa,0x91fb,0x95fc,0x91fd,\n"); fprintf(fp, " 0x91fe,0x95ff,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x1506,0x1107,0x1108,0x1509,0x150a,0x110b,0x150c,0x110d,\n"); fprintf(fp, " 0x110e,0x150f,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1116,0x1517,0x1518,0x1119,0x111a,0x151b,0x111c,0x151d,\n"); fprintf(fp, " 0x151e,0x111f,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1126,0x1527,0x1528,0x1129,0x112a,0x152b,0x112c,0x152d,\n"); fprintf(fp, " 0x152e,0x112f,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1536,0x1137,0x1138,0x1539,0x153a,0x113b,0x153c,0x113d,\n"); fprintf(fp, " 0x113e,0x153f,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1146,0x1547,0x1548,0x1149,0x114a,0x154b,0x114c,0x154d,\n"); fprintf(fp, " 0x154e,0x114f,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1556,0x1157,0x1158,0x1559,0x155a,0x115b,0x155c,0x115d,\n"); fprintf(fp, " 0x115e,0x155f,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x5600,0x1201,0x1202,0x1603,0x1204,0x1605,0x1606,0x1207,\n"); fprintf(fp, " 0x1208,0x1609,0x1204,0x1605,0x1606,0x1207,0x1208,0x1609,\n"); fprintf(fp, " 0x1210,0x1611,0x1612,0x1213,0x1614,0x1215,0x1216,0x1617,\n"); fprintf(fp, " 0x1618,0x1219,0x1614,0x1215,0x1216,0x1617,0x1618,0x1219,\n"); fprintf(fp, " 0x1220,0x1621,0x1622,0x1223,0x1624,0x1225,0x1226,0x1627,\n"); fprintf(fp, " 0x1628,0x1229,0x1624,0x1225,0x1226,0x1627,0x1628,0x1229,\n"); fprintf(fp, " 0x1630,0x1231,0x1232,0x1633,0x1234,0x1635,0x1636,0x1237,\n"); fprintf(fp, " 0x1238,0x1639,0x1234,0x1635,0x1636,0x1237,0x1238,0x1639,\n"); fprintf(fp, " 0x1240,0x1641,0x1642,0x1243,0x1644,0x1245,0x1246,0x1647,\n"); fprintf(fp, " 0x1648,0x1249,0x1644,0x1245,0x1246,0x1647,0x1648,0x1249,\n"); fprintf(fp, " 0x1650,0x1251,0x1252,0x1653,0x1254,0x1655,0x1656,0x1257,\n"); fprintf(fp, " 0x1258,0x1659,0x1254,0x1655,0x1656,0x1257,0x1258,0x1659,\n"); fprintf(fp, " 0x1660,0x1261,0x1262,0x1663,0x1264,0x1665,0x1666,0x1267,\n"); fprintf(fp, " 0x1268,0x1669,0x1264,0x1665,0x1666,0x1267,0x1268,0x1669,\n"); fprintf(fp, " 0x1270,0x1671,0x1672,0x1273,0x1674,0x1275,0x1276,0x1677,\n"); fprintf(fp, " 0x1678,0x1279,0x1674,0x1275,0x1276,0x1677,0x1678,0x1279,\n"); fprintf(fp, " 0x9280,0x9681,0x9682,0x9283,0x9684,0x9285,0x9286,0x9687,\n"); fprintf(fp, " 0x9688,0x9289,0x9684,0x9285,0x9286,0x9687,0x9688,0x9289,\n"); fprintf(fp, " 0x9690,0x9291,0x9292,0x9693,0x9294,0x9695,0x9696,0x9297,\n"); fprintf(fp, " 0x9298,0x9699,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x1340,0x1741,0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,\n"); fprintf(fp, " 0x1748,0x1349,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x1750,0x1351,0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,\n"); fprintf(fp, " 0x1358,0x1759,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x1760,0x1361,0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,\n"); fprintf(fp, " 0x1368,0x1769,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x1370,0x1771,0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,\n"); fprintf(fp, " 0x1778,0x1379,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x9380,0x9781,0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,\n"); fprintf(fp, " 0x9788,0x9389,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x9790,0x9391,0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,\n"); fprintf(fp, " 0x9398,0x9799,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799,\n"); fprintf(fp, " 0x97a0,0x93a1,0x93a2,0x97a3,0x93a4,0x97a5,0x97a6,0x93a7,\n"); fprintf(fp, " 0x93a8,0x97a9,0x93a4,0x97a5,0x97a6,0x93a7,0x93a8,0x97a9,\n"); fprintf(fp, " 0x93b0,0x97b1,0x97b2,0x93b3,0x97b4,0x93b5,0x93b6,0x97b7,\n"); fprintf(fp, " 0x97b8,0x93b9,0x97b4,0x93b5,0x93b6,0x97b7,0x97b8,0x93b9,\n"); fprintf(fp, " 0x97c0,0x93c1,0x93c2,0x97c3,0x93c4,0x97c5,0x97c6,0x93c7,\n"); fprintf(fp, " 0x93c8,0x97c9,0x93c4,0x97c5,0x97c6,0x93c7,0x93c8,0x97c9,\n"); fprintf(fp, " 0x93d0,0x97d1,0x97d2,0x93d3,0x97d4,0x93d5,0x93d6,0x97d7,\n"); fprintf(fp, " 0x97d8,0x93d9,0x97d4,0x93d5,0x93d6,0x97d7,0x97d8,0x93d9,\n"); fprintf(fp, " 0x93e0,0x97e1,0x97e2,0x93e3,0x97e4,0x93e5,0x93e6,0x97e7,\n"); fprintf(fp, " 0x97e8,0x93e9,0x97e4,0x93e5,0x93e6,0x97e7,0x97e8,0x93e9,\n"); fprintf(fp, " 0x97f0,0x93f1,0x93f2,0x97f3,0x93f4,0x97f5,0x97f6,0x93f7,\n"); fprintf(fp, " 0x93f8,0x97f9,0x93f4,0x97f5,0x97f6,0x93f7,0x93f8,0x97f9,\n"); fprintf(fp, " 0x5700,0x1301,0x1302,0x1703,0x1304,0x1705,0x1706,0x1307,\n"); fprintf(fp, " 0x1308,0x1709,0x1304,0x1705,0x1706,0x1307,0x1308,0x1709,\n"); fprintf(fp, " 0x1310,0x1711,0x1712,0x1313,0x1714,0x1315,0x1316,0x1717,\n"); fprintf(fp, " 0x1718,0x1319,0x1714,0x1315,0x1316,0x1717,0x1718,0x1319,\n"); fprintf(fp, " 0x1320,0x1721,0x1722,0x1323,0x1724,0x1325,0x1326,0x1727,\n"); fprintf(fp, " 0x1728,0x1329,0x1724,0x1325,0x1326,0x1727,0x1728,0x1329,\n"); fprintf(fp, " 0x1730,0x1331,0x1332,0x1733,0x1334,0x1735,0x1736,0x1337,\n"); fprintf(fp, " 0x1338,0x1739,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x1340,0x1741,0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,\n"); fprintf(fp, " 0x1748,0x1349,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x1750,0x1351,0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,\n"); fprintf(fp, " 0x1358,0x1759,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x1760,0x1361,0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,\n"); fprintf(fp, " 0x1368,0x1769,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x1370,0x1771,0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,\n"); fprintf(fp, " 0x1778,0x1379,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x9380,0x9781,0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,\n"); fprintf(fp, " 0x9788,0x9389,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x9790,0x9391,0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,\n"); fprintf(fp, " 0x9398,0x9799,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799,\n"); fprintf(fp, " 0x97fa,0x93fb,0x97fc,0x93fd,0x93fe,0x97ff,0x5600,0x1201,\n"); fprintf(fp, " 0x1202,0x1603,0x1204,0x1605,0x1606,0x1207,0x1208,0x1609,\n"); fprintf(fp, " 0x160a,0x120b,0x160c,0x120d,0x120e,0x160f,0x1210,0x1611,\n"); fprintf(fp, " 0x1612,0x1213,0x1614,0x1215,0x1216,0x1617,0x1618,0x1219,\n"); fprintf(fp, " 0x121a,0x161b,0x121c,0x161d,0x161e,0x121f,0x1220,0x1621,\n"); fprintf(fp, " 0x1622,0x1223,0x1624,0x1225,0x1226,0x1627,0x1628,0x1229,\n"); fprintf(fp, " 0x122a,0x162b,0x122c,0x162d,0x162e,0x122f,0x1630,0x1231,\n"); fprintf(fp, " 0x1232,0x1633,0x1234,0x1635,0x1636,0x1237,0x1238,0x1639,\n"); fprintf(fp, " 0x163a,0x123b,0x163c,0x123d,0x123e,0x163f,0x1240,0x1641,\n"); fprintf(fp, " 0x1642,0x1243,0x1644,0x1245,0x1246,0x1647,0x1648,0x1249,\n"); fprintf(fp, " 0x124a,0x164b,0x124c,0x164d,0x164e,0x124f,0x1650,0x1251,\n"); fprintf(fp, " 0x1252,0x1653,0x1254,0x1655,0x1656,0x1257,0x1258,0x1659,\n"); fprintf(fp, " 0x165a,0x125b,0x165c,0x125d,0x125e,0x165f,0x1660,0x1261,\n"); fprintf(fp, " 0x1262,0x1663,0x1264,0x1665,0x1666,0x1267,0x1268,0x1669,\n"); fprintf(fp, " 0x166a,0x126b,0x166c,0x126d,0x126e,0x166f,0x1270,0x1671,\n"); fprintf(fp, " 0x1672,0x1273,0x1674,0x1275,0x1276,0x1677,0x1678,0x1279,\n"); fprintf(fp, " 0x127a,0x167b,0x127c,0x167d,0x167e,0x127f,0x9280,0x9681,\n"); fprintf(fp, " 0x9682,0x9283,0x9684,0x9285,0x9286,0x9687,0x9688,0x9289,\n"); fprintf(fp, " 0x928a,0x968b,0x928c,0x968d,0x968e,0x928f,0x9690,0x9291,\n"); fprintf(fp, " 0x9292,0x9693,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x173a,0x133b,0x173c,0x133d,0x133e,0x173f,0x1340,0x1741,\n"); fprintf(fp, " 0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x134a,0x174b,0x134c,0x174d,0x174e,0x134f,0x1750,0x1351,\n"); fprintf(fp, " 0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x175a,0x135b,0x175c,0x135d,0x135e,0x175f,0x1760,0x1361,\n"); fprintf(fp, " 0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x176a,0x136b,0x176c,0x136d,0x136e,0x176f,0x1370,0x1771,\n"); fprintf(fp, " 0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x137a,0x177b,0x137c,0x177d,0x177e,0x137f,0x9380,0x9781,\n"); fprintf(fp, " 0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x938a,0x978b,0x938c,0x978d,0x978e,0x938f,0x9790,0x9391,\n"); fprintf(fp, " 0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799,\n"); fprintf(fp, " 0x979a,0x939b,0x979c,0x939d,0x939e,0x979f,0x97a0,0x93a1,\n"); fprintf(fp, " 0x93a2,0x97a3,0x93a4,0x97a5,0x97a6,0x93a7,0x93a8,0x97a9,\n"); fprintf(fp, " 0x97aa,0x93ab,0x97ac,0x93ad,0x93ae,0x97af,0x93b0,0x97b1,\n"); fprintf(fp, " 0x97b2,0x93b3,0x97b4,0x93b5,0x93b6,0x97b7,0x97b8,0x93b9,\n"); fprintf(fp, " 0x93ba,0x97bb,0x93bc,0x97bd,0x97be,0x93bf,0x97c0,0x93c1,\n"); fprintf(fp, " 0x93c2,0x97c3,0x93c4,0x97c5,0x97c6,0x93c7,0x93c8,0x97c9,\n"); fprintf(fp, " 0x97ca,0x93cb,0x97cc,0x93cd,0x93ce,0x97cf,0x93d0,0x97d1,\n"); fprintf(fp, " 0x97d2,0x93d3,0x97d4,0x93d5,0x93d6,0x97d7,0x97d8,0x93d9,\n"); fprintf(fp, " 0x93da,0x97db,0x93dc,0x97dd,0x97de,0x93df,0x93e0,0x97e1,\n"); fprintf(fp, " 0x97e2,0x93e3,0x97e4,0x93e5,0x93e6,0x97e7,0x97e8,0x93e9,\n"); fprintf(fp, " 0x93ea,0x97eb,0x93ec,0x97ed,0x97ee,0x93ef,0x97f0,0x93f1,\n"); fprintf(fp, " 0x93f2,0x97f3,0x93f4,0x97f5,0x97f6,0x93f7,0x93f8,0x97f9,\n"); fprintf(fp, " 0x97fa,0x93fb,0x97fc,0x93fd,0x93fe,0x97ff,0x5700,0x1301,\n"); fprintf(fp, " 0x1302,0x1703,0x1304,0x1705,0x1706,0x1307,0x1308,0x1709,\n"); fprintf(fp, " 0x170a,0x130b,0x170c,0x130d,0x130e,0x170f,0x1310,0x1711,\n"); fprintf(fp, " 0x1712,0x1313,0x1714,0x1315,0x1316,0x1717,0x1718,0x1319,\n"); fprintf(fp, " 0x131a,0x171b,0x131c,0x171d,0x171e,0x131f,0x1320,0x1721,\n"); fprintf(fp, " 0x1722,0x1323,0x1724,0x1325,0x1326,0x1727,0x1728,0x1329,\n"); fprintf(fp, " 0x132a,0x172b,0x132c,0x172d,0x172e,0x132f,0x1730,0x1331,\n"); fprintf(fp, " 0x1332,0x1733,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x173a,0x133b,0x173c,0x133d,0x133e,0x173f,0x1340,0x1741,\n"); fprintf(fp, " 0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x134a,0x174b,0x134c,0x174d,0x174e,0x134f,0x1750,0x1351,\n"); fprintf(fp, " 0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x175a,0x135b,0x175c,0x135d,0x135e,0x175f,0x1760,0x1361,\n"); fprintf(fp, " 0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x176a,0x136b,0x176c,0x136d,0x136e,0x176f,0x1370,0x1771,\n"); fprintf(fp, " 0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x137a,0x177b,0x137c,0x177d,0x177e,0x137f,0x9380,0x9781,\n"); fprintf(fp, " 0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x938a,0x978b,0x938c,0x978d,0x978e,0x938f,0x9790,0x9391,\n"); fprintf(fp, " 0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799 \n"); fprintf(fp, "};\n\n"); fprintf(fp, "void DDFDCBHandler(UINT32 dwWhich);\n\n"); fprintf(fp, "\n"); } else { assert(0); } } CodeSegmentBegin() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " section .text use32 flat class=code\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "static void InvalidInstruction(UINT32 dwCount)\n"); fprintf(fp, "{\n"); fprintf(fp, " pbPC -= dwCount; /* Invalid instruction - back up */\n"); fprintf(fp, " dwReturnCode = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " dwOriginalCycles -= sdwCyclesRemaining;\n"); fprintf(fp, " sdwCyclesRemaining = 0;\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } CodeSegmentEnd() { } ProgramEnd() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " end\n"); } else if (MZ80_C == bWhat) { } else { assert(0); } } EmitRegularInstructions() { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_REGULAR; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { dwLoop2 = 0; sprintf(procname, "RegInst%.2x", dwLoop); while (StandardOps[dwLoop2].bOpCode != dwLoop && StandardOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (StandardOps[dwLoop2].Emitter && StandardOps[dwLoop2].bOpCode != 0xffffffff) StandardOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "/* Main execution entry point */\n\n"); fprintf(fp, "UINT32 %sexec(UINT32 dwCycles)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " UINT8 bOpcode;\n\n"); fprintf(fp, " dwReturnCode = 0x80000000; /* Assume it'll work */\n"); fprintf(fp, " sdwCyclesRemaining = dwCycles;\n"); fprintf(fp, " dwOriginalCycles = dwCycles;\n"); fprintf(fp, " if (cpu.z80halted)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks += dwCycles;\n"); fprintf(fp, " return(0x80000000);\n"); fprintf(fp, " }\n\n"); fprintf(fp, " pbPC = cpu.z80Base + cpu.z80pc;\n\n"); fprintf(fp, " while (sdwCyclesRemaining > 0)\n"); fprintf(fp, " {\n"); fprintf(fp, " bOpcode = *pbPC++;\n"); fprintf(fp, " switch (bOpcode)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (StandardOps[dwLoop2].bOpCode != dwLoop && StandardOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingRegular[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %ld;\n", bTimingRegular[dwLoop]); } if (StandardOps[dwLoop2].Emitter) { StandardOps[dwLoop2].Emitter(dwLoop); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, " }\n\n"); fprintf(fp, " dwElapsedTicks += (dwOriginalCycles - sdwCyclesRemaining);\n\n"); fprintf(fp, " cpu.z80pc = (UINT32) pbPC - (UINT32) cpu.z80Base;\n"); fprintf(fp, " return(dwReturnCode); /* Indicate success */\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } EmitCBInstructions() { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_CB; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "CBInst%.2x", dwLoop); dwLoop2 = 0; while (CBOps[dwLoop2].bOpCode != dwLoop && CBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (CBOps[dwLoop2].Emitter && CBOps[dwLoop2].bOpCode != 0xffffffff) CBOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void CBHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (CBOps[dwLoop2].bOpCode != dwLoop && CBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingCB[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %ld;\n", bTimingCB[dwLoop]); } if (CBOps[dwLoop2].Emitter) { CBOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { assert(0); } } EmitEDInstructions() { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_ED; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "EDInst%.2x", dwLoop); dwLoop2 = 0; while (EDOps[dwLoop2].bOpCode != dwLoop && EDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (EDOps[dwLoop2].Emitter && EDOps[dwLoop2].bOpCode != 0xffffffff) EDOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void EDHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (EDOps[dwLoop2].bOpCode != dwLoop && EDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingED[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %ld;\n", bTimingED[dwLoop]); } if (EDOps[dwLoop2].Emitter) { EDOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { assert(0); } fprintf(fp, "\n"); } EmitDDInstructions() { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_DDFD; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "DDInst%.2x", dwLoop); dwLoop2 = 0; while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (DDFDOps[dwLoop2].Emitter && DDFDOps[dwLoop2].bOpCode != 0xffffffff) DDFDOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } bCurrentMode = TIMING_XXCB; dwLoop = 0; while (dwLoop < 0x100) { sprintf(procname, "DDFDCBInst%.2x", dwLoop); dwLoop2 = 0; while (DDFDCBOps[dwLoop2].bOpCode != dwLoop && DDFDCBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (DDFDCBOps[dwLoop2].Emitter && DDFDCBOps[dwLoop2].bOpCode != 0xffffffff) DDFDCBOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void DDHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingDDFD[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %ld;\n", bTimingDDFD[dwLoop]); } if (DDFDOps[dwLoop2].Emitter) { DDFDOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); // DDFD Handler bCurrentMode = TIMING_XXCB; dwLoop = 0; fprintf(fp, "void DDFDCBHandler(UINT32 dwWhich)\n"); fprintf(fp, "{\n"); fprintf(fp, " if (dwWhich)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwAddr = (UINT32) ((INT32) cpu.z80IY + ((INT32) *pbPC++)) & 0xffff;\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " dwAddr = (UINT32) ((INT32) cpu.z80IX + ((INT32) *pbPC++)) & 0xffff;\n"); fprintf(fp, " }\n\n"); ReadValueFromMemory("dwAddr", "bTemp"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (DDFDCBOps[dwLoop2].bOpCode != dwLoop && DDFDCBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingXXCB[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %ld;\n", bTimingXXCB[dwLoop]); } if (DDFDCBOps[dwLoop2].Emitter) { DDFDCBOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(4); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { assert(0); } } EmitFDInstructions() { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_DDFD; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "FDInst%.2x", dwLoop); dwLoop2 = 0; while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (DDFDOps[dwLoop2].Emitter && DDFDOps[dwLoop2].bOpCode != 0xffffffff) DDFDOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void FDHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingDDFD[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %ld;\n", bTimingDDFD[dwLoop]); } if (DDFDOps[dwLoop2].Emitter) { DDFDOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { assert(0); } } /* These are the meta routines */ void ReadMemoryByteHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic read memory byte handler when a foreign\n"); fprintf(fp, "; handler is to be called\n\n"); fprintf(fp, "; EDI=Handler address, EDX=Address\n"); fprintf(fp, "; On return, EDX & EDI are undisturbed and AL=Byte read\n\n"); fprintf(fp, "ReadMemoryByte:\n"); fprintf(fp, " mov [_z80af], ax ; Save AF\n"); fprintf(fp, " cmp [edi+8], dword 0 ; Null handler?\n"); fprintf(fp, " je directReadHandler ; Yep! It's a direct read!\n\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BC\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n", cpubasename); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); fprintf(fp, " push edx ; And our desired address\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, edx ; Get our desired address reg\n"); fprintf(fp, " mov edx, edi ; Pointer to the structure\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); fprintf(fp, " pop edi ; Restore our handler's address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n", cpubasename); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n", cpubasename); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); // Note: the callee must restore AF! fprintf(fp, " ret\n\n"); fprintf(fp, "directReadHandler:\n"); fprintf(fp, " mov eax, [edi+12] ; Get our base address\n"); fprintf(fp, " sub edx, [edi] ; Subtract our base (low) address\n"); fprintf(fp, " mov al, [edx+eax] ; Get our data byte\n"); fprintf(fp, " and eax, 0ffh ; Only the lower byte matters!\n"); fprintf(fp, " add edx, [edi] ; Add our base back\n"); fprintf(fp, " ret ; Return to caller!\n\n"); } else if (MZ80_C == bWhat) { } else { assert(0); } } void WriteMemoryByteHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic read memory byte handler when a foreign\n"); fprintf(fp, "; handler is to be called.\n"); fprintf(fp, "; EDI=Handler address, AL=Byte to write, EDX=Address\n"); fprintf(fp, "; EDI and EDX Are undisturbed on exit\n\n"); fprintf(fp, "WriteMemoryByte:\n"); fprintf(fp, " cmp [edi+8], dword 0 ; Null handler?\n"); fprintf(fp, " je directWriteHandler\n\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BX\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n", cpubasename); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); if (bUseStack) fprintf(fp, " push eax ; Data to write\n"); fprintf(fp, " push edx ; And our desired address\n"); if (FALSE == bUseStack) { fprintf(fp, " xchg eax, edx ; Swap address/data around\n"); fprintf(fp, " mov ebx, edi ; Our MemoryWriteByte structure address\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); if (bUseStack) fprintf(fp, " pop eax ; Restore our data written\n"); fprintf(fp, " pop edi ; Save our structure address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); fprintf(fp, " mov ax, [_z80af] ; Get AF back\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n", cpubasename); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " ret\n\n"); fprintf(fp, "directWriteHandler:\n"); fprintf(fp, " sub edx, [edi] ; Subtract our offset\n"); fprintf(fp, " add edx, [edi+12] ; Add in the base address\n"); fprintf(fp, " mov [edx], al ; Store our byte\n"); fprintf(fp, " sub edx, [edi+12] ; Restore our base address\n"); fprintf(fp, " add edx, [edi] ; And put our offset back\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } else { assert(0); } } void PushWordHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; DX=Top of SP, [_wordval]=word value to push\n"); fprintf(fp, ";\n\n"); fprintf(fp, "PushWord:\n"); fprintf(fp, " mov dx, [_z80sp]\n"); fprintf(fp, " dec dx\n"); WriteValueToMemory("dx", "byte [_wordval+1]"); fprintf(fp, " dec dx\n"); WriteValueToMemory("dx", "byte [_wordval]"); fprintf(fp, " sub [_z80sp], word 2\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " ret\n\n"); } } void PopWordHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; [_z80sp]=Top of SP, DX=Word value read\n"); fprintf(fp, ";\n\n"); fprintf(fp, "PopWord:\n"); fprintf(fp, " mov dx, [_z80sp]\n"); ReadWordFromMemory("dx", "dx"); fprintf(fp, " ret\n\n"); } } void ReadIoHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic I/O read byte handler for when a foreign\n"); fprintf(fp, "; handler is to be called\n"); fprintf(fp, "; EDI=Handler address, EDX=I/O Address\n"); fprintf(fp, "; On return, EDX & EDI are undisturbed and AL=Byte read\n\n"); fprintf(fp, "ReadIOByte:\n"); fprintf(fp, " mov [_z80af], ax ; Save AF\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BC\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n", cpubasename); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); fprintf(fp, " push edx ; And our desired I/O port\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, edx ; Get our desired address reg\n"); fprintf(fp, " mov edx, edi ; Pointer to the structure\n"); } fprintf(fp, " call dword [edi + 4] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); fprintf(fp, " pop edi ; Restore our handler's address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n", cpubasename); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); // Note: the callee must restore AF! fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } else { assert(0); } } void WriteIoHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic write I/O byte handler when a foreign handler is to\n"); fprintf(fp, "; be called\n"); fprintf(fp, "; EDI=Handler address, AL=Byte to write, EDX=I/O Address\n"); fprintf(fp, "; EDI and EDX Are undisturbed on exit\n\n"); fprintf(fp, "WriteIOByte:\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BX\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n", cpubasename); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); if (bUseStack) fprintf(fp, " push eax ; Data to write\n"); fprintf(fp, " push edx ; And our desired I/O address\n"); if (FALSE == bUseStack) { fprintf(fp, " xchg eax, edx ; Swap address/data around\n"); fprintf(fp, " mov ebx, edi ; Our z80IoWrite structure address\n"); } fprintf(fp, " call dword [edi + 4] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); if (bUseStack) fprintf(fp, " pop eax ; Restore our data written\n"); fprintf(fp, " pop edi ; Save our structure address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); fprintf(fp, " mov ax, [_z80af] ; Get AF back\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n", cpubasename); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } else { assert(0); } } ExecCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sexec\n", cpubasename); fprintf(fp, " global %sexec_\n", cpubasename); if (bPlain) fprintf(fp, " global %sexec\n", cpubasename); sprintf(procname, "%sexec_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sexec:\n", cpubasename); if (bPlain) fprintf(fp, "%sexec:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our execution cycle count\n"); fprintf(fp, " push ebx ; Save all registers we use\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ebp\n"); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, "\n"); fprintf(fp, " mov edi, eax\n"); fprintf(fp, " mov dword [cyclesRemaining], eax ; Store # of instructions to\n"); fprintf(fp, " mov [dwLastRSample], eax\n"); fprintf(fp, " mov [dwOriginalExec], eax ; Store this!\n"); fprintf(fp, " cmp dword [_z80halted], 0\n"); fprintf(fp, " je goCpu\n"); fprintf(fp, " add [_z80rCounter], eax\n"); if (FALSE == bNoTiming) { fprintf(fp, " add dword [dwElapsedTicks], eax\n"); } fprintf(fp, " mov dword [cyclesRemaining], 0 ; Nothing left!\n"); fprintf(fp, " mov eax, 80000000h ; Successful exection\n"); fprintf(fp, " jmp popReg\n"); fprintf(fp, "goCpu:\n"); fprintf(fp, " cld ; Go forward!\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Zero EAX 'cause we use it!\n"); fprintf(fp, " xor ebx, ebx ; Zero EBX, too\n"); fprintf(fp, " xor ecx, ecx ; Zero ECX\n"); fprintf(fp, " xor edx, edx ; And EDX\n"); fprintf(fp, " xor esi, esi ; Zero our source address\n"); fprintf(fp, "\n"); fprintf(fp, " mov ax, [_z80af] ; Accumulator & flags\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov bx, [_z80hl] ; Get our HL value\n"); fprintf(fp, " mov cx, [_z80bc] ; And our BC value\n"); fprintf(fp, " mov ebp, [_z80Base] ; Get the base address\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " cmp [_z80intPending], byte 0 ; Interrupt pending?\n"); fprintf(fp, " jz masterExecTarget\n\n"); fprintf(fp, " call causeInternalInterrupt\n\n"); fprintf(fp, "masterExecTarget:\n"); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80regular+edx*4]\n\n"); fprintf(fp, "; We get to invalidInsWord if it's a double byte invalid opcode\n"); fprintf(fp, "\n"); fprintf(fp, "invalidInsWord:\n"); fprintf(fp, " dec esi\n"); fprintf(fp, "\n"); fprintf(fp, "; We get to invalidInsByte if it's a single byte invalid opcode\n"); fprintf(fp, "\n"); fprintf(fp, "invalidInsByte:\n"); fprintf(fp, " xchg ah, al ; Swap them back so they look good\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, " dec esi ; Back up one instruction...\n"); fprintf(fp, " mov edx, esi ; Get our address in EAX\n"); fprintf(fp, " sub edx, ebp ; And subtract our base for\n"); fprintf(fp, " ; an invalid instruction\n"); fprintf(fp, " jmp short emulateEnd\n"); fprintf(fp, "\n"); fprintf(fp, "noMoreExec:\n"); fprintf(fp, " cmp [bEIExit], byte 0 ; Are we exiting because of an EI?\n"); fprintf(fp, " jne checkEI\n"); fprintf(fp, "noMoreExecNoEI:\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, " mov edx, [dwOriginalExec] ; Original exec time\n"); fprintf(fp, " sub edx, edi ; Subtract # of cycles remaining\n"); fprintf(fp, " add [_z80rCounter], edx\n"); fprintf(fp, " add [dwElapsedTicks], edx ; Add our executed time\n"); fprintf(fp, " mov edx, 80000000h ; Indicate successful exec\n"); fprintf(fp, " jmp short emulateEnd ; All finished!\n"); fprintf(fp, "\n"); fprintf(fp, "; Now let's tuck away the virtual registers for next time\n"); fprintf(fp, "\n"); fprintf(fp, "storeFlags:\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, "emulateEnd:\n"); fprintf(fp, " mov [_z80hl], bx ; Store HL\n"); fprintf(fp, " mov [_z80bc], cx ; Store BC\n"); fprintf(fp, " sub esi, [_z80Base] ; Knock off physical address\n"); fprintf(fp, " mov [_z80pc], si ; And store virtual address\n"); fprintf(fp, " mov eax, edx ; Result code return\n"); fprintf(fp, "\n"); fprintf(fp, "popReg:\n"); fprintf(fp, " pop edi ; Restore registers\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, "\n"); fprintf(fp, " ret\n"); fprintf(fp, "\n"); Alignment(); fprintf(fp, "checkEI:\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov [bEIExit], byte 0\n"); fprintf(fp, " sub edx, edi ; Find out how much time has passed\n"); fprintf(fp, " mov edi, [dwEITiming]\n"); fprintf(fp, " sub edi, edx\n"); fprintf(fp, " js noMoreExecNoEI\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " cmp [_z80intPending], byte 0\n"); fprintf(fp, " je near masterExecTarget\n"); fprintf(fp, " call causeInternalInterrupt\n"); fprintf(fp, " jmp masterExecTarget\n\n"); Alignment(); fprintf(fp, "causeInternalInterrupt:\n"); fprintf(fp, " mov dword [_z80halted], 0 ; We're not halted anymore!\n"); fprintf(fp, " test [_z80iff], byte IFF1 ; Interrupt enabled yet?\n"); fprintf(fp, " jz near internalInterruptsDisabled\n"); fprintf(fp, "\n; Interrupts enabled. Clear IFF1 and IFF2\n\n"); fprintf(fp, " mov [_z80intPending], byte 0\n"); fprintf(fp, "\n; Save off our active register sets\n\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, " mov [_z80hl], bx ; Store HL\n"); fprintf(fp, " mov [_z80bc], cx ; Store BC\n"); fprintf(fp, " sub esi, ebp ; Knock off physical address\n"); fprintf(fp, " mov [_z80pc], si ; And store virtual address\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov al, [_intData]\n\n"); fprintf(fp, "\n"); fprintf(fp, " push edi\n"); fprintf(fp, "\n"); if (bThroughCallHandler) { fprintf(fp, " pushad\n" ); fprintf(fp, " xor edx, edx\n" ); fprintf(fp, " mov ax, [_z80pc]\n"); fprintf(fp, " mov [_wordval], ax\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push esi\n"); fprintf(fp, " mov ax, [_z80af]\n"); // Get AF fprintf(fp, " mov bx, [_z80hl]\n"); // Get HL fprintf(fp, " mov cx, [_z80bc]\n"); // Get BC fprintf(fp, " call PushWord\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " popad\n" ); } else { fprintf(fp, " mov dx, [_z80pc]\n"); fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, word [_z80sp]\n"); fprintf(fp, " sub di, 2\n"); fprintf(fp, " mov word [_z80sp], di\n"); fprintf(fp, " mov [ebp+edi], dx\n"); } fprintf(fp, " cmp dword [_z80interruptMode], 2 ; Are we lower than mode 2?\n"); fprintf(fp, " jb internalJustModeTwo\n"); fprintf(fp, " mov ah, [_z80i] ; Get our high address here\n"); fprintf(fp, " and eax, 0ffffh ; Only the lower part\n"); fprintf(fp, " mov ax, [eax+ebp] ; Get our vector\n"); fprintf(fp, " jmp short internalSetNewVector ; Go set it!\n"); fprintf(fp, "internalJustModeTwo:\n"); fprintf(fp, " mov ax, word [_z80intAddr]\n"); fprintf(fp, "internalSetNewVector:\n"); fprintf(fp, " mov [_z80pc], ax\n"); fprintf(fp, "\n"); fprintf(fp, " pop edi\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Zero this so we can use it as an index\n"); fprintf(fp, " mov al, [_z80interruptMode]\n"); fprintf(fp, " mov al, [intModeTStates+eax]\n"); fprintf(fp, " sub edi, eax\n"); fprintf(fp, " add [_z80rCounter], eax\n"); fprintf(fp, "\n; Restore all the registers and whatnot\n\n"); fprintf(fp, " mov ax, [_z80af] ; Accumulator & flags\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov bx, [_z80hl] ; Get our HL value\n"); fprintf(fp, " mov cx, [_z80bc] ; And our BC value\n"); fprintf(fp, " mov ebp, [_z80Base] ; Get the base address\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, "internalInterruptsDisabled:\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " ret\n"); } else if (MZ80_C == bWhat) { } else { assert(0); } } NmiCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%snmi\n", cpubasename); fprintf(fp, " global %snmi_\n", cpubasename); if (bPlain) fprintf(fp, " global %snmi\n", cpubasename); sprintf(procname, "%snmi_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%snmi:\n", cpubasename); if (bPlain) fprintf(fp, "%snmi:\n", cpubasename); fprintf(fp, " mov dword [_z80halted], 0 ; We're not halted anymore!\n"); fprintf(fp, " mov al, [_z80iff] ; Get our IFF setting\n"); fprintf(fp, " and al, IFF1 ; Just IFF 1\n"); fprintf(fp, " shl al, 1 ; Makes IFF1->IFF2 and zeros IFF1\n"); fprintf(fp, " mov [_z80iff], al ; Store it back to the interrupt state!\n"); fprintf(fp, "\n"); fprintf(fp, " push ebp\n"); fprintf(fp, " push edi\n"); fprintf(fp, " mov ebp, [_z80Base]\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov ax, [_z80pc]\n"); if (bThroughCallHandler) { fprintf(fp, " push esi\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " mov [_wordval], ax\n"); fprintf(fp, " mov esi, ebp\n"); fprintf(fp, " add esi, eax\n"); fprintf(fp, " mov ax, [_z80af]\n"); // Get AF fprintf(fp, " mov bx, [_z80hl]\n"); // Get HL fprintf(fp, " mov cx, [_z80bc]\n"); // Get BC fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push esi\n"); fprintf(fp, " push eax\n"); fprintf(fp, " call PushWord\n"); fprintf(fp, " pop eax\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop esi\n"); } else { fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, word [_z80sp]\n"); fprintf(fp, " sub di, 2\n"); fprintf(fp, " mov word [_z80sp], di\n"); fprintf(fp, " mov [ebp+edi], ax\n"); } fprintf(fp, " mov ax, [_z80nmiAddr]\n"); fprintf(fp, " mov [_z80pc], ax\n"); fprintf(fp, "\n"); fprintf(fp, " add [dwElapsedTicks], dword 11 ; 11 T-States for NMI\n"); fprintf(fp, " add [_z80rCounter], dword 11\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Indicate we took the interrupt\n"); fprintf(fp, " ret\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* NMI Handler */\n\n"); fprintf(fp, "UINT32 %snmi(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80halted = 0;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " cpu.z80pc = cpu.z80nmiAddr; /* Our NMI */\n"); fprintf(fp, " return(0);\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } IntCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sint\n", cpubasename); fprintf(fp, " global %sint_\n", cpubasename); if (bPlain) fprintf(fp, " global %sint\n", cpubasename); sprintf(procname, "%sint_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sint:\n", cpubasename); if (bPlain) fprintf(fp, "%sint:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our (potential) lower interrupt address\n"); fprintf(fp, " mov dword [_z80halted], 0 ; We're not halted anymore!\n"); fprintf(fp, " mov ah, IFF1 ; Is IFF1 enabled?\n"); fprintf(fp, " and ah, [_z80iff] ; Well, is it?\n"); fprintf(fp, " jz near interruptsDisabled\n"); fprintf(fp, "\n; Interrupts enabled. Clear IFF1 and IFF2\n\n"); fprintf(fp, " and dword [_z80iff], ~(IFF1 | IFF2);\n\n"); fprintf(fp, " mov [_z80intPending], byte 0\n"); fprintf(fp, "\n"); fprintf(fp, " push ebp\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " mov ebp, [_z80Base]\n"); fprintf(fp, "\n"); if (bThroughCallHandler) { fprintf(fp, " pushad\n" ); fprintf(fp, " xor edx, edx\n" ); fprintf(fp, " mov ax, [_z80pc]\n"); fprintf(fp, " mov [_wordval], ax\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push esi\n"); fprintf(fp, " mov ax, [_z80af]\n"); // Get AF fprintf(fp, " mov bx, [_z80hl]\n"); // Get HL fprintf(fp, " mov cx, [_z80bc]\n"); // Get BC fprintf(fp, " call PushWord\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " popad\n" ); } else { fprintf(fp, " mov dx, [_z80pc]\n"); fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, word [_z80sp]\n"); fprintf(fp, " sub di, 2\n"); fprintf(fp, " mov word [_z80sp], di\n"); fprintf(fp, " mov [ebp+edi], dx\n"); } fprintf(fp, " cmp dword [_z80interruptMode], 2 ; Are we lower than mode 2?\n"); fprintf(fp, " jb justModeTwo\n"); fprintf(fp, " mov ah, [_z80i] ; Get our high address here\n"); fprintf(fp, " and eax, 0ffffh ; Only the lower part\n"); fprintf(fp, " mov ax, [eax+ebp] ; Get our vector\n"); fprintf(fp, " jmp short setNewVector ; Go set it!\n"); fprintf(fp, "justModeTwo:\n"); fprintf(fp, " mov ax, word [_z80intAddr]\n"); fprintf(fp, "setNewVector:\n"); fprintf(fp, " mov [_z80pc], ax\n"); fprintf(fp, "\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Zero this so we can use it as an index\n"); fprintf(fp, " mov al, [_z80interruptMode]\n"); fprintf(fp, " mov al, [intModeTStates+eax]\n"); fprintf(fp, " add [dwElapsedTicks], eax\n"); fprintf(fp, " add [_z80rCounter], eax\n"); fprintf(fp, " xor eax, eax ; Indicate we took the interrupt\n"); fprintf(fp, " jmp short z80intExit\n"); fprintf(fp, "\n"); fprintf(fp, "interruptsDisabled:\n"); fprintf(fp, " mov [_z80intPending], byte 1\n"); fprintf(fp, " mov [_intData], al ; Save this info for later\n"); fprintf(fp, " mov eax, 0ffffffffh ; Indicate we didn't take it\n"); fprintf(fp, "\n"); fprintf(fp, "z80intExit:\n"); fprintf(fp, " ret\n\n"); fprintf(fp, " global _%sClearPendingInterrupt\n", cpubasename); fprintf(fp, " global %sClearPendingInterrupt_\n", cpubasename); if (bPlain) fprintf(fp, " global %sClearPendingInterrupt\n", cpubasename); sprintf(procname, "%sClearPendingInterrupt_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sClearPendingInterrupt:\n", cpubasename); if (bPlain) fprintf(fp, "%sClearPendingInterrupt:\n", cpubasename); fprintf(fp, " mov [_z80intPending], byte 0\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Interrupt handler */\n\n"); fprintf(fp, "UINT32 %sint(UINT32 dwLowAddr)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80halted = 0;\n"); fprintf(fp, " if (0 == (cpu.z80iff & IFF1))\n"); fprintf(fp, " return(0xffffffff);\n"); fprintf(fp, " cpu.z80iff &= ~(IFF1 | IFF2);\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " if (2 == cpu.z80interruptMode)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = ((UINT16) cpu.z80i << 8) | (dwLowAddr & 0xff);\n"); fprintf(fp, " cpu.z80pc = ((UINT16) cpu.z80Base[cpu.z80pc + 1] << 8) | (cpu.z80Base[cpu.z80pc]);\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = cpu.z80intAddr;\n"); fprintf(fp, " }\n"); fprintf(fp, " pbPC = cpu.z80Base + cpu.z80pc; /* Normalize the address */\n"); fprintf(fp, " return(0);\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } ResetCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sreset\n", cpubasename); fprintf(fp, " global %sreset_\n", cpubasename); if (bPlain) fprintf(fp, " global %sreset\n", cpubasename); sprintf(procname, "%sreset_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sreset:\n", cpubasename); if (bPlain) fprintf(fp, "%sreset:\n", cpubasename); fprintf(fp, " xor eax, eax ; Zero AX\n"); fprintf(fp, "\n"); fprintf(fp, " mov dword [_z80halted], eax ; We're not halted anymore!\n"); fprintf(fp, " mov word [_z80af], 0040h ; Zero A & flags - zero flag set\n"); fprintf(fp, " mov word [_z80bc], ax ; Zero BC\n"); fprintf(fp, " mov word [_z80de], ax ; Zero DE\n"); fprintf(fp, " mov word [_z80hl], ax ; Zero HL\n"); fprintf(fp, " mov word [_z80afprime], ax ; Zero AF Prime\n"); fprintf(fp, " mov word [_z80bcprime], ax ; Zero BC prime\n"); fprintf(fp, " mov word [_z80deprime], ax ; Zero DE prime\n"); fprintf(fp, " mov word [_z80hlprime], ax ; Zero HL prime\n"); fprintf(fp, " mov byte [_z80i], al ; Zero Interrupt register\n"); fprintf(fp, " mov byte [_z80r], al ; Zero refresh register\n"); fprintf(fp, " mov word [_z80ix], 0ffffh ; Default mz80Index register\n"); fprintf(fp, " mov word [_z80iy], 0ffffh ; Default mz80Index register\n"); fprintf(fp, " mov word [_z80pc], ax ; Zero program counter\n"); fprintf(fp, " mov word [_z80sp], ax ; And the stack pointer\n"); fprintf(fp, " mov dword [_z80iff], eax ; IFF1/IFF2 disabled!\n"); fprintf(fp, " mov dword [_z80interruptMode], eax ; Clear our interrupt mode (0)\n"); fprintf(fp, " mov word [_z80intAddr], 38h ; Set default interrupt address\n"); fprintf(fp, " mov word [_z80nmiAddr], 66h ; Set default nmi addr\n"); fprintf(fp, "\n"); fprintf(fp, " ret\n"); fprintf(fp, "\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* This routine is mz80's reset handler */\n\n"); fprintf(fp, "void %sreset(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80halted = 0;\n"); fprintf(fp, " cpu.z80AF = 0;\n"); fprintf(fp, " cpu.z80F = Z80_FLAG_ZERO;\n"); fprintf(fp, " cpu.z80BC = 0;\n"); fprintf(fp, " cpu.z80DE = 0;\n"); fprintf(fp, " cpu.z80HL = 0;\n"); fprintf(fp, " cpu.z80afprime = 0;\n"); fprintf(fp, " cpu.z80bcprime = 0;\n"); fprintf(fp, " cpu.z80deprime = 0;\n"); fprintf(fp, " cpu.z80hlprime = 0;\n"); fprintf(fp, " cpu.z80i = 0;\n"); fprintf(fp, " cpu.z80r = 0;\n"); fprintf(fp, " cpu.z80IX = 0xffff; /* Yes, this is intentional */\n"); fprintf(fp, " cpu.z80IY = 0xffff; /* Yes, this is intentional */\n"); fprintf(fp, " cpu.z80pc = 0;\n"); fprintf(fp, " cpu.z80sp = 0;\n"); fprintf(fp, " cpu.z80interruptMode = 0;\n"); fprintf(fp, " cpu.z80intAddr = 0x38;\n"); fprintf(fp, " cpu.z80nmiAddr = 0x66;\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } SetContextCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sSetContext\n", cpubasename); fprintf(fp, " global %sSetContext_\n", cpubasename); if (bPlain) fprintf(fp, " global %sSetContext\n", cpubasename); sprintf(procname, "%sSetContext_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sSetContext:\n", cpubasename); if (bPlain) fprintf(fp, "%sSetContext:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our context address\n"); fprintf(fp, " push esi ; Save registers we use\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push es\n"); fprintf(fp, " mov di, ds\n"); fprintf(fp, " mov es, di\n"); fprintf(fp, " mov edi, _%scontextBegin\n", cpubasename); fprintf(fp, " mov esi, eax ; Source address in ESI\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) >> 2\n", cpubasename, cpubasename); fprintf(fp, " rep movsd\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) & 0x03\n", cpubasename, cpubasename); fprintf(fp, " rep movsb\n"); fprintf(fp, " pop es\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret ; No return code\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Set mz80's context */\n\n"); fprintf(fp, "void %sSetContext(void *pData)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " memcpy(&cpu, pData, sizeof(CONTEXTMZ80));\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } GetContextCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sGetContext\n", cpubasename); fprintf(fp, " global %sGetContext_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetContext\n", cpubasename); sprintf(procname, "%sGetContext_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetContext:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetContext:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our context address\n"); fprintf(fp, " push esi ; Save registers we use\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push es\n"); fprintf(fp, " mov di, ds\n"); fprintf(fp, " mov es, di\n"); fprintf(fp, " mov esi, _%scontextBegin\n", cpubasename); fprintf(fp, " mov edi, eax ; Source address in ESI\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) >> 2\n", cpubasename, cpubasename); fprintf(fp, " rep movsd\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) & 0x03\n", cpubasename, cpubasename); fprintf(fp, " rep movsb\n"); fprintf(fp, " pop es\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret ; No return code\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Get mz80's context */\n\n"); fprintf(fp, "void %sGetContext(void *pData)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " memcpy(pData, &cpu, sizeof(CONTEXTMZ80));\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } GetContextSizeCode() { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sGetContextSize\n", cpubasename); fprintf(fp, " global %sGetContextSize_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetContextSize\n", cpubasename); sprintf(procname, "%sGetContextSize_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetContextSize:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetContextSize:\n", cpubasename); fprintf(fp, " mov eax, _%scontextEnd - _%scontextBegin\n", cpubasename, cpubasename); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Get mz80's context size */\n\n"); fprintf(fp, "UINT32 %sGetContextSize(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " return(sizeof(CONTEXTMZ80));\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } void InitCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sinit\n", cpubasename); fprintf(fp, " global %sinit_\n", cpubasename); if (bPlain) fprintf(fp, " global %sinit\n", cpubasename); sprintf(procname, "%sinit_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sinit:\n", cpubasename); if (bPlain) fprintf(fp, "%sinit:\n", cpubasename); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Initialize MZ80 for action */\n\n"); fprintf(fp, "void %sinit(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " UINT32 dwLoop;\n"); fprintf(fp, " UINT8 *pbTempPtr;\n"); fprintf(fp, " UINT8 *pbTempPtr2;\n"); fprintf(fp, " UINT8 bNewAdd;\n"); fprintf(fp, " UINT8 bNewSub;\n"); fprintf(fp, " UINT8 bFlag;\n"); fprintf(fp, " UINT8 bLow;\n"); fprintf(fp, " UINT8 bHigh;\n"); fprintf(fp, " UINT8 bCarry;\n"); fprintf(fp, "\n"); fprintf(fp, " if (NULL == pbAddAdcTable)\n"); fprintf(fp, " {\n"); fprintf(fp, " pbAddAdcTable = malloc(256*256*2);\n"); fprintf(fp, "\n"); fprintf(fp, " if (NULL == pbAddAdcTable)\n"); fprintf(fp, " {\n"); fprintf(fp, " return;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " pbTempPtr = pbAddAdcTable;\n\n"); fprintf(fp, " pbSubSbcTable = malloc(256*256*2);\n"); fprintf(fp, "\n"); fprintf(fp, " if (NULL == pbSubSbcTable)\n"); fprintf(fp, " {\n"); fprintf(fp, " return;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " pbTempPtr2 = pbSubSbcTable;\n"); fprintf(fp, "\n"); fprintf(fp, " for (dwLoop = 0; dwLoop < (256*256*2); dwLoop++)\n"); fprintf(fp, " {\n"); fprintf(fp, " bLow = dwLoop & 0xff;\n"); fprintf(fp, " bHigh = (dwLoop >> 8) & 0xff;\n"); fprintf(fp, " bCarry = (dwLoop >> 16);\n"); fprintf(fp, "\n"); fprintf(fp, " bFlag = 0;\n"); fprintf(fp, " bNewAdd = bHigh + bLow + bCarry;\n"); fprintf(fp, "\n"); fprintf(fp, " if (0 == bNewAdd)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag = bNewAdd & 0x80; /* Sign flag */\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if (((UINT32) bLow + (UINT32) bHigh + (UINT32) bCarry) >= 0x100)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((bLow ^ bHigh ^ 0x80) & (bLow ^ (bNewAdd & 0x80))) & 0x80)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if (((bLow & 0x0f) + (bHigh & 0x0f) + bCarry) >= 0x10)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_HALF_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " *pbTempPtr++ = bFlag; /* Store our new flag */\n\n"); fprintf(fp, " // Now do subtract - Zero\n"); fprintf(fp, "\n"); fprintf(fp, " bFlag = Z80_FLAG_NEGATIVE;\n"); fprintf(fp, " bNewSub = bHigh - bLow - bCarry;\n"); fprintf(fp, "\n"); fprintf(fp, " if (0 == bNewSub)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= bNewSub & 0x80; /* Sign flag */\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((INT32) bHigh - (INT32) bLow - (INT32) bCarry) < 0)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((INT32) (bHigh & 0xf) - (INT32) (bLow & 0x0f) - (INT32) bCarry) < 0)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_HALF_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((bLow ^ bHigh) & (bHigh ^ bNewSub) & 0x80) )\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " *pbTempPtr2++ = bFlag; /* Store our sub flag */\n"); fprintf(fp, "\n"); fprintf(fp, " }\n"); fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { assert(0); } } void ShutdownCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sshutdown\n", cpubasename); fprintf(fp, " global %sshutdown_\n", cpubasename); if (bPlain) fprintf(fp, " global %sshutdown\n", cpubasename); sprintf(procname, "%sshutdown_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sshutdown:\n", cpubasename); if (bPlain) fprintf(fp, "%sshutdown:\n", cpubasename); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Shut down MZ80 */\n\n"); fprintf(fp, "void %sshutdown(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, "}\n\n"); } else { assert(0); } } void DebuggerCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; In : EAX=Reg #, ESI=Context address\n"); fprintf(fp, "; Out: EAX=Value of register\n"); fprintf(fp, ";\n"); fprintf(fp, "getRegValueInternal:\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n\n"); fprintf(fp, " cmp eax, CPUREG_MAXINDEX\n"); fprintf(fp, " jae badIndex2\n\n"); fprintf(fp, " shl eax, 4 ; Times 16 for table entry size\n"); fprintf(fp, " add eax, RegTable ; Now it's the memory location\n"); fprintf(fp, " mov edx, [eax+4] ; Get the offset of the register\n"); fprintf(fp, " mov edx, [edx + esi] ; Get our value\n"); fprintf(fp, " mov ecx, [eax+8] ; Get our shift value\n"); fprintf(fp, " shr edx, cl ; Shift it right by a value\n"); fprintf(fp, " and edx, [eax+12] ; Mask off any unneeded bits\n"); fprintf(fp, " mov eax, edx ; Put our value in EAX\n"); fprintf(fp, " jmp short indexExit ; Index's exit!\n"); fprintf(fp, "badIndex2:\n"); fprintf(fp, " mov eax, 0ffffffffh\n\n"); fprintf(fp, "indexExit:\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; In : EAX=Value, EDX=Reg #, ESI=Context address\n"); fprintf(fp, "; Out: EAX=Value of register\n"); fprintf(fp, ";\n"); fprintf(fp, "convertValueToText:\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n\n"); fprintf(fp, " cmp edx, CPUREG_MAXINDEX\n"); fprintf(fp, " jae badIndex3\n\n"); fprintf(fp, " shl edx, 4 ; Times 16 for table entry size\n"); fprintf(fp, " add edx, RegTable ; Now it's the memory location\n"); fprintf(fp, " mov edx, [edx + 12] ; Shift mask\n"); fprintf(fp, " xor ecx, ecx ; Zero our shift\n"); fprintf(fp, "shiftLoop:\n"); fprintf(fp, " test edx, 0f0000000h ; High nibble nonzero yet?\n"); fprintf(fp, " jnz convertLoop ; Yup!\n"); fprintf(fp, " shl edx, 4 ; Move over, bacon\n"); fprintf(fp, " shl eax, 4 ; Move the value over, too\n"); fprintf(fp, " jmp short shiftLoop ; Keep shiftin'\n\n"); fprintf(fp, "convertLoop:\n"); fprintf(fp, " mov ecx, eax ; Get our value\n"); fprintf(fp, " shr ecx, 28 ; Only the top nibble\n"); fprintf(fp, " add cl, '0' ; Convert to ASCII\n"); fprintf(fp, " cmp cl, '9' ; Greater than 9?\n"); fprintf(fp, " jbe noAdd ; Nope! Don't add it\n"); fprintf(fp, " add cl, 32+7 ; Convert from lowercase a-f\n"); fprintf(fp, "noAdd:\n"); fprintf(fp, " mov [edi], cl ; New value storage\n"); fprintf(fp, " inc edi ; Next byte, please\n"); fprintf(fp, " shl eax, 4 ; Move the mask over\n"); fprintf(fp, " shl edx, 4 ; Move the mask over\n"); fprintf(fp, " jnz convertLoop ; Keep convertin'\n\n"); fprintf(fp, "badIndex3:\n"); fprintf(fp, " mov [edi], byte 0 ; Null terminate the sucker!\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " ret\n\n"); fprintf(fp, " global _%sSetRegisterValue\n", cpubasename); fprintf(fp, " global %sSetRegisterValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sSetRegisterValue\n", cpubasename); sprintf(procname, "%sSetRegisterValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sSetRegisterValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sSetRegisterValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ecx\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+20] ; Get our register #\n"); fprintf(fp, " mov esi, [esp+24] ; Get our context address\n"); fprintf(fp, " mov edi, [esp+28] ; Value to assign\n"); } else { fprintf(fp, " mov esi, eax ; Get context\n"); fprintf(fp, " mov eax, edx ; Get register # in EAX\n"); fprintf(fp, " mov edi, ebx ; Get value to assign\n"); } fprintf(fp, " or esi, esi ; Are we NULL?\n"); fprintf(fp, " jnz userDefined\n"); fprintf(fp, " mov esi, _%scontextBegin\n", cpubasename); fprintf(fp, "userDefined:\n\n"); fprintf(fp, " shl eax, 4 ; Times 16 for reg entry size\n"); fprintf(fp, " add eax, RegTable\n"); fprintf(fp, " mov edx, [eax+12] ; Our mask\n"); fprintf(fp, " not edx ; Invert EDX!\n"); fprintf(fp, " test edi, edx ; Did we set any invalid bits?\n"); fprintf(fp, " jnz rangeViolation\n\n"); fprintf(fp, " not edx ; Toggle it back to normal\n"); fprintf(fp, " mov ecx, [eax+8] ; Get our shift value\n"); fprintf(fp, " shl edx, cl ; Shift our mask\n"); fprintf(fp, " shl eax, cl ; And our value to OR in\n"); fprintf(fp, " not edx ; Make it the inverse of what we want\n"); fprintf(fp, " mov eax, [eax+4] ; Get our offset into the context\n"); fprintf(fp, " and [esi+eax], edx ; Mask off the bits we're changin\n"); fprintf(fp, " or [esi+eax], edi ; Or in our new value\n\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " jmp short setExit\n\n"); fprintf(fp, "rangeViolation:\n"); fprintf(fp, " mov eax, 0ffffffffh\n\n"); fprintf(fp, "setExit:\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sGetRegisterValue\n", cpubasename); fprintf(fp, " global %sGetRegisterValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetRegisterValue\n", cpubasename); sprintf(procname, "%sGetRegisterValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetRegisterValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetRegisterValue:\n", cpubasename); fprintf(fp, " push esi\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+8] ; Get our register #\n"); fprintf(fp, " mov esi, [esp+12] ; Get our context address\n"); } else { fprintf(fp, " mov esi, eax ; Get context\n"); fprintf(fp, " mov eax, edx ; Get register # in EAX\n"); } fprintf(fp, " or esi, esi ; Is context NULL?\n"); fprintf(fp, " jnz getVal ; Nope - use it!\n"); fprintf(fp, " mov esi, _%scontextBegin\n\n", cpubasename); fprintf(fp, "getVal:\n"); fprintf(fp, " call getRegValueInternal\n\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sGetRegisterName\n", cpubasename); fprintf(fp, " global %sGetRegisterName_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetRegisterName\n", cpubasename); sprintf(procname, "%sGetRegisterName_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetRegisterName:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetRegisterName:\n", cpubasename); if (bUseStack) { fprintf(fp, " mov eax, [esp+4] ; Get our register #\n"); } fprintf(fp, " cmp eax, CPUREG_MAXINDEX\n"); fprintf(fp, " jae badIndex\n"); fprintf(fp, " shl eax, 4 ; Times 16 bytes for each entry\n"); fprintf(fp, " mov eax, [eax+RegTable]\n"); fprintf(fp, " jmp nameExit\n\n"); fprintf(fp, "badIndex:\n"); fprintf(fp, " xor eax, eax\n\n"); fprintf(fp, "nameExit:\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sGetRegisterTextValue\n", cpubasename); fprintf(fp, " global %sGetRegisterTextValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetRegisterTextValue\n", cpubasename); sprintf(procname, "%sGetRegisterTextValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetRegisterTextValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetRegisterTextValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+16] ; Get our register #\n"); fprintf(fp, " mov esi, [esp+20] ; Get our context address\n"); fprintf(fp, " mov edi, [esp+24] ; Address to place text\n"); } else { fprintf(fp, " mov esi, eax ; Get context\n"); fprintf(fp, " mov eax, edx ; Get register # in EAX\n"); fprintf(fp, " mov edi, ebx ; Address to place text\n"); } fprintf(fp, " or esi, esi ; Is context NULL?\n"); fprintf(fp, " jnz getVal2 ; Nope - use it!\n"); fprintf(fp, " mov esi, _%scontextBegin\n\n", cpubasename); fprintf(fp, "getVal2:\n"); fprintf(fp, " mov edx, eax ; Save off our index for later\n"); fprintf(fp, " call getRegValueInternal\n\n"); fprintf(fp, "; EAX Holds the value, EDX=Register #, and EDI=Destination!\n\n"); fprintf(fp, " call convertValueToText\n\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sWriteValue\n", cpubasename); fprintf(fp, " global %sWriteValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sWriteValue\n", cpubasename); sprintf(procname, "%sWriteValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sWriteValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sWriteValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebp\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+28] ; What kind of write is this?\n"); fprintf(fp, " mov ebx, [esp+32] ; Address\n"); fprintf(fp, " mov edx, [esp+36] ; Value\n"); } else { fprintf(fp, " xchg edx, ebx ; Addr=EBX, value=EDX\n"); } fprintf(fp, " cmp eax, 1 ; Is it a word write?\n"); fprintf(fp, " je near invalidWrite ; Yep - it's not valid\n"); fprintf(fp, " cmp eax, 2 ; Is it a dword write?\n"); fprintf(fp, " je near invalidWrite ; Yep - it's not valid\n\n"); fprintf(fp, " or eax, eax ; Is it a byte write?\n"); fprintf(fp, " jnz itsIoDummy ; Nope... it's an I/O write\n\n"); // Here we do a write memory byte fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " mov edi, [_z80MemWrite] ; Point to the write array\n"); fprintf(fp, "checkLoop:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je memoryWrite ; Yes - go write it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextAddr ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+4] ; Are we smaller?\n"); fprintf(fp, " jbe callRoutine ; If not, go call it!\n"); fprintf(fp, "nextAddr:\n"); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop\n"); fprintf(fp, "callRoutine:\n"); fprintf(fp, "\n;\n; EBX=Address to target, DL=Byte to write \n;\n\n"); fprintf(fp, " cmp [edi+8], dword 0 ; Null handler?\n"); fprintf(fp, " je directWriteHandler2\n\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov ebx, edi ; Pointer to struct (EDX Already has the byte to write)\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push edx ; Byte\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); if (bUseStack) { fprintf(fp, " add esp, 12\n"); } fprintf(fp, " jmp short itsGood\n"); fprintf(fp, "directWriteHandler2:\n"); fprintf(fp, " sub ebx, [edi] ; Subtract our offset\n"); fprintf(fp, " add ebx, [edi+12] ; Add in the base address\n"); fprintf(fp, " mov [ebx], dl ; Store our byte\n"); fprintf(fp, " jmp short itsGood\n"); fprintf(fp, "memoryWrite:\n"); fprintf(fp, " mov [ebp + ebx], dl\n\n"); fprintf(fp, " jmp short itsGood\n"); // Here we do an "out" fprintf(fp, "itsIoDummy:\n"); fprintf(fp, " mov edi, [_z80IoWrite] ; Point to the I/O write array\n"); fprintf(fp, "IOCheck:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je itsGood ; Yes - ignore it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextIOAddr ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+2] ; Are we bigger?\n"); fprintf(fp, " jbe callIOHandler ; If not, go call it!\n"); fprintf(fp, "nextIOAddr:\n"); fprintf(fp, " add edi, 0ch ; Next structure, please\n"); fprintf(fp, " jmp short IOCheck\n"); fprintf(fp, "callIOHandler:\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov ebx, edi ; Pointer to struct (EDX Already has the byte to write)\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push edx ; Byte\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi+4] ; Call the handler!\n"); if (bUseStack) fprintf(fp, " add esp, 12\n"); fprintf(fp, " jmp short itsGood\n\n"); // Errors and whatnot fprintf(fp, "invalidWrite:\n"); fprintf(fp, " mov eax, 0ffffffffh\n"); fprintf(fp, " jmp short writeValueExit\n\n"); fprintf(fp, "itsGood:\n"); fprintf(fp, " xor eax, eax\n\n"); fprintf(fp, "writeValueExit:\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sReadValue\n", cpubasename); fprintf(fp, " global %sReadValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sReadValue\n", cpubasename); sprintf(procname, "%sReadValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sReadValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sReadValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebp\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+28] ; What kind of read is this?\n"); fprintf(fp, " mov ebx, [esp+32] ; Address\n"); } else { fprintf(fp, " xchg edx, ebx ; Addr=EBX\n"); } fprintf(fp, " cmp eax, 1 ; Is it a word read?\n"); fprintf(fp, " je near invalidRead ; Yep - it's not valid\n"); fprintf(fp, " cmp eax, 2 ; Is it a dword read?\n"); fprintf(fp, " je near invalidRead ; Yep - it's not valid\n\n"); fprintf(fp, " or eax, eax ; Is it a byte read?\n"); fprintf(fp, " jnz itsIoDummyRead ; Nope... it's an I/O read\n\n"); // Here we do a read memory byte fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " mov edi, [_z80MemRead] ; Point to the read array\n"); fprintf(fp, "checkLoopRead:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je memoryRead ; Yes - go read it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextAddrRead ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+4] ; Are we smaller?\n"); fprintf(fp, " jbe callRoutineRead ; If not, go call it!\n"); fprintf(fp, "nextAddrRead:\n"); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoopRead\n"); fprintf(fp, "callRoutineRead:\n"); fprintf(fp, "\n;\n; EBX=Address to target\n;\n\n"); fprintf(fp, " cmp [edi+8], dword 0 ; NULL HAndler?\n"); fprintf(fp, " je handleSharedRead\n\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov edx, edi ; Pointer to struct\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); fprintf(fp, " mov dl, al ; Get our byte read\n"); if (bUseStack) { fprintf(fp, " add esp, 8\n"); } fprintf(fp, " jmp short itsGoodRead\n\n"); fprintf(fp, "memoryRead:\n"); fprintf(fp, " mov dl, [ebp+ebx]\n\n"); fprintf(fp, " jmp short itsGoodRead\n\n"); fprintf(fp, "handleSharedRead:\n"); fprintf(fp, " sub ebx, [edi]\n"); fprintf(fp, " add ebx, [edi+12]\n"); fprintf(fp, " mov dl, [ebx]\n"); fprintf(fp, " jmp short itsGoodRead\n\n"); // Here we do an "out" fprintf(fp, "itsIoDummyRead:\n"); fprintf(fp, " mov edi, [_z80IoRead] ; Point to the I/O read array\n"); fprintf(fp, " mov dl, 0ffh ; Assume no handler\n"); fprintf(fp, "IOCheckRead:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je itsGoodRead ; Yes - ignore it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextIOAddrRead ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+2] ; Are we bigger?\n"); fprintf(fp, " jbe callIOHandlerRead ; If not, go call it!\n"); fprintf(fp, "nextIOAddrRead:\n"); fprintf(fp, " add edi, 0ch ; Next structure, please\n"); fprintf(fp, " jmp short IOCheckRead\n"); fprintf(fp, "callIOHandlerRead:\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov edx, edi ; Pointer to struct (EDX Already has the byte to write)\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi+4] ; Call the handler!\n"); fprintf(fp, " mov dl, al ; Get our byte read\n"); if (bUseStack) fprintf(fp, " add esp, 8\n"); fprintf(fp, " jmp short itsGoodRead\n\n"); // Errors and whatnot fprintf(fp, "invalidRead:\n"); fprintf(fp, " mov eax, 0ffffffffh\n"); fprintf(fp, " jmp short ReadValueExit\n\n"); fprintf(fp, "itsGoodRead:\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov al, dl\n\n"); fprintf(fp, "ReadValueExit:\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } } EmitCode() { CodeSegmentBegin(); EmitCBInstructions(); EmitEDInstructions(); if (MZ80_ASSEMBLY_X86 == bWhat) strcpy(mz80Index, "ix"); else { strcpy(mz80Index, "cpu.z80IX"); strcpy(mz80IndexHalfHigh, "cpu.z80XH"); strcpy(mz80IndexHalfLow, "cpu.z80XL"); } strcpy(majorOp, "DD"); EmitDDInstructions(); if (MZ80_ASSEMBLY_X86 == bWhat) strcpy(mz80Index, "iy"); else { strcpy(mz80Index, "cpu.z80IY"); strcpy(mz80IndexHalfHigh, "cpu.z80YH"); strcpy(mz80IndexHalfLow, "cpu.z80YL"); } strcpy(majorOp, "FD"); EmitFDInstructions(); majorOp[0] = '\0'; EmitRegularInstructions(); ReadMemoryByteHandler(); WriteMemoryByteHandler(); if (bThroughCallHandler) { PushWordHandler(); PopWordHandler(); } ReadIoHandler(); WriteIoHandler(); GetContextCode(); SetContextCode(); GetContextSizeCode(); GetTicksCode(); ReleaseTimesliceCode(); ResetCode(); IntCode(); NmiCode(); ExecCode(); InitCode(); ShutdownCode(); DebuggerCode(); CodeSegmentEnd(); } main(int argc, char **argv) { UINT32 dwLoop = 0; printf("MakeZ80 - V%s - Copyright 1996-2000 Neil Bradley (neil@synthcom.com)\n", VERSION); if (argc < 2) { printf("Usage: %s outfile [option1] [option2] ....\n", argv[0]); printf("\n -s - Stack calling conventions (DJGPP, MSVC, Borland)\n"); printf(" -x86 - Emit an assembly version of mz80\n"); printf(" -c - Emit a C version of mz80\n"); printf(" -cs - All stack operations go through handlers\n"); printf(" -16 - Treat all I/O input and output as 16 bit (BC) instead of (C)\n"); printf(" -l - Create 'plain' labels - ones without leading or trailing _'s\n"); printf(" -nt - No timing additions occur\n"); printf(" -os2 - Emit OS/2 compatible segmentation pragmas\n"); exit(1); } dwLoop = 1; while (dwLoop < argc) { if (strcmp("-x86", argv[dwLoop]) == 0 || strcmp("-X86", argv[dwLoop]) == 0) bWhat = MZ80_ASSEMBLY_X86; if (strcmp("-c", argv[dwLoop]) == 0 || strcmp("-C", argv[dwLoop]) == 0) bWhat = MZ80_C; if (strcmp("-cs", argv[dwLoop]) == 0 || strcmp("-cs", argv[dwLoop]) == 0) bThroughCallHandler = TRUE; if (strcmp("-s", argv[dwLoop]) == 0 || strcmp("-S", argv[dwLoop]) == 0) bUseStack = 1; if (strcmp("-l", argv[dwLoop]) == 0 || strcmp("-L", argv[dwLoop]) == 0) bPlain = TRUE; if (strcmp("-16", argv[dwLoop]) == 0) b16BitIo = TRUE; if (strcmp("-os2", argv[dwLoop]) == 0 || strcmp("-OS2", argv[dwLoop]) == 0) bOS2 = TRUE; if (strcmp("-nt", argv[dwLoop]) == 0) { bNoTiming = TRUE; } dwLoop++; } if (bWhat == MZ80_UNKNOWN) { fprintf(stderr, "Need emitted type qualifier\n"); exit(1); } for (dwLoop = 1; dwLoop < argc; dwLoop++) if (argv[dwLoop][0] != '-') { fp = fopen(argv[dwLoop], "w"); break; } if (NULL == fp) { fprintf(stderr, "Can't open %s for writing\n", argv[1]); exit(1); } strcpy(cpubasename, "mz80"); StandardHeader(); DataSegment(); EmitCode(); ProgramEnd(); fclose(fp); } dgen-sdl-1.23/mz80/mz80.txt 644 1750 1750 74657 7065016352 10461 Multi-Z80 32 Bit emulator Copyright 1996, 1997, 1998, 1999, 2000 - Neil Bradley, All rights reserved MZ80 License agreement ----------------------- (MZ80 Refers to both the assembly code emitted by makez80.c and makez80.c itself) MZ80 May be distributed in unmodified form to any medium. MZ80 May not be sold, or sold as a part of a commercial package without the express written permission of Neil Bradley (neil@synthcom.com). This includes shareware. Modified versions of MZ80 may not be publicly redistributed without author approval (neil@synthcom.com). This includes distributing via a publicly accessible LAN. You may make your own source modifications and distribute MZ80 in source or object form, but if you make modifications to MZ80 then it should be noted in the top as a comment in makez80.c. MZ80 Licensing for commercial applications is available. Please email neil@synthcom.com for details. Synthcom Systems, Inc, and Neil Bradley will not be held responsible for any damage done by the use of MZ80. It is purely "as-is". If you use MZ80 in a freeware application, credit in the following text: "Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)" must accompany the freeware application within the application itself or in the documentation. Legal stuff aside: If you find problems with MZ80, please email the author so they can get resolved. If you find a bug and fix it, please also email the author so that those bug fixes can be propogated to the installed base of MZ80 users. If you find performance improvements or problems with MZ80, please email the author with your changes/suggestions and they will be rolled in with subsequent releases of MZ80. The whole idea of this emulator is to have the fastest available 32 bit Multi-Z80 emulator for the x86, giving maximum performance. MZ80 Contact information ------------------------- Author : Neil Bradley (neil@synthcom.com) Distribution: ftp://ftp.synthcom.com/pub/emulators/cpu/makez80.zip (latest) You can join the cpuemu mailing list on Synthcom for discussion of Neil Bradley's Z80 (and other) CPU emulators. Send a message to "cpuemu-request@synthcom.com" with "subscribe" in the message body. The traffic is fairly low, and is used as a general discussion and announcement for aforementioned emulators. MZ80 Documentation ------------------- MZ80 Is a full featured Z80 emulator coded in 32 bit assembly. It runs well over a hundred games, in addition to it supporting many undocumented Z80 instructions required to run some of the Midway MCR games, Galaga, and countless other wonderful Z80 based arcade games. MZ80 Contains a makez80.c program that must be compiled. It is the program that emits the assembly code that NASM will compile. This minimizes the possibility of bugs creeping in to MZ80 for the different addressing modes for each instruction. It requires NASM 0.97 or greater. The goal of MZ80 is to have a high performance Z80 emulator that is capable of running multiple emulations concurrently at full speed, even on lower-end machines (486/33). MZ80 Harnesses the striking similarities of both the Z80 and the x86 instruction sets to take advantage of flag handling which greatly reduces the time required to emulate a processor, so no extra time is spent computing things that are already available in the native x86 processor, allowing it to perform leaps and bounds over comparable C based Z80 emulators on the same platform. MZ80 Is designed exclusively for use with NASM, the Netwide Assembler. This gives the ultimate in flexibility, as NASM can emit object files that work with Watcom, Microsoft Visual C++ (4.0-current), DJGPP, Borland C++, and gcc under FreeBSD or Linux. MZ80 Has been tested with each one of these compilers and is known to work properly on each. What's in the package --------------------- MZ80.TXT - This text file MAKEZ80.C - Multi Z80 32 Bit emulator emitter program MZ80.H - C Header file for MZ80 functions What's new in this release -------------------------- Revision 3.4: * Fixed the overflow flag not getting cleared in the SetOverflow() routine. It caused strange problems with a handful of Genesis games * Removed invalid instruction in the C version so that more instructions will execute Revision 3.3: * Undocumented opcodes added to the C emitter * Bug fix to the C emission that properly handles shared RAM regions (I.E. with handlers that are NULL) * Now using 32 bit registers to do register/memory access. Slight speed increase (assembly version only) Revision 3.2: * R Register emulation now accurate with a real Z80 * mz80int() Called when interrupts are disabled causes the z80intPending flag to be set, and an interrupt will be caused after the execution of EI and the next instruction. See "IMPORTANT NOTE ABOUT INTERRUPTS" below * The instruction after EI executes fully before interrupt status is checked. (as does a real Z80) Revision 3.1: * Fixed bug in memory dereference when handler was set to NULL (keeps system from crashing or faulting) * Removed the only stricmp() from the entire file and replaced it with strcmp() so that stdlibs without it will compile * Changed cyclesRemaining > 0 to cyclesRemaining >= 0 to be compatible with the ASM core * Removed additional sub [dwCyclesRemaining], 5 at the beginning of mz80exec() (ASM Core only). Increases timing accuracy. * NMIs And INTs add additional time to dwElapsedTicks as it should * mz80ReleaseTimeslice() Sets remaining clocks to 0 instead of 1 Revision 3.0: * All instructions validated against a real Z80. Used an ISA card with a Z80 on it to validate flag handling, instruction handling, timing, and other goodies. The only thing not implemented/emulated is flag bit 3 & 5 emulation. Believed to be 100% bug free! * 80% Speed improvement over version 2.7 of mz80 * z80stb.c Removed. Use -c to emit a C version of mz80! API compatible! Note that this is mostly, but not fully, debugged, so consider the C version a beta! It's at least healthier than z80stb.c was. The C version does not include the undocumented Z80 instructions. * mz80nmi() No longer trashes registers it uses when using -cs * IN/OUT Instructions work properly when using -16 * IN A, (xxh) uses A as high 8 bits of I/O fetch address when using -16 * IM 0/IM 1 Description in documentation fixed * Sizes of all context registers increased to 32 bits - for speed! * IFF1/IFF2 Now properly emulated * JR Instruction offset can fetch from $ffff and properly wrap * LDIR/LDDR Instruction now won't go to completion - instead it will run until BC=0 or the # of cycles to execute have expired. These instructions used to run to completion - even beyond the # of cycles left to execute * INI/IND/INIR/INDR countdown bug fixed - it was decrementing B twice for each IN! Whoops! * If you specify NULL as a handler address to a memory region, mz80 will use vpData as a pointer to where that block of data resides. Quite useful for multiprocessor emulations that share the same memory. * EDI Now keeps track of cycle counting for faster execution * Modified memory region scanning code to use 32 bit registers instead of their 16 bit counterparts * Get/SetContext() uses rep movsd/movsb. Insignificant overall, but why waste the time? * Debugging routines added. See the "DEBUGGING" section below for more information. NOTE: The debugging routines are not yet available in the C emission. * Timing done slightly differently now. Mz80 now executes one instruction past the timing given on input. For example, mz80exec(0) will cause a single instruction to be executed (thusly -ss was removed). Revision 2.7: * Fixed OTIR/OTDR/INIR/INDR instructions so their 16 bit counterparts work properly * Emulation core 30-70% faster overall than 2.6 due to optimization to the timing routines * Replaced word reads/writes with a special word write routine rather than the standard calling to read/write byte functions * z80stb.c (the C equivalent of mz80) compiles properly now * Fixed OS/2 text/segment issue * Fixed bug in set/getCPU context that ensures that ES=DS and avoids crashes. Caused crashes under OS/2 and other OS's Revision 2.6: * Emulator core 5-30% faster overall. Some 16 and 8 bit instructions sped up when using their 32 bit equivalents. * Fix to -l so that proper labels without leading and trailing underscores so Linux/FreeBSD compiles will work properly * Single step now executes the # of instructions passed in to z80exec() instead of just 1 as it had in prior releases. This is only active when the -ss option is used. * The -nt option was added. This will cause the timing information to not be added in, speeding up execution. Warning: Only do this if your emulated target does not require instruction timing! * Updated documentation errors * C Version of mz80 (mz80.c) that is API compliant is distributed with the archive (With kind permission of Edward Massey). Revision 2.5: * Fixed an unconditional flag being cleared in the ddcbxx instructions. It caused Donkey Kong's barrels to not roll. Revision 2.4: * Fixed improper HALT handling (didn't advance the PTR when it should) * Fixed SRL (IX+$xx) instruction so that carry wasn't trashed * Fixed single stepping problems with it giving too much time to any given instruction * Fixed half carry flag handling with 16 bit SBC and ADD instructions * Fixed DAA emulation so that parity flags weren't getting trashed Revision 2.3: * Fixed many stack handling bugs * Timing problems fixed. The prior version was causing massive overruns on maximum timeslices with some insutructions. Revision 2.2: * Fixed a bug in CPI/CPD/CPIR/CPDR that mishandled flags * All known bugs are out of mz80 now * Added the -cs option to route all stack operations through the handlers (required for games like Galaga) Revision 2.1: * Fixed a bug in CPI/CPD/CPIR/CPDR that caused intermittent lockups. Also fixed a bug that caused erratic behavior in several video games. * Added INI/IND/INIR/INDR instruction group * Added OUTI/OUTD/OTIR/OTDR instruction group Revision 1.0: * First release! The whole thing is new! ASSEMBLING FOR USE WITH WATCOM C/C++ ------------------------------------ Watcom, by default, uses register calling conventions, as does MZ80. To create a proper emulator for Watcom: makez80 MZ80.asm -x86 From here: nasm -f win32 MZ80.asm Link the MZ80.obj with your Watcom linker. ASSEMBLING FOR USE WITH MICROSOFT VISUAL C++ AND BORLAND C++ -------------------------------------------------------------------- Visual C++ and Borland C++ use stack calling conventions by default. To create a proper emulator for these compilers: makez80 MZ80.asm -s -x86 For Visual C++ or Borland C++: nasm -f win32 MZ80.asm Link with your standard Visual C++ or Borland C++. ASSEMBLING FOR USE WITH DJGPP, GCC/FREEBSD, OR GCC/LINUX -------------------------------------------------------------------- DJGPP Uses stack calling conventions: makez80 MZ80.asm -s -x86 To assemble: nasm -f coff MZ80.asm Link with your standard DJGPP linker. The same holds true for GCC under FreeBSD or Linux. If you're using GCC, use the -l option to generate "plain" labels so that gcc's linker will properly link things. MAKEZ80 COMMAND LINE OPTIONS ---------------------------- -s - Use stack calling conventions (DJGPP, MSVC, Borland, etc...) -cs - Force all stack operations to go through the Read/Write memory handlers. This slows things down, but is useful when needed. -16 - Treat all I/O input and output as 16 bit (BC) -l - Create 'plain' labels - ones without leading and trailing underscores -nt - Do not generate timing code - this speeds the emulator up, but the downside is that no timing info is available. -c - Emit a C mz80 emulator (API Compatible with the assembly version - handy for porters!) -x86 - Emit an assembly (x86) mz80 emulator -os2 - Generate OS/2 compatible segmentation IMPORTANT NOTE ABOUT INTERRUPTS ------------------------------- A minor change was made between the 3.1 and 3.2 versions of makez80 in the way that interrupts were handled. On a real Z80, the !INT line is a level triggered interrupt, meaning that if the interrupt line is held low, the Z80 will continue to take interrupts immediately after the instruction after the EI instruction is executed until the interrupt line is high again. In 3.1, if an interrupt came in and interrupts were disabled, the interrupt would never be "latched" for later execution. The Z80 does not have any internal latching capabilities, however external hardware often does hold the interrupt line low until the interrupt is executed, in effect, a latch. I've only found one video game so far that requires the "raising/lowering" of the interrupt line (Ataxx). In the games that I've tried, it has improved performance, in some cases drastically, and in others not at all. This can be accounted for by interrupts being taken now, where they were being dropped in prior mz80 releases. mz80 Emulates the most commonly used scenario. Now when mz80int() is executed and a nonzero value is returned (indicating interrupts were disabled), it will set z80intPending, and the interrupt will be taken after execution of one instruction beyond the EI instruction. So now, if mz80int() returns a nonzero value, that means an interrupt is latched. If clearing this latch is desired or the old behavior of 3.1 is desired, make a call to the mz80ClearPendingInterrupt() call. It's a 2 instruction call that has extremely small overhead and will not affect performance in any measurable way. In any case, MZ80 will now execute one instruction after EI regardless of how much time is available to avoid the possibility of an interrupt request coming in directly after the EI instruction. STEPS TO EMULATION ------------------ NOTE: -16 Is a command line option that will treat all I/O as 16 bit. That is, in an instruction like "IN AL, (C)", the addressed passed to the I/O handler will be BC instead of just C. Bear this in mind when considering your emulated platform. There are a few steps you want to go through to get proper emulation, and a few guidelines must be followed. 1) Create a MZ80CONTEXT 2) Create your virtual 64K memory space using whatever means of obtaining memory you need to do. 3) Set mz80Base in your context to be the base of your 64K memory space 4) Load up your image to be emulated within that 64K address space. 5) Set z80IoRead and z80IoWrite to their appropriate structure arrays. Here's an example: struct z80PortRead ReadPorts[] = { {0x10, 0x1f, SoundChip1Read}, {0x20, 0x2f, SoundChip2Read} {(UINT32) -1, (UINT32) -1, NULL} }; When an IN instruction occurs, mz80 will probe this table looking for a handler to the address of the "IN" instruction. If it is found in the list, it's up to the handler to return the proper value. Otherwise, a value of 0ffh is returned internally if no handler for that I/O address is found. In the case above, SoundChip1Read is called when the I/O address is between 0x10- 0x1f. A similar structure is used for I/O writes as well (OUT): struct z80PortWrite WritePorts[] = { {0x20, 0x2f, SoundChip2Write}, {0x30, 0x36, VideoCtrlWrite}, {(UINT32) -1, (UINT32) -1, NULL} } Of course, this does the opposite that the z80PortRead struct, and instead looks for a handler to hand some data to. If it doesn't find an appropriate handler, nothing happens. 6) Set mz80MemoryRead & mz80MemoryWrite to their appropriate structure arrays. Here is an example: struct MemoryWriteByte GameWrite[] = { {0x3000, 0x3fff, VideoWrite}, {0x4000, 0x4fff, SpriteWrite}, {(UINT32) -1, (UINT32) -1, NULL} }; The above example says that any time a write occurs in the 0x3000-0x3fff range, call the VideoWrite routine. The same holds true for the SpriteWrite region as well. NOTE: When your write handler is called, it is passed the address of the write and the data that is to be written to it. If your handler doesn't write the data to the virtual image, the mz80 internal code will not. NOTE: These routines will *NOT* be called when execution asks for these addresses. It will only call them when a particular instruction uses the memory at these locations. If you wish for a region to be RAM, just leave it out of your memory region exception list. The WriteMemoryByte routine will treat it as read/write RAM and will write to mz80Base + addr directly. If you wish to protect ROM regions (not often necessary), create a range that encompasses the ROM image, and have it call a routine that does nothing. This will prevent data from being written back onto the ROM image. Leave your last entry in the table as shown above, with a null handler and 0xffffffff-0xffffffff as your read address. Even though the Z80 only addresses 64K of space, the read/write handlers are defined as 32 bit so the compiler won't pass junk in the upper 16 bits of the address lines. Not only that, it allows orthoganality for future CPU emulators that may use these upper bits. You can do a mz80GetContext() if you'd like to read the current context of the registers. Note that by the time your handler gets called, the program counter will be pointing to the *NEXT* instruction. struct MemoryReadByte GameRead[] = { {0x2000, 0x200f, ReadHandler}, {(UINT32) -1, (UINT32) -1, NULL} }; Same story here. If you have a special handler for an attempted read at a particular address, place its range in this table and create a handler routine for it. If you don't define a handler for a particular region, then the ReadMemoryByte in mz80.ASM will actually read the value out of mz80Base + the offset required to complete the instruction. 7) Set the intAddr and nmiAddr to the addresses where you want mz80 to start executing when an interrupt or NMI happens. Take a look at the section entitled "INTERRUPTS" below for more information on this. 8) Call mz80SetContext() on your Z80 context 9) Call mz80Reset(). This will prime the program counter and cause a virtual CPU-wide reset. 10) Once you have those defined, you're ready to begin emulation. There's some sort of main loop that you'll want. Maybe something like: while (hit == 0) { if (lastSec != (UINT32) time(0)) { diff = (mz80clockticks - prior) / 3000000; printf("%ld Clockticks, %ld frames, %ld Times original speed\n", MZ80clockticks - prior, frames, diff); frames = 0; prior = mz80clockticks; lastSec = time(0); if (kbhit()) { getch(); hit = 1; } } /* 9000 Cycles per NMI (~3 milliseconds @ 3MHZ) */ dwResult = mz80exec(9000); mz80clockticks += mz80GetElapsedTicks(TRUE); mz80nmi(); /* If the result is not 0x80000000, it's an address where an invalid instruction was hit. */ if (0x80000000 != dwResult) { mz80GetContext(&sCpu1); printf("Invalid instruction at %.2x\n", sCpu1.MZ80pc); exit(1); } } Call mz80exec() With the # of virtual CPU cycles you'd like mz80 to execute. Be sure to use the mz80GetElapsedTicks() call *AFTER* execution to see how many virtual CPU cycles it actually executed. For example, if you tell mz80 to execute 500 virtual CPU cycles, it will execute slightly more. Anything from 500 to 524 (24 cycles being the longest any 1 instruction takes in the Z80). Use the mz80GetElapsedTicks() call for more accurate cycle counting. Of course, this is only if you have *NOT* included the -nt option. If you pass FALSE to the mz80GetElapsedTicks() function, the internal CPU elapsed tick clock will not be reset. The elapsed tick counter is something that continues to increase every emulated instruction, and like an odometer, will keep counting unless you pass TRUE to mz80GetElapsedTicks(), of which case it will return you the current value of the elapsed ticks and set it to 0 when complete. NOTE: The bigger value you pass to mz80exec, the greater benefit you get out of the virtual registers persisting within the emulator, and it will run faster. Pass in a value that is large enough to take advantage of it, but not so often that you can't handle nmi or int's properly. If you wish to create a virtual NMI, call mz80nmi(), and it will be taken the next time you call mz80exec, or alternately if you have a handler call mz80nmi/mz80int(), the interrupt will be taken upon return. Note that mz80nmi() doesn't actually execute any code - it only primes the emulator to begin executing NMI/INT code. NOTE: mz80int() is defined with a UINT32 as a formal parameter. Depending upon what interrupt mode you're executing in (described later), it may or may not take a value. NMI's can interrupt interrupts, but not the other way around - just like a real Z80. If your program is already in an interrupt, another one will not be taken. The same holds true for an NMI - Just like a real Z80! MUTLI-PROCESSOR NOTES --------------------- Doing multi processor support is a bit trickier, but is still fairly straight- forward. For each processor to be emulated, go through steps 1-7 above - giving each CPU its own memory space, register storage, and read/write handlers. EXECUTION OF MULTI-CPUS: ------------------------- When you're ready to execute a given CPU, do the following: mz80SetContext(contextPointer); This will load up all information saved before into the emulator and ready it for execution. Then execute step 7 above to do your virtual NMI's, interrupts, etc... All CPU state information is saved within a context. When the execution cycle is complete, do the following to save the updated context away for later: mz80GetContext(contextPointer); Give each virtual processor a slice of time to execute. Don't make the values too small or it will spend its time swapping contexts. While this in itself isn't particularly CPU expensive, the more time you spend executing the better. mz80 Keeps all of the Z80 register in native x86 register (including most of the flags, HL, BC, and A). If no context swap is needed, then you get the added advantage of the register storage. For example, let's say you were running two Z80s - one at 2.0MHZ and one at 3.0MHZ. An example like this might be desirable: mz80SetContext(cpu1Context); // Set CPU #1's information mz80exec(2000); // 2000 Instructions for 2.0MHZ CPU mz80GetContext(cpu1Context); // Get CPU #1's state info mz80SetContext(cpu2Context); // Set CPU #2's state information mz80exec(3000); // 3000 Instructions for 3.0MHZ CPU mz80GetContext(cpu2Context); // Get CPU #2's state information This isn't entirely realistic, but if you keep the instruction or timing ratios between the emulated CPUs even, then timing is a bit more accurate. NOTE: If you need to make a particular CPU give up its own time cycle because of a memory read/write, simply trap a particular address (say, a write to a slave processor) and call mz80ReleaseTimeslice(). It will not execute any further instructions, and will give up its timeslice. Put this in your read/write memory trap. NOTE: You are responsible for "holding back" the processor emulator from running too fast. INTERRUPTS ---------- The Z80 has three interrupt modes: IM 0 - IM 2. Each act differently. Here's a description of each: IM 0 This mode will cause the Z80 to be able to pull a "single byte instruction" off the bus when an interrupt occurs. Since we're not doing bus cycle emulation, it acts identically to mode 1 (described below). The formal parameter to mz80int() is ignored. There is really no point in actually emulating the instruction execution since any instruction that would be executed would be a branch instruction! IM 1 This mode is the "default" mode that the Z80 (and mz80 for that matter) comes up in. When you call mz80reset(), the interrupt address is set to 38h and the NMI address is set to 66h. So when you're in IM 1 and mz80int() is called, the formal parameter is ignored and the z80intAddr/z80nmiAddr values are appropriately loaded into the program counter. IM 2 This mode causes the Z80 to read the upper 8 bits from the current value of the "I" register, and the lower 8 bits from the value passed into mz80int(). So, if I contained 35h, and you did an mz80int(0x64), then an interrupt at address 3564h would be taken. Simple! OTHER GOODIES ------------- MZ80 Has a nice feature for allowing the same handler to handle different data regions on a single handler. Here's an example: struct PokeyDataStruct Pokey1; struct PokeyDataStruct Pokey2; struct MemoryWriteByte GameWrite[] = { {0x1000, 0x100f, PokeyHandler, Pokey1}, {0x1010, 0x101f, PokeyHandler, Pokey2}, {(UINT32) -1, (UINT32) -1, NULL} }; void PokeyHandler(UINT32 dwAddr, UINT8 bData, struct sMemoryWriteByte *psMem) { struct PokeyDataStruct *psPokey = psMem->pUserArea; // Do stuff with psPokey here.... } This passes in the pointer to the sMemoryWriteByte structure that caused the handler to be called. The pUserArea is a user defined address that can be anything. It is not necessary to fill it in with anything or even initialize it if the handler doesn't actually use it. This allows a single handler to handle multiple data references. This is particularly useful when handling sound chip emulation, where there might be more than one of a given device. Sure beats having multiple unique handlers that are identical with the exception of the data area where it writes! This allows a good deal of flexibility. The same construct holds for MemoryReadByte, z80PortRead, and z80PortWrite, so all can take advantage of this feature. SHARED MEMORY FEATURES ---------------------- MZ80 Also has another useful feature for dealing with shared memory regions: UINT8 bSharedRAM[0x100]; struct MemoryWriteByte Processor1[] = { {0x1000, 0x10ff, NULL, bSharedRAM}, {(UINT32) -1, (UINT32) -1, NULL} }; struct MemoryWriteByte Processor2[] = { {0x1000, 0x10ff, NULL, bSharedRAM}, {(UINT32) -1, (UINT32) -1, NULL} }; If the handler address is NULL, mz80 will look at the pUserArea field as a pointer to RAM to read from/write to. This comes in extremely handy when you have an emulation that requires two or more processors writing to the same memory block. And it's lots faster than creating a handler that writes to a common area as well. DEBUGGING --------- Several new functions have been added to mz80 that assist the emulator author by providing a standard set of functions for register access: UINT8 mz80SetRegisterValue(void *pContext, UINT32 dwRegister, UINT32 dwValue) This allows setting of any register within the Z80. The register field can be one of the following values (defined in mz80.h): CPUREG_PC CPUREG_Z80_AF CPUREG_Z80_BC CPUREG_Z80_DE CPUREG_Z80_HL CPUREG_Z80_AFPRIME CPUREG_Z80_BCPRIME CPUREG_Z80_DEPRIME CPUREG_Z80_HLPRIME CPUREG_Z80_IX CPUREG_Z80_IY CPUREG_Z80_SP CPUREG_Z80_I CPUREG_Z80_R CPUREG_Z80_A CPUREG_Z80_B CPUREG_Z80_C CPUREG_Z80_D CPUREG_Z80_E CPUREG_Z80_H CPUREG_Z80_L CPUREG_Z80_F CPUREG_Z80_CARRY CPUREG_Z80_NEGATIVE CPUREG_Z80_PARITY CPUREG_Z80_OVERFLOW CPUREG_Z80_HALFCARRY CPUREG_Z80_ZERO CPUREG_Z80_SIGN CPUREG_Z80_IFF1 CPUREG_Z80_IFF2 Each individual register's value can be set, including the flags at the end. The only valid values for the flags are 1 and 0. Setting these will automatically adjust the "F" register. If pContext is NULL, then the registers in the currently active context are changed. If pContext points to a non-NULL area, that area is assumed to be a CONTEXTMZ80 structure where the new register value will be written. If mz80SetRegisterValue() returns a nonzero value, either the register value or register is out of range or invalid. UINT32 mz80GetRegisterValue(void *pContext, UINT32 dwRegister) This returns the value of the register given on input (listed above as CPUREG_Z80_xxxxx). Flag values will be 1 or 0. If pContext is NULL, then the registers in the currently active context are read. If pContext points to a non-NULL area, that area is assumed to be a CONTEXTMZ80 structure from which register values are pulled. UINT32 mz80GetRegisterTextValue(void *pContext, UINT32 dwRegister, UINT8 *pbTextArea) This returns the textual representation of the value of a given register. It is a text printable string that can be used in sprintf() statements and the like. This function is useful because different representations for registers (like flags) can be a group of 8 flag bytes instead of a single value. On entry, pContext being set to NULL indicates that mz80 should get the register value from the currently active context. Otherwise, it is assumed to be pointing to a CONTEXTMZ80 structure, which contains the value of the registers to be read. pbTextArea points to a buffer where the value text can be written. This points to a user supplied buffer. On exit, if any nonzero value is encountered, either the register # is out of range or pbTextArea is NULL. UINT8 *mz80GetRegisterName(UINT32 dwRegister) This returns a pointer to the textual name of the register passed in. NULL Is returned if the register index (CPUREG_Z80_xxxx table described above) is out of range. DO NOT MODIFY THE TEXT! It is static data. FINAL NOTES ----------- I have debugged MZ80.ASM to the best of my abilities. There might still be a few bugs floating around in it, but I'm not aware of any. I've validated all instructions (That I could) against a custom built Z80 on an ISA card (that fits in a PC) so I'm quite confident that it works just like a real Z80. If you see any problems, please point them out to me, as I am eager to make mz80 the best emulator that I can. If you have questions, comments, etc... about mz80, please don't hesitate to send me an email. And if you use mz80 in your emulator, I'd love to take a look at your work. If you have special needs, or need implementation specific hints, feel free to email me, Neil Bradley (neil@synthcom.com). I will do my best to help you. Enjoy! Neil Bradley neil@synthcom.com dgen-sdl-1.23/sdl/Makefile.in 644 1750 1750 20141 7320415003 11114 # Makefile.in generated automatically by automake 1.4 from Makefile.am # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # DGen/SDL v1.20+ # SDL Interface SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ infodir = @infodir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include DESTDIR = pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. ACLOCAL = @ACLOCAL@ AUTOCONF = @AUTOCONF@ AUTOMAKE = @AUTOMAKE@ AUTOHEADER = @AUTOHEADER@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_alias = @build_alias@ build_triplet = @build@ host_alias = @host_alias@ host_triplet = @host@ target_alias = @target_alias@ target_triplet = @target@ AWK = @AWK@ CC = @CC@ CHOP_ = @CHOP_@ CPP = @CPP@ CPUDIRS = @CPUDIRS@ CXX = @CXX@ CXXCPP = @CXXCPP@ EXTRAOBJS = @EXTRAOBJS@ INTERFACE = @INTERFACE@ LN_S = @LN_S@ MAKEINFO = @MAKEINFO@ MUSA = @MUSA@ MZ80 = @MZ80@ NASM = @NASM@ NASM_FMT = @NASM_FMT@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ SDL_CONFIG = @SDL_CONFIG@ SDL_LIBS = @SDL_LIBS@ STAR = @STAR@ VERSION = @VERSION@ EXTRA_DIST = dgenfont.pbm chartfont.c INCLUDES = -I.. noinst_PROGRAMS = pbm2df noinst_LIBRARIES = libpd.a # built sources BUILT_SOURCES = dgenfont.cpp # pd.a libpd_a_SOURCES = font.cpp dgenfont.cpp sdl.cpp font.h pd-defs.h ogl_fonts.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ libpd_a_LIBADD = libpd_a_OBJECTS = font.o dgenfont.o sdl.o AR = ar PROGRAMS = $(noinst_PROGRAMS) pbm2df_SOURCES = pbm2df.c pbm2df_OBJECTS = pbm2df.o pbm2df_LDADD = $(LDADD) pbm2df_DEPENDENCIES = pbm2df_LDFLAGS = CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ DIST_COMMON = Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best SOURCES = $(libpd_a_SOURCES) pbm2df.c OBJECTS = $(libpd_a_OBJECTS) pbm2df.o all: all-redirect .SUFFIXES: .SUFFIXES: .S .c .cpp .o .s $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps sdl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status mostlyclean-noinstLIBRARIES: clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) distclean-noinstLIBRARIES: maintainer-clean-noinstLIBRARIES: .c.o: $(COMPILE) -c $< .s.o: $(COMPILE) -c $< .S.o: $(COMPILE) -c $< mostlyclean-compile: -rm -f *.o core *.core clean-compile: distclean-compile: -rm -f *.tab.c maintainer-clean-compile: libpd.a: $(libpd_a_OBJECTS) $(libpd_a_DEPENDENCIES) -rm -f libpd.a $(AR) cru libpd.a $(libpd_a_OBJECTS) $(libpd_a_LIBADD) $(RANLIB) libpd.a mostlyclean-noinstPROGRAMS: clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) distclean-noinstPROGRAMS: maintainer-clean-noinstPROGRAMS: pbm2df: $(pbm2df_OBJECTS) $(pbm2df_DEPENDENCIES) @rm -f pbm2df $(LINK) $(pbm2df_LDFLAGS) $(pbm2df_OBJECTS) $(pbm2df_LDADD) $(LIBS) .cpp.o: $(CXXCOMPILE) -c $< tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ here=`pwd` && cd $(srcdir) \ && mkid -f$$here/ID $$unique $(LISP) TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS)'; \ unique=`for i in $$list; do echo $$i; done | \ awk ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) mostlyclean-tags: clean-tags: distclean-tags: -rm -f TAGS ID maintainer-clean-tags: distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) subdir = sdl distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done pbm2df.o: pbm2df.c info-am: info: info-am dvi-am: dvi: dvi-am check-am: all-am check: check-am installcheck-am: installcheck: installcheck-am install-exec-am: install-exec: install-exec-am install-data-am: install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-am uninstall-am: uninstall: uninstall-am all-am: Makefile $(LIBRARIES) $(PROGRAMS) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: mostlyclean-generic: clean-generic: distclean-generic: -rm -f Makefile $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ mostlyclean-noinstPROGRAMS mostlyclean-tags \ mostlyclean-generic mostlyclean: mostlyclean-am clean-am: clean-noinstLIBRARIES clean-compile clean-noinstPROGRAMS \ clean-tags clean-generic mostlyclean-am clean: clean-am distclean-am: distclean-noinstLIBRARIES distclean-compile \ distclean-noinstPROGRAMS distclean-tags \ distclean-generic clean-am distclean: distclean-am maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean-compile \ maintainer-clean-noinstPROGRAMS maintainer-clean-tags \ maintainer-clean-generic distclean-am @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." maintainer-clean: maintainer-clean-am .PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile mostlyclean-noinstPROGRAMS \ distclean-noinstPROGRAMS clean-noinstPROGRAMS \ maintainer-clean-noinstPROGRAMS tags mostlyclean-tags distclean-tags \ clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ check-am installcheck-am installcheck install-exec-am install-exec \ install-data-am install-data install-am install uninstall-am uninstall \ all-redirect all-am all installdirs mostlyclean-generic \ distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean distclean maintainer-clean dgenfont.cpp: pbm2df dgenfont.pbm ./pbm2df dgenfont.pbm dgenfont.cpp # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: dgen-sdl-1.23/sdl/Makefile.am 644 1750 1750 535 7241313704 11057 # DGen/SDL v1.20+ # SDL Interface EXTRA_DIST = dgenfont.pbm chartfont.c INCLUDES += -I.. noinst_PROGRAMS = pbm2df noinst_LIBRARIES = libpd.a # built sources BUILT_SOURCES = dgenfont.cpp dgenfont.cpp: pbm2df dgenfont.pbm ./pbm2df dgenfont.pbm dgenfont.cpp # pd.a libpd_a_SOURCES = font.cpp dgenfont.cpp sdl.cpp font.h pd-defs.h ogl_fonts.h dgen-sdl-1.23/sdl/font.cpp 644 1750 1750 4030 7241272640 10512 // DGen/SDL v1.14+ // by Joe Groff // How's my programming? E-mail /* DGen's font renderer. * I hope it's pretty well detached from the DGen core, so you can use it in * any other SDL app you like. */ /* Also note that these font renderers do no error detection, and absolutely * NO clipping whatsoever, so try to keep the glyphs on-screen. Thank you :-) */ #include #include #include #include #include "font.h" /* The interface functions */ extern int *dgen_font[]; // Support function // Put a glyph at the specified coordinates // THIS IS REALLY A MACRO - SDL_LockSurface should have been called already if // necessary static inline void _putglyph(char *p, int Bpp, int pitch, char which) { int *glyph = dgen_font[which]; int x = 0, i; for(; *glyph != -1; ++glyph) { p += (((x += *glyph) >> 3) * pitch); x &= 7; for(i = 0; i < Bpp; ++i) p[(x * Bpp) + i] = 0xff; } } // This writes a string of text at the given x and y coordinates void font_text(SDL_Surface *surf, int x, int y, const char *message) { int pitch = surf->pitch, Bpp = surf->format->BytesPerPixel; char *p = (char*)surf->pixels + (pitch * y) + (Bpp * x); if(SDL_MUSTLOCK(surf)) if(SDL_LockSurface(surf) < 0) { fprintf(stderr, "font: Couldn't lock screen: %s!", SDL_GetError()); return; } for(; *message; p += (8 * Bpp), ++message) _putglyph(p, Bpp, pitch, *message); if(SDL_MUSTLOCK(surf)) SDL_UnlockSurface(surf); } // This writes a string of text of fixed length n void font_text_n(SDL_Surface *surf, int x, int y, const char *message, int n) { int pitch = surf->pitch, Bpp = surf->format->BytesPerPixel; char *p = (char*)surf->pixels + (pitch * y) + (Bpp * x); if(SDL_MUSTLOCK(surf)) if(SDL_LockSurface(surf) < 0) { fprintf(stderr, "font: Couldn't lock screen: %s!", SDL_GetError()); return; } for(; n > 0; p += (8 * Bpp), ++message, --n) _putglyph(p, Bpp, pitch, *message); if(SDL_MUSTLOCK(surf)) SDL_UnlockSurface(surf); } dgen-sdl-1.23/sdl/dgenfont.cpp 644 1750 1750 21726 7320166720 11402 /* DGen font, generated by pbm2df from "dgenfont.pbm" */ #include /* for NULL definition */ static int _glyph_20[] = {-1}; static int _glyph_21[] = {19, 8, 8, 8, 8, 8, 8, 16, -1}; static int _glyph_22[] = {18, 3, 5, 3, 5, 3, -1}; static int _glyph_23[] = {26, 3, 5, 3, 4, 1, 1, 1, 1, 1, 4, 3, 4, 1, 1, 1, 1, 1, 4, 3, 5, 3, -1}; static int _glyph_24[] = {27, 7, 1, 1, 1, 4, 2, 7, 1, 1, 7, 2, 4, 1, 1, 1, 7, -1}; static int _glyph_25[] = {18, 4, 3, 2, 3, 4, 3, 7, 8, 7, 7, 3, 5, 2, 2, 3, 4, -1}; static int _glyph_26[] = {34, 1, 6, 3, 5, 3, 6, 1, 6, 3, 2, 3, 4, 5, 1, 1, 2, -1}; static int _glyph_27[] = {18, 1, 1, 6, 1, 6, -1}; static int _glyph_28[] = {21, 7, 8, 7, 8, 8, 9, 8, 9, -1}; static int _glyph_29[] = {18, 9, 8, 9, 8, 8, 7, 8, 7, -1}; static int _glyph_2A[] = {34, 3, 6, 1, 5, 1, 1, 1, 1, 1, 5, 1, 6, 3, -1}; static int _glyph_2B[] = {35, 8, 6, 1, 1, 1, 1, 6, 8, -1}; static int _glyph_2C[] = {74, 1, 1, 6, 1, 6, -1}; static int _glyph_2D[] = {49, 1, 1, 1, 1, 1, -1}; static int _glyph_2E[] = {75, 7, 1, 1, 7, -1}; static int _glyph_2F[] = {22, 8, 7, 7, 7, 7, 7, 7, 8, -1}; static int _glyph_30[] = {19, 1, 6, 3, 4, 5, 3, 5, 3, 5, 3, 5, 3, 5, 4, 3, 6, 1, -1}; static int _glyph_31[] = {19, 7, 1, 6, 2, 8, 8, 8, 8, 8, 6, 1, 1, 1, 1, -1}; static int _glyph_32[] = {18, 1, 1, 1, 4, 5, 3, 5, 8, 7, 6, 1, 6, 7, 8, 1, 1, 1, 1, 1, -1}; static int _glyph_33[] = {17, 1, 1, 1, 1, 1, 8, 7, 7, 7, 1, 1, 9, 8, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_34[] = {21, 7, 1, 6, 2, 5, 3, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 7, 8, -1}; static int _glyph_35[] = {17, 1, 1, 1, 1, 1, 3, 8, 8, 2, 1, 1, 4, 1, 4, 8, 8, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_36[] = {19, 1, 1, 5, 7, 8, 8, 2, 1, 1, 4, 1, 4, 3, 5, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_37[] = {17, 1, 1, 1, 1, 1, 8, 7, 7, 8, 7, 8, 7, 8, -1}; static int _glyph_38[] = {18, 1, 1, 1, 4, 5, 3, 5, 3, 5, 4, 1, 1, 1, 4, 5, 3, 5, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_39[] = {18, 1, 1, 1, 4, 5, 3, 5, 3, 4, 1, 4, 1, 1, 2, 8, 8, 7, 5, 1, 1, -1}; static int _glyph_3A[] = {35, 7, 1, 1, 7, 24, 7, 1, 1, 7, -1}; static int _glyph_3B[] = {35, 7, 1, 1, 7, 23, 1, 1, 6, 1, 6, -1}; static int _glyph_3C[] = {22, 7, 7, 7, 7, 9, 9, 9, 9, -1}; static int _glyph_3D[] = {41, 1, 1, 1, 1, 1, 19, 1, 1, 1, 1, 1, -1}; static int _glyph_3E[] = {17, 9, 9, 9, 9, 7, 7, 7, 7, -1}; static int _glyph_3F[] = {18, 1, 1, 1, 4, 5, 3, 5, 8, 7, 7, 8, 16, -1}; static int _glyph_40[] = {18, 1, 1, 1, 4, 5, 3, 5, 3, 3, 1, 1, 3, 2, 3, 3, 2, 2, 1, 3, 3, 2, 3, 9, 1, 1, 1, -1}; static int _glyph_41[] = {19, 1, 6, 3, 4, 5, 3, 5, 3, 5, 3, 1, 1, 1, 1, 1, 3, 5, 3, 5, 3, 5, -1}; static int _glyph_42[] = {16, 1, 1, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 1, 1, 1, 1, 4, 5, 3, 5, 3, 5, 2, 1, 1, 1, 1, 1, -1}; static int _glyph_43[] = {18, 1, 1, 1, 4, 5, 3, 8, 8, 8, 8, 8, 5, 4, 1, 1, 1, -1}; static int _glyph_44[] = {16, 1, 1, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 2, 1, 1, 1, 1, 1, -1}; static int _glyph_45[] = {17, 1, 1, 1, 1, 1, 3, 8, 8, 8, 1, 1, 1, 5, 8, 8, 8, 1, 1, 1, 1, 1, -1}; static int _glyph_46[] = {17, 1, 1, 1, 1, 1, 3, 8, 8, 8, 1, 1, 1, 5, 8, 8, 8, -1}; static int _glyph_47[] = {18, 1, 1, 1, 4, 5, 3, 8, 8, 8, 3, 1, 1, 3, 5, 3, 4, 1, 4, 1, 1, 2, -1}; static int _glyph_48[] = {17, 5, 3, 5, 3, 5, 3, 5, 3, 1, 1, 1, 1, 1, 3, 5, 3, 5, 3, 5, 3, 5, -1}; static int _glyph_49[] = {17, 1, 1, 1, 1, 6, 8, 8, 8, 8, 8, 8, 6, 1, 1, 1, 1, -1}; static int _glyph_4A[] = {19, 1, 1, 1, 7, 8, 8, 8, 8, 8, 4, 4, 5, 1, 1, -1}; static int _glyph_4B[] = {17, 5, 3, 4, 4, 3, 5, 2, 6, 1, 7, 2, 6, 3, 5, 4, 4, 5, -1}; static int _glyph_4C[] = {17, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, -1}; static int _glyph_4D[] = {16, 6, 2, 6, 2, 1, 4, 1, 2, 2, 2, 2, 2, 3, 3, 2, 3, 3, 2, 6, 2, 6, 2, 6, -1}; static int _glyph_4E[] = {17, 5, 3, 5, 3, 1, 4, 3, 2, 3, 3, 3, 2, 3, 4, 1, 3, 5, 3, 5, 3, 5, -1}; static int _glyph_4F[] = {18, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_50[] = {17, 1, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 1, 1, 1, 1, 4, 8, 8, 8, -1}; static int _glyph_51[] = {18, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 2, 3, 3, 3, 2, 4, 1, 1, 1, 9, -1}; static int _glyph_52[] = {17, 1, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 1, 1, 1, 1, 4, 2, 6, 3, 5, 4, 4, 5, -1}; static int _glyph_53[] = {18, 1, 1, 1, 4, 5, 3, 8, 9, 1, 1, 1, 9, 8, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_54[] = {16, 1, 1, 1, 1, 1, 1, 5, 8, 8, 8, 8, 8, 8, 8, -1}; static int _glyph_55[] = {17, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_56[] = {16, 6, 2, 6, 3, 4, 4, 4, 4, 4, 5, 2, 6, 2, 6, 2, 7, -1}; static int _glyph_57[] = {16, 6, 2, 6, 2, 6, 2, 6, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 2, 2, 2, 3, 4, -1}; static int _glyph_58[] = {16, 6, 2, 6, 3, 4, 5, 2, 7, 7, 2, 5, 4, 3, 6, 2, 6, -1}; static int _glyph_59[] = {16, 6, 2, 6, 3, 4, 5, 2, 7, 8, 8, 8, 8, -1}; static int _glyph_5A[] = {17, 1, 1, 1, 1, 1, 8, 7, 7, 7, 7, 7, 8, 8, 1, 1, 1, 1, 1, -1}; static int _glyph_5B[] = {18, 1, 1, 1, 5, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, -1}; static int _glyph_5C[] = {16, 8, 9, 9, 9, 9, 9, 9, 8, -1}; static int _glyph_5D[] = {17, 1, 1, 1, 8, 8, 8, 8, 8, 8, 8, 5, 1, 1, 1, -1}; static int _glyph_5E[] = {19, 7, 2, 5, 4, -1}; static int _glyph_5F[] = {88, 1, 1, 1, 1, 1, 1, -1}; static int _glyph_60[] = {18, 1, 1, 7, 1, 9, -1}; static int _glyph_61[] = {42, 1, 1, 1, 9, 4, 1, 1, 1, 1, 3, 5, 3, 4, 1, 4, 1, 1, 2, -1}; static int _glyph_62[] = {17, 8, 8, 8, 2, 1, 1, 4, 1, 4, 3, 5, 3, 5, 3, 1, 4, 3, 2, 1, 1, -1}; static int _glyph_63[] = {42, 1, 1, 1, 4, 5, 3, 8, 8, 5, 4, 1, 1, 1, -1}; static int _glyph_64[] = {22, 8, 8, 4, 1, 1, 2, 3, 4, 1, 3, 5, 3, 5, 3, 4, 1, 4, 1, 1, 2, -1}; static int _glyph_65[] = {42, 1, 1, 1, 4, 5, 3, 1, 1, 1, 1, 1, 3, 8, 5, 4, 1, 1, 1, -1}; static int _glyph_66[] = {19, 1, 1, 5, 4, 4, 8, 7, 1, 1, 1, 1, 5, 8, 8, 8, -1}; static int _glyph_67[] = {42, 1, 1, 2, 3, 4, 4, 4, 5, 1, 1, 5, 9, 1, 1, 1, 4, 5, 4, 1, 1, 1, -1}; static int _glyph_68[] = {17, 8, 8, 8, 2, 1, 1, 4, 1, 4, 3, 5, 3, 5, 3, 5, 3, 5, -1}; static int _glyph_69[] = {27, 15, 1, 8, 8, 8, 8, 6, 1, 1, 1, 1, -1}; static int _glyph_6A[] = {29, 15, 1, 8, 8, 8, 8, 4, 4, 4, 4, 5, 1, 1, -1}; static int _glyph_6B[] = {17, 8, 8, 8, 4, 4, 3, 5, 1, 1, 6, 3, 5, 4, 4, 5, -1}; static int _glyph_6C[] = {18, 1, 8, 8, 8, 8, 8, 8, 8, 6, 1, 1, 1, 1, -1}; static int _glyph_6D[] = {40, 1, 1, 2, 1, 3, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 6, -1}; static int _glyph_6E[] = {41, 2, 1, 1, 4, 1, 4, 3, 5, 3, 5, 3, 5, 3, 5, -1}; static int _glyph_6F[] = {42, 1, 1, 1, 4, 5, 3, 5, 3, 5, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_70[] = {41, 2, 1, 1, 4, 1, 4, 3, 5, 3, 1, 4, 3, 2, 1, 1, 4, 8, 8, -1}; static int _glyph_71[] = {42, 1, 1, 2, 3, 4, 1, 3, 5, 3, 4, 1, 4, 1, 1, 2, 8, 8, 8, -1}; static int _glyph_72[] = {41, 2, 1, 1, 5, 4, 4, 8, 8, 8, -1}; static int _glyph_73[] = {42, 1, 1, 1, 4, 5, 4, 1, 9, 1, 4, 5, 4, 1, 1, 1, -1}; static int _glyph_74[] = {26, 8, 7, 1, 1, 1, 1, 5, 8, 8, 8, 4, 5, 1, 1, -1}; static int _glyph_75[] = {41, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 1, 1, 2, -1}; static int _glyph_76[] = {41, 4, 4, 4, 4, 4, 5, 2, 6, 2, 7, -1}; static int _glyph_77[] = {40, 6, 2, 6, 2, 3, 3, 2, 3, 3, 2, 2, 2, 2, 3, 4, -1}; static int _glyph_78[] = {41, 5, 4, 3, 6, 1, 7, 1, 6, 3, 4, 5, -1}; static int _glyph_79[] = {41, 5, 3, 5, 3, 5, 3, 4, 1, 4, 1, 1, 2, 8, 3, 5, 4, 1, 1, 1, -1}; static int _glyph_7A[] = {41, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, -1}; static int _glyph_7B[] = {20, 1, 1, 5, 8, 9, 6, 1, 9, 7, 8, 9, 1, 1, -1}; static int _glyph_7C[] = {19, 8, 8, 8, 8, 8, 8, 8, 8, -1}; static int _glyph_7D[] = {17, 1, 1, 9, 8, 7, 9, 1, 6, 9, 8, 5, 1, 1, -1}; static int _glyph_7E[] = {18, 3, 4, 2, 2, 4, 3, -1}; static int _glyph_7F[] = {-1}; int *dgen_font[] = { /* Fill in for the control characters */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, _glyph_20, _glyph_21, _glyph_22, _glyph_23, _glyph_24, _glyph_25, _glyph_26, _glyph_27, _glyph_28, _glyph_29, _glyph_2A, _glyph_2B, _glyph_2C, _glyph_2D, _glyph_2E, _glyph_2F, _glyph_30, _glyph_31, _glyph_32, _glyph_33, _glyph_34, _glyph_35, _glyph_36, _glyph_37, _glyph_38, _glyph_39, _glyph_3A, _glyph_3B, _glyph_3C, _glyph_3D, _glyph_3E, _glyph_3F, _glyph_40, _glyph_41, _glyph_42, _glyph_43, _glyph_44, _glyph_45, _glyph_46, _glyph_47, _glyph_48, _glyph_49, _glyph_4A, _glyph_4B, _glyph_4C, _glyph_4D, _glyph_4E, _glyph_4F, _glyph_50, _glyph_51, _glyph_52, _glyph_53, _glyph_54, _glyph_55, _glyph_56, _glyph_57, _glyph_58, _glyph_59, _glyph_5A, _glyph_5B, _glyph_5C, _glyph_5D, _glyph_5E, _glyph_5F, _glyph_60, _glyph_61, _glyph_62, _glyph_63, _glyph_64, _glyph_65, _glyph_66, _glyph_67, _glyph_68, _glyph_69, _glyph_6A, _glyph_6B, _glyph_6C, _glyph_6D, _glyph_6E, _glyph_6F, _glyph_70, _glyph_71, _glyph_72, _glyph_73, _glyph_74, _glyph_75, _glyph_76, _glyph_77, _glyph_78, _glyph_79, _glyph_7A, _glyph_7B, _glyph_7C, _glyph_7D, _glyph_7E, _glyph_7F }; dgen-sdl-1.23/sdl/sdl.cpp 644 1750 1750 73700 7320164561 10360 // DGen/SDL v1.21+ // SDL interface // OpenGL code added by Andre Duarte de Souza #include #include #include #include #include #include #include #ifdef SDL_OPENGL_SUPPORT # include # include "ogl_fonts.h" #endif #include "md.h" #include "rc.h" #include "rc-vars.h" #include "pd.h" #include "pd-defs.h" #include "font.h" #ifdef SDL_OPENGL_SUPPORT // Defines for RGBA # define R 0 # define G 1 # define B 2 # define A 3 // Constant alpha value # define Alpha 255 // Width and height of screen # define XRES xs # define YRES ys // Where tex (256x256) ends in x // (256/320 == 512/640. 512-320 == 192 (Negative half ignored). // Positive tex end pos (range from 0.0 to 1.0 (0 to 320) in x) == 192/320) static double tex_end = (double)192/320; // Framebuffer textures static unsigned char mybuffer[256][256][4]; static unsigned char mybufferb[256][64][4]; // Textures (one 256x256 and on 64x256 => 320x256) static GLuint texture[2]; // xtabs for faster buffer access static int xtab[321]; // x - 256 for the 64x256 texture static int x4tab_r[321], x4tab_g[321], x4tab_b[321]; // x*4 (RGBA) // Display list static GLuint dlist; // Texture pitches static int mypitch = 256*4, mypitchb = 64*4; // Is OpenGL mode enabled? static int opengl = 0; // Text static unsigned char message[5][256][4]; static unsigned char m_clear[256][5][4]; #endif // SDL_OPENGL_SUPPORT // Bad hack- extern slot etc. from main.cpp so we can save/load states extern int slot; void md_save(md &megad); void md_load(md &megad); // Temp space static char temp[256]; // Define externed variables struct bmap mdscr; unsigned char *mdpal = NULL; struct sndinfo sndi; char *pd_options = "fX:Y:S:" #ifdef SDL_OPENGL_SUPPORT "G:" #endif ; // Define our personal variables // Graphics static SDL_Surface *screen = NULL; static SDL_Color colors[64]; static int ysize = 0, fullscreen = 0, bytes_pixel = 0, pal_mode = 0; static int x_scale = 1, y_scale = 1, xs, ys; // Sound static SDL_AudioSpec spec; static int snd_rate, snd_segs, snd_16bit, snd_buf; static volatile int snd_read = 0; static Uint8 *playbuf = NULL; // Messages static volatile int sigalrm_happened = 0; #ifdef SDL_JOYSTICK_SUPPORT // Extern joystick stuff extern int js_map_button[2][16]; #endif // Number of seconds to sustain messages #define MESSAGE_LIFE 3 // Catch SIGALRM static void sigalrm_handler(int) { sigalrm_happened = 1; } // Screenshots, thanks to Allan Noe static void do_screenshot(void) { char fname[20], msg[80], *ok; static int n = 0; int x; FILE *fp; #ifdef SDL_OPENGL_SUPPORT if(opengl) { pd_message("Screenshot not supported in OpenGL mode"); return; } #endif for(;;) { sprintf(fname, "shot%04d.bmp", n); if ((fp = fopen(fname, "r")) == NULL) break; else fclose(fp); if (++n > 9999) { pd_message("No more screenshot filenames!"); return; } } x = SDL_SaveBMP(screen, fname); if(x) pd_message("Screenshot failed!"); else { sprintf(msg, "Screenshot written to %s", fname); pd_message(msg); } } // Document the -f switch void pd_help() { printf( " -f Attempt to run fullscreen.\n" " -X scale Scale the screen in the X direction.\n" " -Y scale Scale the screen in the Y direction.\n" " -S scale Scale the screen by the same amount in both directions.\n" #ifdef SDL_OPENGL_SUPPORT " -G XxY Use OpenGL mode, with width X and height Y.\n" #endif ); } // Handle the switches void pd_option(char c, const char *) { // Set stuff up from the rcfile first, so we can override it with commandline // options fullscreen = dgen_fullscreen; x_scale = y_scale = dgen_scale; #ifdef SDL_OPENGL_SUPPORT opengl = dgen_opengl; if(opengl) { xs = dgen_opengl_width; ys = dgen_opengl_height; } #endif if(c == 'f') fullscreen = !fullscreen; if(c == 'X') x_scale = atoi(optarg); if(c == 'Y') y_scale = atoi(optarg); if(c == 'S') x_scale = y_scale = atoi(optarg); #ifdef SDL_OPENGL_SUPPORT if(c == 'G') { sscanf(optarg, " %d x %d ", &xs, &ys); opengl = 1; } #endif } #ifdef SDL_OPENGL_SUPPORT static void maketex(int num, int size) { glGenTextures(num,&texture[num-1]); glBindTexture(GL_TEXTURE_2D,texture[num-1]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); switch (num) { case 1: glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,size,256,0,GL_RGBA, GL_UNSIGNED_BYTE, mybuffer); break; case 2: glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,size,256,0,GL_RGBA, GL_UNSIGNED_BYTE, mybufferb); break; }; } static void makedlist() { int i; dlist=glGenLists(1); glNewList(dlist,GL_COMPILE); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); // 256x256 glBindTexture(GL_TEXTURE_2D, texture[0]); glBegin(GL_QUADS); glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0); // upper left glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left glTexCoord2f(1.0,0.0); glVertex2f(tex_end,1.0); // lower right glTexCoord2f(1.0,1.0); glVertex2f(tex_end,-1.0); // upper right glEnd(); // 64x256 glBindTexture(GL_TEXTURE_2D, texture[1]); glBegin(GL_QUADS); glTexCoord2f(0.0,1.0); glVertex2f(tex_end,-1.0); // upper left glTexCoord2f(0.0,0.0); glVertex2f(tex_end,1.0); // lower left glTexCoord2f(1.0,0.0); glVertex2f(1.0,1.0); // lower right glTexCoord2f(1.0,1.0); glVertex2f(1.0,-1.0); // upper right glEnd(); glDisable(GL_TEXTURE_2D); glEndList(); } static void init_textures() { int i,j; // First, the x tables (for a little faster access) for (i=256;i<321;i++) xtab[i]=i-256; for (i=0;i<321;i++) { x4tab_r[i]=(i*4)+2; x4tab_g[i]=(i*4)+1; x4tab_b[i]=i*4; } // Constant Alpha for (j=0;j<256;j++) for (i=0;i<320;i++) { if (i<256) mybuffer[j][i][A]=Alpha; else mybufferb[j][i-256][A]=Alpha; } // Clear Message Buffer for (j=0;j<256;j++) for (i=0;i<5;i++) { m_clear[i][j][R]=m_clear[i][j][G]=m_clear[i][j][B]=0; m_clear[i][j][A]=255; } // Dithering glEnable(GL_DITHER); // Anti-aliasing glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glClearColor(1.0,1.0,1.0,1.0); glShadeModel(GL_FLAT); maketex(1,256); maketex(2,64); makedlist(); } static void display() { glCallList(dlist); SDL_GL_SwapBuffers(); } #endif // SDL_OPENGL_SUPPORT // Initialize SDL, and the graphics int pd_graphics_init(int want_sound, int want_pal) { SDL_Color color; pal_mode = want_pal; /* Neither scale value may be 0 or negative */ if(x_scale <= 0) x_scale = 1; if(y_scale <= 0) y_scale = 1; if(SDL_Init(want_sound? (SDL_INIT_VIDEO | SDL_INIT_AUDIO) : (SDL_INIT_VIDEO))) { fprintf(stderr, "sdl: Couldn't init SDL: %s!\n", SDL_GetError()); return 0; } atexit(SDL_Quit); ysize = (want_pal? 240 : 224); // Set screen size vars #ifdef SDL_OPENGL_SUPPORT if(!opengl) #endif xs = 320*x_scale, ys = ysize*y_scale; // Make a 320x224 or 320x240 display for the MegaDrive, with an extra 16 lines // for the message bar. #ifdef SDL_OPENGL_SUPPORT if(opengl) screen = SDL_SetVideoMode(xs, ys, 0, fullscreen? (SDL_HWPALETTE | SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_FULLSCREEN) : (SDL_HWPALETTE | SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER)); else #endif screen = SDL_SetVideoMode(xs, ys + 16, 0, fullscreen? (SDL_HWPALETTE | SDL_HWSURFACE | SDL_FULLSCREEN) : (SDL_HWPALETTE | SDL_HWSURFACE)); if(!screen) { fprintf(stderr, "sdl: Couldn't set %dx%d video mode: %s!", xs, ys, SDL_GetError()); return 0; } // We don't need setuid priveledges anymore if(getuid() != geteuid()) setuid(getuid()); // Set the titlebar SDL_WM_SetCaption("DGen "VER, "dgen"); // Hide the cursor SDL_ShowCursor(0); #ifdef SDL_OPENGL_SUPPORT if(opengl) init_textures(); #endif #ifdef SDL_OPENGL_SUPPORT if(!opengl) #endif // If we're in 8 bit mode, set color 0xff to white for the text, // and make a palette buffer if(screen->format->BitsPerPixel == 8) { color.r = color.g = color.b = 0xff; SDL_SetColors(screen, &color, 0xff, 1); mdpal = (unsigned char*)malloc(256); if(!mdpal) { fprintf(stderr, "sdl: Couldn't allocate palette!\n"); return 0; } } // Ignore events besides quit and keyboard SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE); SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE); SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); // Set up the MegaDrive screen #ifdef SDL_OPENGL_SUPPORT if(opengl) bytes_pixel = 4; else #endif bytes_pixel = screen->format->BytesPerPixel; mdscr.w = 320 + 16; mdscr.h = ysize + 16; #ifdef SDL_OPENGL_SUPPORT if(opengl) mdscr.bpp = 32; else #endif mdscr.bpp = screen->format->BitsPerPixel; mdscr.pitch = mdscr.w * bytes_pixel; mdscr.data = (unsigned char*) malloc(mdscr.pitch * mdscr.h); if(!mdscr.data) { fprintf(stderr, "sdl: Couldn't allocate screen!\n"); return 0; } // Set SIGALRM handler (used to clear messages after 3 seconds) signal(SIGALRM, sigalrm_handler); // And that's it! :D return 1; } // Update palette void pd_graphics_palette_update() { int i; for(i = 0; i < 64; ++i) { colors[i].r = mdpal[(i << 2) ]; colors[i].g = mdpal[(i << 2)+1]; colors[i].b = mdpal[(i << 2)+2]; } #ifdef SDL_OPENGL_SUPPORT if(!opengl) #endif SDL_SetColors(screen, colors, 0, 64); } #ifdef SDL_OPENGL_SUPPORT void update_textures() { int i,x,y; int c,x2; glBindTexture(GL_TEXTURE_2D,texture[0]); glTexSubImage2D(GL_TEXTURE_2D,0,0,15,256,224,GL_RGBA,GL_UNSIGNED_BYTE,mybuffer); glBindTexture(GL_TEXTURE_2D,texture[1]); glTexSubImage2D(GL_TEXTURE_2D,0,0,15,64,224,GL_RGBA,GL_UNSIGNED_BYTE,mybufferb); display(); } #endif // Update screen // This code is fairly transmittable to any linear display, just change p to // point to your favorite raw framebuffer. ;) But planar buffers are a // completely different deal... // Anyway, feel free to use it in your implementation. :) void pd_graphics_update() { static int f = 0; int i, j, k; unsigned char *p, *q; #ifdef SDL_OPENGL_SUPPORT int x, y, x2; unsigned char *pb, *qb; #endif // If you need to do any sort of locking before writing to the buffer, do so // here. if(SDL_MUSTLOCK(screen)) SDL_LockSurface(screen); // If SIGALRM was tripped, clear message if(sigalrm_happened) { sigalrm_happened = 0; pd_clear_message(); } #ifdef SDL_OPENGL_SUPPORT if(!opengl) #endif p = (unsigned char*)screen->pixels; // 2696 = 336 * 8 + 8. 336 should be the width of mdscr, so we move 8 pixels // down and 8 to the right to skip the messy border. q = (unsigned char*)mdscr.data + 2696 * bytes_pixel; for(i = 0; i < ysize; ++i) { #ifdef SDL_OPENGL_SUPPORT if(opengl) { // Copy, converting from BGRA to RGBA for(x = 0; x < 320; ++x) { if(x < 256) { mybuffer[i][x][R] = *(q + x4tab_r[x]); mybuffer[i][x][G] = *(q + x4tab_g[x]); mybuffer[i][x][B] = *(q + x4tab_b[x]); } else if(x < 320) { mybufferb[i][xtab[x]][R] = *(q + x4tab_r[x]); mybufferb[i][xtab[x]][G] = *(q + x4tab_g[x]); mybufferb[i][xtab[x]][B] = *(q + x4tab_b[x]); } } } else { #endif // SDL_OPENGL_SUPPORT #ifdef ASM_CTV if(dgen_craptv) switch(dgen_craptv) { // Blur, by Dave case CTV_BLUR: if(mdscr.bpp == 16) blur_bitmap_16(q, 319); else if(mdscr.bpp == 15) blur_bitmap_15(q, 319); break; // Scanline, by Phil case CTV_SCANLINE: if((i & 1) && (mdscr.bpp == 16 || mdscr.bpp == 15)) test_ctv(q, 320); break; // Interlace, a hacked form of Scanline by me :) case CTV_INTERLACE: if((i & 1) ^ (++f & 1) && (mdscr.bpp == 16 || mdscr.bpp == 15)) test_ctv(q, 320); break; default: break; } #endif // ASM_CTV if(x_scale == 1) { if(y_scale == 1) { memcpy(p, q, 320 * bytes_pixel); p += screen->pitch; } else { for(j = 0; j < y_scale; ++j) { memcpy(p, q, 320 * bytes_pixel); p += screen->pitch; } } } else { /* Stretch the scanline out */ switch(bytes_pixel) { case 1: { unsigned char *pp = p, *qq = q; for(j = 0; j < 320; ++j, ++qq) for(k = 0; k < x_scale; ++k) *(pp++) = *qq; if(y_scale != 1) for(pp = p, j = 1; j < y_scale; ++j) { p += screen->pitch; memcpy(p, pp, xs); } } break; case 2: { short *pp = (short*)p, *qq = (short*)q; for(j = 0; j < 320; ++j, ++qq) for(k = 0; k < x_scale; ++k) *(pp++) = *qq; if(y_scale != 1) for(pp = (short*)p, j = 1; j < y_scale; ++j) { p += screen->pitch; memcpy(p, pp, xs*2); } } break; case 3: /* FIXME */ break; case 4: { long *pp = (long*)p, *qq = (long*)q; for(j = 0; j < 320; ++j, ++qq) for(k = 0; k < x_scale; ++k) *(pp++) = *qq; if(y_scale != 1) for(pp = (long*)p, j = 1; j < y_scale; ++j) { p += screen->pitch; memcpy(p, pp, xs*4); } } break; } p += screen->pitch; } #ifdef SDL_OPENGL_SUPPORT } #endif q += mdscr.pitch; } // Unlock when you're done! if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); // Update the screen #ifdef SDL_OPENGL_SUPPORT if(opengl) update_textures(); else #endif SDL_UpdateRect(screen, 0, 0, xs, ys); } // Callback for sound static void _snd_callback(void*, Uint8 *stream, int len) { int i; // Slurp off the play buffer for(i = 0; i < len; ++i) { if(snd_read == snd_buf) snd_read = 0; stream[i] = playbuf[snd_read++]; } } // Initialize the sound int pd_sound_init(long &format, long &freq, long &segs) { SDL_AudioSpec wanted; // Set the desired format wanted.freq = freq; wanted.format = format; wanted.channels = 2; wanted.samples = 512; wanted.callback = _snd_callback; wanted.userdata = NULL; // Open audio, and get the real spec if(SDL_OpenAudio(&wanted, &spec) < 0) { fprintf(stderr, "sdl: Couldn't open audio: %s!\n", SDL_GetError()); return 0; } // Check everything if(spec.channels != 2) { fprintf(stderr, "sdl: Couldn't get stereo audio format!\n"); goto snd_error; } if(spec.format == PD_SND_16) snd_16bit = 1, format = PD_SND_16; else if(spec.format == PD_SND_8) snd_16bit = 0, format = PD_SND_8; else { fprintf(stderr, "sdl: Couldn't get a supported audio format!\n"); goto snd_error; } // Set things as they really are snd_rate = freq = spec.freq; sndi.len = spec.freq / (pal_mode? 50 : 60); if(segs <= 4) segs = snd_segs = 4; else if(segs <= 8) segs = snd_segs = 8; else if(segs <= 16) segs = snd_segs = 16; else segs = snd_segs = 32; // Calculate buffer size snd_buf = sndi.len * snd_segs * (snd_16bit? 4 : 2); --snd_segs; // Allocate play buffer if(!(sndi.l = (signed short*) malloc(sndi.len * sizeof(signed short))) || !(sndi.r = (signed short*) malloc(sndi.len * sizeof(signed short))) || !(playbuf = (Uint8*)malloc(snd_buf))) { fprintf(stderr, "sdl: Couldn't allocate sound buffers!\n"); goto snd_error; } // It's all good! return 1; snd_error: // Oops! Something bad happened, cleanup. SDL_CloseAudio(); if(sndi.l) free((void*)sndi.l); if(sndi.r) free((void*)sndi.r); if(playbuf) free((void*)playbuf); return 0; } // Start/stop audio processing void pd_sound_start() { SDL_PauseAudio(0); } void pd_sound_pause() { SDL_PauseAudio(1); } // Return segment we're currently playing from int pd_sound_rp() { return (snd_read / (sndi.len << (1+snd_16bit))) & snd_segs; } // Write contents of sndi to playbuf void pd_sound_write(int seg) { int i; signed short *w = (signed short*)(playbuf + seg * (sndi.len << (1+snd_16bit))); // Thanks Daniel Wislocki for this much improved audio loop :) if(!snd_16bit) { SDL_LockAudio(); for(i = 0; i < sndi.len; ++i) *w++ = ((sndi.l[i] & 0xFF00) + 0x8000) | ((sndi.r[i] >> 8) + 0x80); SDL_UnlockAudio(); } else { SDL_LockAudio(); for(i = 0; i < sndi.len; ++i) { *w++ = sndi.l[i]; *w++ = sndi.r[i]; } SDL_UnlockAudio(); } } // This is a small event loop to handle stuff when we're stopped. static int stop_events(md &/*megad*/) { SDL_Event event; // We still check key events, but we can wait for them while(SDL_WaitEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: // We can still quit :) if(event.key.keysym.sym == dgen_quit) return 0; else return 1; case SDL_QUIT: return 0; default: break; } } // SDL_WaitEvent only returns zero on error :( fprintf(stderr, "sdl: SDL_WaitEvent broke: %s!", SDL_GetError()); return 1; } // The massive event handler! // I know this is an ugly beast, but please don't be discouraged. If you need // help, don't be afraid to ask me how something works. Basically, just handle // all the event keys, or even ignore a few if they don't make sense for your // interface. int pd_handle_events(md &megad) { SDL_Event event; long ksym; // If there's any chance your implementation might run under Linux, add these // next four lines for joystick handling. #ifdef LINUX_JOYSTICK_SUPPORT if(dgen_joystick) megad.read_joysticks(); #endif // Check key events while(SDL_PollEvent(&event)) { switch(event.type) { #if SDL_JOYSTICK_SUPPORT case SDL_JOYAXISMOTION: // x-axis if(event.jaxis.axis == 0) { if(event.jaxis.value < -16384) { megad.pad[event.jaxis.which] &= ~0x04; megad.pad[event.jaxis.which] |= 0x08; break; } if(event.jaxis.value > 16384) { megad.pad[event.jaxis.which] |= 0x04; megad.pad[event.jaxis.which] &= ~0x08; break; } megad.pad[event.jaxis.which] |= 0xC; break; } // y-axis if(event.jaxis.axis == 1) { if(event.jaxis.value < -16384) { megad.pad[event.jaxis.which] &= ~0x01; megad.pad[event.jaxis.which] |= 0x02; break; } if(event.jaxis.value > 16384) { megad.pad[event.jaxis.which] |= 0x01; megad.pad[event.jaxis.which] &= ~0x02; break; } megad.pad[event.jaxis.which] |= 0x3; break; } break; case SDL_JOYBUTTONDOWN: // Ignore more than 16 buttons (a reasonable limit :) if(event.jbutton.button > 15) break; megad.pad[event.jbutton.which] &= ~js_map_button[event.jbutton.which] [event.jbutton.button]; break; case SDL_JOYBUTTONUP: // Ignore more than 16 buttons (a reasonable limit :) if(event.jbutton.button > 15) break; megad.pad[event.jbutton.which] |= js_map_button[event.jbutton.which] [event.jbutton.button]; break; #endif // SDL_JOYSTICK_SUPPORT case SDL_KEYDOWN: ksym = event.key.keysym.sym; // Check for modifiers if(event.key.keysym.mod & KMOD_SHIFT) ksym |= KEYSYM_MOD_SHIFT; if(event.key.keysym.mod & KMOD_CTRL) ksym |= KEYSYM_MOD_CTRL; if(event.key.keysym.mod & KMOD_ALT) ksym |= KEYSYM_MOD_ALT; if(event.key.keysym.mod & KMOD_META) ksym |= KEYSYM_MOD_META; // Check if it was a significant key that was pressed if(ksym == pad1_up) megad.pad[0] &= ~0x01; else if(ksym == pad1_down) megad.pad[0] &= ~0x02; else if(ksym == pad1_left) megad.pad[0] &= ~0x04; else if(ksym == pad1_right) megad.pad[0] &= ~0x08; else if(ksym == pad1_a) megad.pad[0] &= ~0x1000; else if(ksym == pad1_b) megad.pad[0] &= ~0x10; else if(ksym == pad1_c) megad.pad[0] &= ~0x20; else if(ksym == pad1_x) megad.pad[0] &= ~0x40000; else if(ksym == pad1_y) megad.pad[0] &= ~0x20000; else if(ksym == pad1_z) megad.pad[0] &= ~0x10000; else if(ksym == pad1_mode) megad.pad[0] &= ~0x80000; else if(ksym == pad1_start) megad.pad[0] &= ~0x2000; else if(ksym == pad2_up) megad.pad[1] &= ~0x01; else if(ksym == pad2_down) megad.pad[1] &= ~0x02; else if(ksym == pad2_left) megad.pad[1] &= ~0x04; else if(ksym == pad2_right) megad.pad[1] &= ~0x08; else if(ksym == pad2_a) megad.pad[1] &= ~0x1000; else if(ksym == pad2_b) megad.pad[1] &= ~0x10; else if(ksym == pad2_c) megad.pad[1] &= ~0x20; else if(ksym == pad2_x) megad.pad[1] &= ~0x40000; else if(ksym == pad2_y) megad.pad[1] &= ~0x20000; else if(ksym == pad2_z) megad.pad[1] &= ~0x10000; else if(ksym == pad2_mode) megad.pad[1] &= ~0x80000; else if(ksym == pad2_start) megad.pad[1] &= ~0x2000; else if(ksym == dgen_quit) return 0; // Split screen is unnecessary with new renderer. // else if(ksym == dgen_splitscreen_toggle) // { // split_screen = !split_screen; // pd_message(split_screen? "Split screen enabled." : // "Split screen disabled."); // } else if(ksym == dgen_craptv_toggle) { dgen_craptv = ((++dgen_craptv) % NUM_CTV); sprintf(temp, "Crap TV mode \"%s\".", ctv_names[dgen_craptv]); pd_message(temp); } else if(ksym == dgen_reset) { megad.reset(); pd_message("Genesis reset."); } else if(ksym == dgen_slot_0) { slot = 0; pd_message("Selected save slot 0."); } else if(ksym == dgen_slot_1) { slot = 1; pd_message("Selected save slot 1."); } else if(ksym == dgen_slot_2) { slot = 2; pd_message("Selected save slot 2."); } else if(ksym == dgen_slot_3) { slot = 3; pd_message("Selected save slot 3."); } else if(ksym == dgen_slot_4) { slot = 4; pd_message("Selected save slot 4."); } else if(ksym == dgen_slot_5) { slot = 5; pd_message("Selected save slot 5."); } else if(ksym == dgen_slot_6) { slot = 6; pd_message("Selected save slot 6."); } else if(ksym == dgen_slot_7) { slot = 7; pd_message("Selected save slot 7."); } else if(ksym == dgen_slot_8) { slot = 8; pd_message("Selected save slot 8."); } else if(ksym == dgen_slot_9) { slot = 9; pd_message("Selected save slot 9."); } else if(ksym == dgen_save) md_save(megad); else if(ksym == dgen_load) md_load(megad); // Added this CPU core hot swap. Compile both Musashi and StarScream // in, and swap on the fly like DirectX DGen. [PKH] #if defined (COMPILE_WITH_MUSA) && (COMPILE_WITH_STAR) else if(ksym == dgen_cpu_toggle) { if(megad.cpu_emu) { megad.change_cpu_emu(0); pd_message("StarScream CPU core activated."); } else { megad.change_cpu_emu(1); pd_message("Musashi CPU core activated."); } } #endif else if(ksym == dgen_stop) { pd_message("* STOPPED * Press any key to continue."); SDL_PauseAudio(1); // Stop audio :) #ifdef HAVE_SDL_WM_TOGGLEFULLSCREEN int fullscreen = 0; // Switch out of fullscreen mode (assuming this is supported) if(screen->flags & SDL_FULLSCREEN) { fullscreen = 1; SDL_WM_ToggleFullScreen(screen); } #endif int r = stop_events(megad); #ifdef HAVE_SDL_WM_TOGGLEFULLSCREEN if(fullscreen) SDL_WM_ToggleFullScreen(screen); #endif pd_clear_message(); if(r) SDL_PauseAudio(0); // Restart audio return r; } #ifdef HAVE_SDL_WM_TOGGLEFULLSCREEN else if(ksym == dgen_fullscreen_toggle) { SDL_WM_ToggleFullScreen(screen); pd_message("Fullscreen mode toggled."); } #endif else if(ksym == dgen_fix_checksum) { pd_message("Checksum fixed."); megad.fix_rom_checksum(); } else if(ksym == dgen_screenshot) { do_screenshot(); } break; case SDL_KEYUP: ksym = event.key.keysym.sym; // Check for modifiers if(event.key.keysym.mod & KMOD_SHIFT) ksym |= KEYSYM_MOD_SHIFT; if(event.key.keysym.mod & KMOD_CTRL) ksym |= KEYSYM_MOD_CTRL; if(event.key.keysym.mod & KMOD_ALT) ksym |= KEYSYM_MOD_ALT; if(event.key.keysym.mod & KMOD_META) ksym |= KEYSYM_MOD_META; // The only time we care about key releases is for the controls if(ksym == pad1_up) megad.pad[0] |= 0x01; else if(ksym == pad1_down) megad.pad[0] |= 0x02; else if(ksym == pad1_left) megad.pad[0] |= 0x04; else if(ksym == pad1_right) megad.pad[0] |= 0x08; else if(ksym == pad1_a) megad.pad[0] |= 0x1000; else if(ksym == pad1_b) megad.pad[0] |= 0x10; else if(ksym == pad1_c) megad.pad[0] |= 0x20; else if(ksym == pad1_x) megad.pad[0] |= 0x40000; else if(ksym == pad1_y) megad.pad[0] |= 0x20000; else if(ksym == pad1_z) megad.pad[0] |= 0x10000; else if(ksym == pad1_mode) megad.pad[0] |= 0x80000; else if(ksym == pad1_start) megad.pad[0] |= 0x2000; else if(ksym == pad2_up) megad.pad[1] |= 0x01; else if(ksym == pad2_down) megad.pad[1] |= 0x02; else if(ksym == pad2_left) megad.pad[1] |= 0x04; else if(ksym == pad2_right) megad.pad[1] |= 0x08; else if(ksym == pad2_a) megad.pad[1] |= 0x1000; else if(ksym == pad2_b) megad.pad[1] |= 0x10; else if(ksym == pad2_c) megad.pad[1] |= 0x20; else if(ksym == pad2_x) megad.pad[1] |= 0x40000; else if(ksym == pad2_y) megad.pad[1] |= 0x20000; else if(ksym == pad2_z) megad.pad[1] |= 0x10000; else if(ksym == pad2_mode) megad.pad[1] |= 0x80000; else if(ksym == pad2_start) megad.pad[1] |= 0x2000; break; case SDL_QUIT: // We've been politely asked to exit, so let's leave return 0; default: break; } } return 1; } #ifdef SDL_OPENGL_SUPPORT static void ogl_write_text(const char *msg) { int j, k, x; unsigned char c, *p; const char *q; char draw; for(q = msg, x = 0, draw = 1; *q; ++q, x += 7, draw = 1) { switch(*q) { case 'A': case 'a': p = font_a; break; case 'B': case 'b': p = font_b; break; case 'C': case 'c': p = font_c; break; case 'D': case 'd': p = font_d; break; case 'E': case 'e': p = font_e; break; case 'F': case 'f': p = font_f; break; case 'G': case 'g': p = font_g; break; case 'H': case 'h': p = font_h; break; case 'I': case 'i': p = font_i; break; case 'J': case 'j': p = font_j; break; case 'K': case 'k': p = font_k; break; case 'L': case 'l': p = font_l; break; case 'M': case 'm': p = font_m; break; case 'N': case 'n': p = font_n; break; case 'O': case 'o': p = font_o; break; case 'P': case 'p': p = font_p; break; case 'Q': case 'q': p = font_q; break; case 'R': case 'r': p = font_r; break; case 'S': case 's': p = font_s; break; case 'T': case 't': p = font_t; break; case 'U': case 'u': p = font_u; break; case 'V': case 'v': p = font_v; break; case 'W': case 'w': p = font_w; break; case 'X': case 'x': p = font_x; break; case 'Y': case 'y': p = font_y; break; case 'Z': case 'z': p = font_z; break; case '0': p = font_0; break; case '1': p = font_1; break; case '2': p = font_2; break; case '3': p = font_3; break; case '4': p = font_4; break; case '5': p = font_5; break; case '6': p = font_6; break; case '7': p = font_7; break; case '8': p = font_0; break; case '9': p = font_0; break; case '*': p = font_ast; break; case '!': p = font_ex; break; case '.': p = font_per; break; case '"': p = font_quot; break; case '\'': p = font_apos; break; case ' ': draw = 0; break; default: draw = 0; break; } if(draw) for(j = 0; j < 5; ++j) for(k = 0; k < 5; ++k) { if(p[k+j*5]) c = 255; else c = 0; message[j][k+x][R] = message[j][k+x][G] = message[j][k+x][B] = c; message[j][k+x][A] = 255; } } } #endif // SDL_OPENGL_SUPPORT // Write a message to the status bar void pd_message(const char *msg) { pd_clear_message(); #ifdef SDL_OPENGL_SUPPORT if(opengl) { ogl_write_text(msg); glBindTexture(GL_TEXTURE_2D, texture[0]); glTexSubImage2D(GL_TEXTURE_2D, 0,0,ys,256,5,GL_RGBA,GL_UNSIGNED_BYTE,message); } else { #endif font_text(screen, 0, ys, msg); SDL_UpdateRect(screen, 0, ys, xs, 16); #ifdef SDL_OPENGL_SUPPORT } #endif // Clear message in 3 seconds alarm(MESSAGE_LIFE); } inline void pd_clear_message() { int i, j; long *p = (long*)((char*)screen->pixels + (screen->pitch * ys)); #ifdef SDL_OPENGL_SUPPORT if(opengl) { memset(message,0,256*5*4); glBindTexture(GL_TEXTURE_2D, texture[0]); glTexSubImage2D(GL_TEXTURE_2D,0,0,ys,256,5,GL_RGBA,GL_UNSIGNED_BYTE,m_clear); } else { #endif for(i = 0; i < 16; ++i, p += (screen->pitch >> 2)) for(j = 0; j < 80 * screen->format->BytesPerPixel; ++j) p[j] = 0; SDL_UpdateRect(screen, 0, ys, xs, 16); #ifdef SDL_OPENGL_SUPPORT } #endif } /* FIXME: Implement this * Look at v1.16 to see how I did carthead there */ void pd_show_carthead(md&) { } /* Clean up this awful mess :) */ void pd_quit() { if(mdscr.data) free((void*)mdscr.data); if(playbuf) { SDL_CloseAudio(); free((void*)playbuf); } if(sndi.l) free((void*)sndi.l); if(sndi.r) free((void*)sndi.r); if(mdpal) free((void*)mdpal); } dgen-sdl-1.23/sdl/font.h 644 1750 1750 572 7241272640 10146 #ifndef __FONT_H__ #define __FONT_H__ // DGen/SDL v1.14+ // Font routine interface #include // Writes a string of text on the surface at given x any y coordinates void font_text(SDL_Surface *surf, int x, int y, const char *message); // Writes a string with given length void font_text_n(SDL_Surface *surf, int x, int y, const char *message, int n); #endif __FONT_H__ dgen-sdl-1.23/sdl/pd-defs.h 644 1750 1750 6750 7241272640 10546 #ifndef __SDL_PD_DEFS_H__ #define __SDL_PD_DEFS_H__ #include #include // Platform-dependent definitions and inlines. // In this file, you should define all the keysyms and audio formats, and // if you want to inline any functions, put them in here too. :) // There are two necessary formats: PD_SND_8, unsigned 8-bit audio, and // PD_SND_16, signed 16-bit audio in the same endianness as your CPU. #define PD_SND_8 AUDIO_U8 #ifdef WORDS_BIGENDIAN #define PD_SND_16 AUDIO_S16MSB #else #define PD_SND_16 AUDIO_S16LSB #endif // Now for a grueling list of keysyms. *muahahahahahaha* // Seriously, this is tedious, I realise, but don't be discouraged please. :) // Just remember I had to do it also. #define PDK_ESCAPE SDLK_ESCAPE #define PDK_1 SDLK_1 #define PDK_2 SDLK_2 #define PDK_3 SDLK_3 #define PDK_4 SDLK_4 #define PDK_5 SDLK_5 #define PDK_6 SDLK_6 #define PDK_7 SDLK_7 #define PDK_8 SDLK_8 #define PDK_9 SDLK_9 #define PDK_0 SDLK_0 #define PDK_MINUS SDLK_MINUS #define PDK_EQUALS SDLK_EQUALS #define PDK_BACKSPACE SDLK_BACKSPACE #define PDK_TAB SDLK_TAB #define PDK_q SDLK_q #define PDK_w SDLK_w #define PDK_e SDLK_e #define PDK_r SDLK_r #define PDK_t SDLK_t #define PDK_y SDLK_y #define PDK_u SDLK_u #define PDK_i SDLK_i #define PDK_o SDLK_o #define PDK_p SDLK_p #define PDK_LEFTBRACKET SDLK_LEFTBRACKET #define PDK_RIGHTBRACKET SDLK_RIGHTBRACKET #define PDK_RETURN SDLK_RETURN #define PDK_a SDLK_a #define PDK_s SDLK_s #define PDK_d SDLK_d #define PDK_f SDLK_f #define PDK_g SDLK_g #define PDK_h SDLK_h #define PDK_j SDLK_j #define PDK_k SDLK_k #define PDK_l SDLK_l #define PDK_SEMICOLON SDLK_SEMICOLON #define PDK_QUOTE SDLK_QUOTE #define PDK_BACKQUOTE SDLK_BACKQUOTE #define PDK_BACKSLASH SDLK_BACKSLASH #define PDK_z SDLK_z #define PDK_x SDLK_x #define PDK_c SDLK_c #define PDK_v SDLK_v #define PDK_b SDLK_b #define PDK_n SDLK_n #define PDK_m SDLK_m #define PDK_COMMA SDLK_COMMA #define PDK_PERIOD SDLK_PERIOD #define PDK_SLASH SDLK_SLASH #define PDK_KP_MULTIPLY SDLK_KP_MULTIPLY #define PDK_SPACE SDLK_SPACE #define PDK_F1 SDLK_F1 #define PDK_F2 SDLK_F2 #define PDK_F3 SDLK_F3 #define PDK_F4 SDLK_F4 #define PDK_F5 SDLK_F5 #define PDK_F6 SDLK_F6 #define PDK_F7 SDLK_F7 #define PDK_F8 SDLK_F8 #define PDK_F9 SDLK_F9 #define PDK_F10 SDLK_F10 #define PDK_KP7 SDLK_KP7 #define PDK_KP8 SDLK_KP8 #define PDK_KP9 SDLK_KP9 #define PDK_KP_MINUS SDLK_KP_MINUS #define PDK_KP4 SDLK_KP4 #define PDK_KP5 SDLK_KP5 #define PDK_KP6 SDLK_KP6 #define PDK_KP_PLUS SDLK_KP_PLUS #define PDK_KP1 SDLK_KP1 #define PDK_KP2 SDLK_KP2 #define PDK_KP3 SDLK_KP3 #define PDK_KP0 SDLK_KP0 #define PDK_KP_PERIOD SDLK_KP_PERIOD #define PDK_F11 SDLK_F11 #define PDK_F12 SDLK_F12 #define PDK_KP_ENTER SDLK_KP_ENTER #define PDK_KP_DIVIDE SDLK_KP_DIVIDE #define PDK_HOME SDLK_HOME #define PDK_UP SDLK_UP #define PDK_PAGEUP SDLK_PAGEUP #define PDK_LEFT SDLK_LEFT #define PDK_RIGHT SDLK_RIGHT #define PDK_END SDLK_END #define PDK_DOWN SDLK_DOWN #define PDK_PAGEDOWN SDLK_PAGEDOWN #define PDK_INSERT SDLK_INSERT #define PDK_DELETE SDLK_DELETE #define PDK_NUMLOCK SDLK_NUMLOCK #define PDK_CAPSLOCK SDLK_CAPSLOCK #define PDK_SCROLLOCK SDLK_SCROLLOCK #define PDK_LSHIFT SDLK_LSHIFT #define PDK_RSHIFT SDLK_RSHIFT #define PDK_LCTRL SDLK_LCTRL #define PDK_RCTRL SDLK_RCTRL #define PDK_LALT SDLK_LALT #define PDK_RALT SDLK_RALT #define PDK_LMETA SDLK_LMETA #define PDK_RMETA SDLK_RMETA // There, that wasn't so hard, was it? :) // If you want to inline any pd_ functions, put their bodies here. // Otherwise, you're done with this file! :D #endif // __SDL_PD_DEFS_H__ dgen-sdl-1.23/sdl/ogl_fonts.h 644 1750 1750 12604 7241312157 11227 static unsigned char font_a[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1 }; static unsigned char font_b[25] = { 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0 }; static unsigned char font_c[25] = { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 }; static unsigned char font_d[25] = { 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0 }; static unsigned char font_e[25] = { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 }; static unsigned char font_f[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }; static unsigned char font_g[25] = { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_h[25] = { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1 }; static unsigned char font_i[25] = { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 }; static unsigned char font_j[25] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_k[25] = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0 }; static unsigned char font_l[25] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 }; static unsigned char font_m[25] = { 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1 }; static unsigned char font_n[25] = { 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1 }; static unsigned char font_o[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_p[25] = { 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }; static unsigned char font_q[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1 }; static unsigned char font_r[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 }; static unsigned char font_s[25] = { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 }; static unsigned char font_t[25] = { 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }; static unsigned char font_u[25] = { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_v[25] = { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }; static unsigned char font_w[25] = { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_x[25] = { 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1 }; static unsigned char font_y[25] = { 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }; static unsigned char font_z[25] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1 }; static unsigned char font_0[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_1[25] = { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 }; static unsigned char font_2[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0 }; static unsigned char font_3[25] = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 }; static unsigned char font_4[25] = { 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 }; static unsigned char font_5[25] = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; static unsigned char font_6[25] = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; static unsigned char font_7[25] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 }; static unsigned char font_8[25] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0 }; static unsigned char font_9[25] = { 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; static unsigned char font_ast[25] = { 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1 }; static unsigned char font_quot[25] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char font_apos[25] = { 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char font_per[25] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; static unsigned char font_ex[25] = { 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; dgen-sdl-1.23/sdl/pbm2df.c 644 1750 1750 4413 7241272640 10363 /* This converts a PBM to a C header file containing a DGen font made from the * PBM. The PBM should be 768x13, with 8x13 cells which from left to right * are the glyphs from 0x20 (space) to 0x7f (character after ~). * The color 1 in the PBM is opaque, and 0 is transparent. */ #include #include #include int main(int argc, char *argv[]) { FILE *pbm, *df; unsigned int pbm_contents[768][13]; char magic[0x20], tmp[0x200]; int x,y, i,j; /* Open the pbm and read it */ if(argc < 3) { printf("Usage: %s pbmfile outfile\n", argv[0]); exit(2); } if(!(pbm = fopen(argv[1], "r"))) exit(1); fgets(magic, 0x20, pbm); /* Throw away possible comments */ do { fgets(tmp, 0x200, pbm); } while(*tmp == '#'); sscanf(tmp, "%d%d", &x, &y); /* Verify magic and dimensions */ if(strcmp(magic, "P1\n")) { printf("Bad magic\n"); return 1; } if(x != 768) { printf("Bad X dimension\n"); return 1; } if(y != 13) { printf("Bad Y dimension\n"); return 1; } for(y = 0; y < 13; ++y) for(x = 0; x < 768; ++x) fscanf(pbm, "%d", &pbm_contents[x][y]); fclose(pbm); /* Start the header to our output file */ if(!(df = fopen(argv[2], "w"))) exit(1); fprintf(df, "/* DGen font, generated by pbm2df from \"%s\" */\n\n" "#include /* for NULL definition */\n\n", argv[1]); /* Now do each cell */ for(i = 0; i < 96; ++i) { fprintf(df, "static int _glyph_%02X[] = {", i + 32); j = 0; for(y = 0; y < 13; ++y) for(x = (i << 3); x < ((i << 3) + 8); ++x) { if(pbm_contents[x][y]) { fprintf(df, "%d, ", j); j = 0; } ++j; } fprintf(df, "-1};\n"); } /* Compile it all into one big mess ;) */ fprintf(df, "int *dgen_font[] = {\n" " /* Fill in for the control characters */\n" " NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n" " NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n" " NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n" " NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL"); for(i = 32; i < 128; ++i) fprintf(df, ",\n _glyph_%02X", i); /* Close off the end of the file */ fprintf(df, "\n};\n"); fclose(df); printf("Successfully generated dgen font source \"%s\" from \"%s\"\n", argv[2], argv[1]); return 0; } dgen-sdl-1.23/sdl/dgenfont.pbm 644 1750 1750 47617 7241272640 11406 P1 # CREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) # CREATOR: The GIMP's PNM Filter Version 1.0 768 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 0 1 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 1 1 1 0 1 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 1 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 1 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 dgen-sdl-1.23/sdl/chartfont.c 644 1750 1750 511 7241272640 11154 /* This prints out all the ASCII characters in the format pbm2df expects them * You can run this on an xterm with an 8x13 font, and put the resulting * screenshot straight into pbm2df! */ main() { unsigned char i; for(i = ' '; i < 128; ++i) { printf("%c", i); if((i % 32) == 31) printf("\n"); } return 0; }