summaryrefslogtreecommitdiff
path: root/arm9
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2007-04-10 23:59:35 +0000
committerIan C <ianc@noddybox.co.uk>2007-04-10 23:59:35 +0000
commit6701f6a9d4f979cc1eadb673e767b5c46cd2a9c8 (patch)
tree5996a9d0a8bb393afc4ef3da9609df7a22af32a1 /arm9
parentcd4886b4b099367c561fa5af6d7346bd43d7e2a7 (diff)
Initial import
Diffstat (limited to 'arm9')
-rw-r--r--arm9/.cvsignore7
-rw-r--r--arm9/Makefile134
-rw-r--r--arm9/data/ant_tape.binbin0 -> 41020 bytes
-rw-r--r--arm9/data/keyb.binbin0 -> 15597 bytes
-rw-r--r--arm9/data/spec48.binbin0 -> 16384 bytes
-rw-r--r--arm9/data/splashimg.binbin0 -> 16334 bytes
-rw-r--r--arm9/include/config.h49
-rw-r--r--arm9/include/framebuffer.h90
-rw-r--r--arm9/include/gui.h30
-rw-r--r--arm9/include/keyboard.h135
-rw-r--r--arm9/include/monitor.h29
-rw-r--r--arm9/include/spec.h69
-rw-r--r--arm9/include/tapes.h27
-rw-r--r--arm9/include/textmode.h37
-rw-r--r--arm9/include/touchwrap.h38
-rw-r--r--arm9/include/z80.h250
-rw-r--r--arm9/include/z80_config.h59
-rw-r--r--arm9/include/z80_private.h276
-rw-r--r--arm9/source/config.c135
-rw-r--r--arm9/source/framebuffer.c386
-rw-r--r--arm9/source/gui.c714
-rw-r--r--arm9/source/keyboard.c411
-rw-r--r--arm9/source/main.c427
-rw-r--r--arm9/source/monitor.c362
-rw-r--r--arm9/source/spec.c507
-rw-r--r--arm9/source/tapes.c160
-rw-r--r--arm9/source/textmode.c157
-rw-r--r--arm9/source/touchwrap.c55
-rw-r--r--arm9/source/z80.c331
-rw-r--r--arm9/source/z80_decode.c2533
-rw-r--r--arm9/source/z80_dis.c2494
31 files changed, 9902 insertions, 0 deletions
diff --git a/arm9/.cvsignore b/arm9/.cvsignore
new file mode 100644
index 0000000..945fe94
--- /dev/null
+++ b/arm9/.cvsignore
@@ -0,0 +1,7 @@
+build
+*.arm9
+*.arm7
+*.ds.gba
+*.elf
+*.nds
+*.p
diff --git a/arm9/Makefile b/arm9/Makefile
new file mode 100644
index 0000000..05062e1
--- /dev/null
+++ b/arm9/Makefile
@@ -0,0 +1,134 @@
+#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(DEVKITARM)),)
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
+endif
+
+include $(DEVKITARM)/ds_rules
+
+#---------------------------------------------------------------------------------
+# BUILD is the directory where object files & intermediate files will be placed
+# SOURCES is a list of directories containing source code
+# INCLUDES is a list of directories containing extra header files
+# DATA is a list of directories containing binary files
+# all directories are relative to this makefile
+#---------------------------------------------------------------------------------
+BUILD := build
+SOURCES := source
+INCLUDES := include build ../common_include
+DATA := data
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH := -mthumb -mthumb-interwork
+
+CFLAGS := -g -Wall -O2\
+ -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
+ -ffast-math \
+ $(ARCH)
+
+CFLAGS += $(INCLUDE) -DARM9
+CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
+
+ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s
+
+LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
+
+#---------------------------------------------------------------------------------
+# any extra libraries we wish to link with the project
+#---------------------------------------------------------------------------------
+LIBS := -lfat -lnds9
+
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS := $(LIBNDS)
+
+#---------------------------------------------------------------------------------
+# no real need to edit anything past this point unless you need to add additional
+# rules for different file extensions
+#---------------------------------------------------------------------------------
+ifneq ($(BUILD),$(notdir $(CURDIR)))
+#---------------------------------------------------------------------------------
+
+export ARM9BIN := $(TOPDIR)/$(TARGET).arm9
+export ARM9ELF := $(CURDIR)/$(TARGET).arm9.elf
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(DATA),$(CURDIR)/$(dir))
+
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(CPPFILES)),)
+#---------------------------------------------------------------------------------
+ export LD := $(CC)
+#---------------------------------------------------------------------------------
+else
+#---------------------------------------------------------------------------------
+ export LD := $(CXX)
+#---------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------
+
+export OFILES := $(addsuffix .o,$(BINFILES)) \
+ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+ -I$(CURDIR)/$(BUILD)
+
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+
+.PHONY: $(BUILD) clean
+
+#---------------------------------------------------------------------------------
+$(BUILD):
+ @[ -d $@ ] || mkdir -p $@
+ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ @rm -fr $(BUILD) *.elf *.nds* *.bin
+
+
+#---------------------------------------------------------------------------------
+else
+
+DEPENDS := $(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+$(ARM9BIN) : $(ARM9ELF)
+ @$(OBJCOPY) -O binary $< $@
+ @echo built ... $(notdir $@)
+
+$(ARM9ELF) : $(OFILES)
+ @echo linking $(notdir $@)
+ @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
+
+#---------------------------------------------------------------------------------
+# you need a rule like this for each extension you use as binary data
+#---------------------------------------------------------------------------------
+%.bin.o : %.bin
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ @$(bin2o)
+
+
+-include $(DEPENDS)
+
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
diff --git a/arm9/data/ant_tape.bin b/arm9/data/ant_tape.bin
new file mode 100644
index 0000000..3547526
--- /dev/null
+++ b/arm9/data/ant_tape.bin
Binary files differ
diff --git a/arm9/data/keyb.bin b/arm9/data/keyb.bin
new file mode 100644
index 0000000..7840379
--- /dev/null
+++ b/arm9/data/keyb.bin
Binary files differ
diff --git a/arm9/data/spec48.bin b/arm9/data/spec48.bin
new file mode 100644
index 0000000..4d6895e
--- /dev/null
+++ b/arm9/data/spec48.bin
Binary files differ
diff --git a/arm9/data/splashimg.bin b/arm9/data/splashimg.bin
new file mode 100644
index 0000000..bf316f7
--- /dev/null
+++ b/arm9/data/splashimg.bin
Binary files differ
diff --git a/arm9/include/config.h b/arm9/include/config.h
new file mode 100644
index 0000000..f61bd81
--- /dev/null
+++ b/arm9/include/config.h
@@ -0,0 +1,49 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_CONFIG_H
+#define DS48_CONFIG_H
+
+typedef enum
+{
+ DS48_STICKY_CAPS,
+ DS48_STICKY_SYM,
+ DS48_AVERAGE_TOUCHSCREEN,
+ DS48_NUM_CONFIG_ITEMS
+} DS48_ConfigItem;
+
+/* Returns TRUE if config loaded from FAT device
+*/
+int LoadConfig(void);
+
+/* Returns TRUE if config saved to FAT device
+*/
+int SaveConfig(void);
+
+/* Gets a description for a config item.
+*/
+const char *ConfigDesc(DS48_ConfigItem item);
+
+/* Table of configs. Done like this for simple performance reasons.
+*/
+extern int DS48_Config[/*DS48_ConfigItem item*/];
+
+#endif /* DS48_CONFIG_H */
diff --git a/arm9/include/framebuffer.h b/arm9/include/framebuffer.h
new file mode 100644
index 0000000..ec64bdd
--- /dev/null
+++ b/arm9/include/framebuffer.h
@@ -0,0 +1,90 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_FRAMEBUFFER_H
+#define DS48_FRAMEBUFFER_H
+
+/* Predefined colours.
+*/
+typedef enum
+{
+ COL_TRANSPARENT = -1,
+ COL_BLACK = 0,
+ COL_WHITE = 240,
+ COL_RED = 241,
+ COL_GREEN = 242,
+ COL_BLUE = 243,
+ COL_GUISELECT = 244,
+ COL_GREY = 245,
+ COL_LIGHTGREY = 246,
+ COL_DARKGREY = 247,
+ COL_YELLOW = 248
+} FB_Colour;
+
+
+/* Initialise 'framebuffer' code. vram is where the 8-bit framebuffer is.
+ palette is the palette to use/set.
+*/
+void FB_Init(uint16 *vram, uint16 *palette);
+
+/* Gives access to the parameters of the frame buffer.
+*/
+uint16 *FB_VRAM(void);
+uint16 *FB_PALETTE(void);
+
+/* Load the internal framebuffer font as a set of ASCII tiles (starting with
+ space) at tiles. The tiles will use colour COL_WHITE.
+*/
+void FB_LoadASCIITiles(uint16 *tiles);
+
+/* Print the text into the framebuffer.
+*/
+void FB_Print(const char *text, int x, int y,
+ FB_Colour colour, FB_Colour paper);
+void FB_Centre(const char *text, int y,
+ FB_Colour colour, FB_Colour paper);
+void FB_printf(int x, int y, FB_Colour colour, FB_Colour paper,
+ const char *format, ...);
+
+/* Lines and boxes.
+*/
+void FB_HLine(int x1, int x2, int y, FB_Colour colour);
+void FB_VLine(int x, int y1, int y2, FB_Colour colour);
+void FB_Box(int x, int y, int w, int h, FB_Colour colour);
+void FB_FillBox(int x, int y, int w, int h, FB_Colour colour);
+
+/* Clear to background
+*/
+void FB_Clear(void);
+
+/* Draw the image. The image must be an 8-bit image, but with only the first
+ 16 palette entries used. Just to complicate matters!
+
+ The image is assumed to be an even number of pixels wide. Also the passed
+ X co-ord will be forced even.
+
+ offset is used to give an offset into the palette to place colours from the
+ image. Palette entries 1 - 128 will always be safe to use (these routines
+ will never use them).
+*/
+void FB_Blit(sImage *img, int x, int y, int offset);
+
+#endif /* DS48_FRAMEBUFFER_H */
diff --git a/arm9/include/gui.h b/arm9/include/gui.h
new file mode 100644
index 0000000..5464659
--- /dev/null
+++ b/arm9/include/gui.h
@@ -0,0 +1,30 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_GUI_H
+#define DS48_GUI_H
+
+int GUI_Menu(const char *opts[]);
+void GUI_Alert(int fatal, const char *text);
+void GUI_Config(void);
+int GUI_FileSelect(char pwd[], char selected_file[], const char *filter);
+
+#endif /* DS48_GUI_H */
diff --git a/arm9/include/keyboard.h b/arm9/include/keyboard.h
new file mode 100644
index 0000000..fa7ec68
--- /dev/null
+++ b/arm9/include/keyboard.h
@@ -0,0 +1,135 @@
+/*
+ ds48 - Nintendo ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_KEYBOARD_H
+#define DS48_KEYBOARD_H
+
+/* Note that the first 40 values purposefully are the keyboard matrix keys.
+ Note also that they are in display order, not matrix order.
+*/
+typedef enum
+{
+ SK_1,
+ SK_2,
+ SK_3,
+ SK_4,
+ SK_5,
+
+ SK_6,
+ SK_7,
+ SK_8,
+ SK_9,
+ SK_0,
+
+ SK_Q,
+ SK_W,
+ SK_E,
+ SK_R,
+ SK_T,
+
+ SK_Y,
+ SK_U,
+ SK_I,
+ SK_O,
+ SK_P,
+
+ SK_A,
+ SK_S,
+ SK_D,
+ SK_F,
+ SK_G,
+
+ SK_H,
+ SK_J,
+ SK_K,
+ SK_L,
+ SK_ENTER,
+
+ SK_CAPS_SHIFT,
+ SK_Z,
+ SK_X,
+ SK_C,
+ SK_V,
+
+ SK_B,
+ SK_N,
+ SK_M,
+ SK_SYMBOL_SHIFT,
+ SK_SPACE,
+
+ SK_ABOUT,
+ SK_CONFIG,
+ SK_PAD_UP,
+ SK_PAD_DOWN,
+ SK_PAD_LEFT,
+ SK_PAD_RIGHT,
+ SK_PAD_A,
+ SK_PAD_B,
+ SK_PAD_X,
+ SK_PAD_Y,
+ SK_PAD_R,
+ SK_PAD_L,
+ SK_PAD_START,
+ SK_PAD_SELECT,
+
+ NUM_SOFT_KEYS
+} SoftKey;
+
+typedef struct
+{
+ SoftKey key;
+ int pressed;
+} SoftKeyEvent;
+
+
+/* Display the soft keyboard.
+*/
+void SK_DisplayKeyboard(void);
+
+/* If dim is TRUE, then the keyboard is displayed with reduced brightness along
+ with the selection box. This routine simply adjusts the palette, and
+ assumes that the keyboard is already on display.
+*/
+void SK_SetDisplayBrightness(int dim);
+
+/* Returns TRUE while there are still key events for this cycle
+*/
+int SK_GetEvent(SoftKeyEvent *ev);
+
+/* Returns TRUE while there are still key events for this cycle. Unlike
+ SK_GetEvent this does not do joypad mappings.
+*/
+int SK_GetBareEvent(SoftKeyEvent *ev);
+
+/* Sets a key to be 'sticky'.
+*/
+void SK_SetSticky(SoftKey key, int is_sticky);
+
+/* Map the joypad to keys. Note that when mapped that both the key and the
+ joypad code will be generated.
+*/
+void SK_DefinePad(SoftKey pad, SoftKey key);
+
+/* Returns a name for key symbols.
+*/
+const char *SK_KeyName(SoftKey pad);
+
+#endif /* DS48_KEYBOARD_H */
diff --git a/arm9/include/monitor.h b/arm9/include/monitor.h
new file mode 100644
index 0000000..fbee80b
--- /dev/null
+++ b/arm9/include/monitor.h
@@ -0,0 +1,29 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_MONITOR_H
+#define DS48_MONITOR_H
+
+#include "z80.h"
+
+void MachineCodeMonitor(Z80 *cpu);
+
+#endif /* DS48_MONITOR_H */
diff --git a/arm9/include/spec.h b/arm9/include/spec.h
new file mode 100644
index 0000000..f9f6786
--- /dev/null
+++ b/arm9/include/spec.h
@@ -0,0 +1,69 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+*/
+
+#ifndef DS48_SPEC_H
+#define DS48_SPEC_H
+
+#include "z80.h"
+#include "keyboard.h"
+
+/* Initialise the SPEC
+*/
+void SPECInit(uint16 *vram, Z80 *z80);
+
+/* Handle keypresses
+*/
+void SPECHandleKey(SoftKey k, int is_pressed);
+
+/* Enable fopen() loading of tape files
+*/
+void SPECEnableFileSystem(int enable);
+
+/* Set a file to load from tape
+*/
+void SPECSetTape(const Z80Byte *image, int len);
+
+/* Interfaces for the Z80
+*/
+Z80Byte SPECPeek(Z80 *z80, Z80Word addr);
+void SPECPoke(Z80 *z80, Z80Word addr, Z80Byte val);
+
+#define SPECDisPeek SPECPeek
+
+Z80Byte SPECReadPort(Z80 *z80, Z80Word port);
+void SPECWritePort(Z80 *z80, Z80Word port, Z80Byte val);
+
+
+/* Reset the speccy
+*/
+void SPECReset(Z80 *z80);
+
+/* Tell the Spectrum that config may have changed
+*/
+void SPECReconfigure(void);
+
+#endif
+
+
+/* END OF FILE */
diff --git a/arm9/include/tapes.h b/arm9/include/tapes.h
new file mode 100644
index 0000000..1fbb2d7
--- /dev/null
+++ b/arm9/include/tapes.h
@@ -0,0 +1,27 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_TAPES_H
+#define DS48_TAPES_H
+
+void SelectTape(void);
+
+#endif /* DS48_TAPES_H */
diff --git a/arm9/include/textmode.h b/arm9/include/textmode.h
new file mode 100644
index 0000000..7cefdbf
--- /dev/null
+++ b/arm9/include/textmode.h
@@ -0,0 +1,37 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_TEXTMODE_H
+#define DS48_TEXTMODE_H
+
+/* Note that the co-ords are into the map -- the user is free to use this and
+ move the map around, scale it, blend it, do want they want with it...
+
+ The routines assume they can write into this map using the ASCII code
+ with 32 subtracted for each char.
+*/
+void TM_Init(uint16 *vram, int map_width, int map_height, int map_is_rotation);
+
+void TM_Cls(void);
+void TM_Put(int x, int y, const char *str);
+void TM_printf(int x, int y, const char *format, ...);
+
+#endif /* DS48_TEXTMODE_H */
diff --git a/arm9/include/touchwrap.h b/arm9/include/touchwrap.h
new file mode 100644
index 0000000..2ee987a
--- /dev/null
+++ b/arm9/include/touchwrap.h
@@ -0,0 +1,38 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+#ifndef DS48_TOUCHWRAP_H
+#define DS48_TOUCHWRAP_H
+
+/* Don't know whether I have a problem with my DS or the library, but sometimes
+ the touchscreen value is off (one co-ord generally completely out).
+
+ To alleviate this, and as this is a simple touch screen keyboard, allow
+ touchs to be averaged if the config says so. And averaged touch just means
+ that two touchs have to happen within 5 pixels on X and Y before being
+ allowed.
+
+ If not configured to average, this simply reads the touchscreen position
+ and returns true.
+*/
+int AllowTouch(touchPosition *tp);
+
+#endif /* DS48_TOUCHWRAP_H */
diff --git a/arm9/include/z80.h b/arm9/include/z80.h
new file mode 100644
index 0000000..e6bdfd9
--- /dev/null
+++ b/arm9/include/z80.h
@@ -0,0 +1,250 @@
+/*
+
+ z80 - Z80 emulation
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+*/
+
+#ifndef Z80_H
+#define Z80_H "$Id$"
+
+/* Configuration
+*/
+#include "z80_config.h"
+
+
+/* ---------------------------------------- TYPES
+*/
+
+/* Large unsigned type
+*/
+typedef unsigned long Z80Val;
+
+
+/* 8-bit type. The emulation will exit with code 2 if this isn't 8 bits.
+*/
+typedef unsigned char Z80Byte;
+
+
+/* 8-bit signed type. The emulation will exit with code 2 if this isn't 8 bits.
+*/
+typedef signed char Z80Relative;
+
+
+/* 16-bit type. The emulation will exit with code 2 if this isn't 16 bits.
+*/
+typedef unsigned short Z80Word;
+
+
+/* A Z80 16-bit register. To access the HI/LO component use the indexes
+ Z80_HI_WORD and Z80_LO_WORD which will be initialised once Z80Init has been
+ called.
+*/
+typedef union
+{
+ Z80Word w;
+ Z80Byte b[2];
+} Z80Reg;
+
+extern int Z80_HI_WORD;
+extern int Z80_LO_WORD;
+
+
+/* The processor
+*/
+struct Z80Private;
+
+typedef struct
+{
+ Z80Word PC;
+
+ Z80Reg AF;
+ Z80Reg BC;
+ Z80Reg DE;
+ Z80Reg HL;
+
+ Z80Word AF_;
+ Z80Word BC_;
+ Z80Word DE_;
+ Z80Word HL_;
+
+ Z80Reg IX;
+ Z80Reg IY;
+
+ Z80Word SP;
+
+ Z80Byte IFF1;
+ Z80Byte IFF2;
+ Z80Byte IM;
+ Z80Byte I;
+ Z80Byte R;
+
+ struct Z80Private *priv;
+} Z80;
+
+
+/* Interfaces used to handle memory
+*/
+typedef Z80Byte (*Z80ReadMemory)(Z80 *cpu, Z80Word address);
+typedef void (*Z80WriteMemory)(Z80 *cpu, Z80Word address, Z80Byte value);
+
+
+/* Interfaces needed to handle ports (IN/OUT commands)
+*/
+typedef Z80Byte (*Z80ReadPort)(Z80 *cpu, Z80Word address);
+typedef void (*Z80WritePort)(Z80 *cpu, Z80Word address, Z80Byte value);
+
+
+/* Callback. Callback should return TRUE for processing to continue.
+*/
+typedef int (*Z80Callback)(Z80 *cpu, Z80Val data);
+
+
+/* Callback reasons
+
+ eZ80_Instruction Called before the initial fetch for an instruction
+ (called just to once no matter how many bytes the
+ instruction is made up of).
+
+ eZ80_EDHook Called when an undefined ED opcode is executed.
+
+ eZ80_Halt Called when the HALT instruction is hit and released.
+
+ eZ80_RETI Called when the RETI instruction is executed
+*/
+typedef enum
+{
+ eZ80_Instruction, /* data = no cycles since reset */
+ eZ80_EDHook, /* data = byte after ED opcode (only for NOP opcodes) */
+ eZ80_Halt, /* data = 1 halt raised, 0 halt cleared by int */
+ eZ80_RETI, /* data = ignored */
+ eZ80_NO_CALLBACK /* leave at end */
+} Z80CallbackReason;
+
+
+/* Flags in the F register
+*/
+typedef enum
+{
+ eZ80_Carry =0x01,
+ eZ80_Neg =0x02,
+ eZ80_PV =0x04,
+ eZ80_Hidden3 =0x08,
+ eZ80_HalfCarry =0x10,
+ eZ80_Hidden5 =0x20,
+ eZ80_Zero =0x40,
+ eZ80_Sign =0x80
+} Z80FlagRegister;
+
+
+/* Disassembly label -- only useful if ENABLE_DISASSEMBLER is set.
+ Labels are stored as an array, where a NULL in the label field marks
+ the end of the list.
+*/
+typedef struct
+{
+ Z80Word address;
+ const char *label;
+} Z80Label;
+
+
+/* ---------------------------------------- INTERFACES
+*/
+
+
+/* Initialises the processor.
+*/
+#ifdef ENABLE_ARRAY_MEMORY
+Z80 *Z80Init(Z80ReadPort read_port,
+ Z80WritePort write_port);
+#else
+Z80 *Z80Init(Z80ReadMemory read_memory,
+ Z80WriteMemory write_memory,
+ Z80ReadPort read_port,
+ Z80WritePort write_port,
+ Z80ReadMemory read_for_disassem);
+#endif
+
+
+/* Resets the processor.
+*/
+void Z80Reset(Z80 *cpu);
+
+
+/* Lodge a callback to be invoked after special events. Returns FALSE
+ if the callback couldn't be lodged (there is a max of 10 callbacks per
+ reason).
+*/
+int Z80LodgeCallback(Z80 *cpu,
+ Z80CallbackReason reason,
+ Z80Callback callback);
+
+
+/* Remove a callback. Does nothing if reason was not lodged with
+ Z80LodgeCallback()
+*/
+void Z80RemoveCallback(Z80 *cpu,
+ Z80CallbackReason reason,
+ Z80Callback callback);
+
+
+/* Cause an interrupt before the next opcode.
+ devbyte is the byte generated by the device (if any).
+*/
+void Z80Interrupt(Z80 *cpu, Z80Byte devbyte);
+
+
+/* Cause an NMI
+*/
+void Z80NMI(Z80 *cpu);
+
+
+/* Execute a single instruction. Returns FALSE if any callback returned
+ FALSE.
+*/
+int Z80SingleStep(Z80 *cpu);
+
+
+/* Executes until a callback returns FALSE (never returns otherwise)
+*/
+void Z80Exec(Z80 *cpu);
+
+
+/* Manipulate the cylce count of the Z80
+*/
+Z80Val Z80Cycles(Z80 *cpu);
+void Z80ResetCycles(Z80 *cpu, Z80Val cycles);
+
+
+/* Set address to label mappings for the disassembler
+*/
+void Z80SetLabels(Z80Label labels[]);
+
+
+/* Simple disassembly of memory accessed through read_for_disassem, or
+ Z80_MEMORY as appropriate. addr is updated on exit.
+*/
+const char *Z80Disassemble(Z80 *cpu, Z80Word *addr);
+
+#endif
+
+/* END OF FILE */
diff --git a/arm9/include/z80_config.h b/arm9/include/z80_config.h
new file mode 100644
index 0000000..7e02bb8
--- /dev/null
+++ b/arm9/include/z80_config.h
@@ -0,0 +1,59 @@
+/*
+
+ z80 - Z80 emulation
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+*/
+
+#ifndef Z80_CONFIG_H
+#define Z80_CONFIG_H "$Id$"
+
+
+/* This file defines various compile-time configuration options
+ for the Z80 emulation
+*/
+
+
+/* Define this to enable the disassembly interface
+*/
+#define ENABLE_DISASSEM
+
+
+/* Define this to enable the array-based memory model. In this mode
+ an externally visible Z80Byte array called Z80_MEMORY must be
+ defined. The macros RAMBOT and RAMTOP define the writable area of
+ memory and must be changed accordingly.
+
+ In this mode the signature of Z80Init changes so that the memory functions
+ are not passed. ALL processor instances share the same memory.
+#define ENABLE_ARRAY_MEMORY
+*/
+
+#ifdef ENABLE_ARRAY_MEMORY
+#define RAMBOT 0x0000
+#define RAMTOP 0xffff
+#endif
+
+
+#endif
+
+/* END OF FILE */
diff --git a/arm9/include/z80_private.h b/arm9/include/z80_private.h
new file mode 100644
index 0000000..bf51b7a
--- /dev/null
+++ b/arm9/include/z80_private.h
@@ -0,0 +1,276 @@
+/*
+
+ z80 - Z80 emulation
+
+ Copyright (C) 2007 Ian Cowburn (ianc@noddybox.co.uk)
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+ Private macros for Z80
+
+*/
+
+#ifndef Z80_PRIVATE_H
+#define Z80_PRIVATE_H "$Id$"
+
+#include "z80_config.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MAX_PER_CALLBACK 10
+
+
+/* ---------------------------------------- TYPES
+*/
+
+struct Z80Private
+{
+ Z80Val cycle;
+
+ int halt;
+
+ Z80Byte shift;
+
+ int raise;
+ Z80Byte devbyte;
+ int nmi;
+
+#ifndef ENABLE_ARRAY_MEMORY
+ Z80ReadMemory disread;
+
+ Z80ReadMemory mread;
+ Z80WriteMemory mwrite;
+#endif
+
+ Z80ReadPort pread;
+ Z80WritePort pwrite;
+
+ Z80Callback callback[eZ80_NO_CALLBACK][MAX_PER_CALLBACK];
+
+ int last_cb;
+};
+
+#define PRIV cpu->priv
+
+
+/* ---------------------------------------- ARRAY MEMORY
+*/
+
+#ifdef ENABLE_ARRAY_MEMORY
+extern Z80Byte Z80_MEMORY[];
+#endif
+
+
+/* ---------------------------------------- MACROS
+*/
+
+/* NOTE: A lot of these macros assume you have a variable called 'cpu'
+ which is a pointer to Z80
+*/
+
+
+/* Invoke a callback class
+*/
+#define CALLBACK(r,d) do \
+ { \
+ int f; \
+ \
+ for(f=0;f<MAX_PER_CALLBACK;f++) \
+ if (PRIV->callback[r][f]) \
+ PRIV->last_cb &= \
+ PRIV->callback[r][f](cpu,d);\
+ } while(0)
+
+/* Flag register
+*/
+#define C_Z80 0x01
+#define N_Z80 0x02
+#define P_Z80 0x04
+#define V_Z80 P_Z80
+#define H_Z80 0x10
+#define Z_Z80 0x40
+#define S_Z80 0x80
+
+#define B3_Z80 0x08
+#define B5_Z80 0x20
+
+
+#define SET(v,b) (v)|=b
+#define CLR(v,b) (v)&=~(b)
+
+#define SETFLAG(f) SET(cpu->AF.b[LO],f)
+#define CLRFLAG(f) CLR(cpu->AF.b[LO],f)
+
+#ifdef ENABLE_ARRAY_MEMORY
+
+#define PEEK(addr) Z80_MEMORY[addr]
+
+static inline Z80Word PEEKW(Z80Word addr)
+{
+ return (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8);
+}
+
+#define POKE(addr,val) do \
+ { \
+ Z80Word ba=addr; \
+ if (ba>=RAMBOT && ba<=RAMTOP) \
+ Z80_MEMORY[ba]=val; \
+ } while(0)
+
+#define POKEW(addr,val) do \
+ { \
+ Z80Word wa=addr; \
+ Z80Word wv=val; \
+ POKE(wa,wv); \
+ POKE(wa+1,wv>>8); \
+ } while(0)
+
+
+#define FETCH_BYTE (Z80_MEMORY[cpu->PC++])
+#define FETCH_WORD (cpu->PC+=2, \
+ Z80_MEMORY[cpu->PC-2]| \
+ ((Z80Word)Z80_MEMORY[cpu->PC-1]<<8))
+
+#else
+
+#define PEEK(addr) (PRIV->mread(cpu,addr))
+#define PEEKW(addr) FPEEKW(cpu,addr)
+
+#define POKE(addr,val) PRIV->mwrite(cpu,addr,val)
+#define POKEW(addr,val) FPOKEW(cpu,addr,val)
+
+#define FETCH_BYTE (PRIV->mread(cpu,cpu->PC++))
+#define FETCH_WORD (cpu->PC+=2,FPEEKW(cpu,cpu->PC-2))
+
+#endif
+
+
+#define IS_C (cpu->AF.b[LO]&C_Z80)
+#define IS_N (cpu->AF.b[LO]&N_Z80)
+#define IS_P (cpu->AF.b[LO]&P_Z80)
+#define IS_H (cpu->AF.b[LO]&H_Z80)
+#define IS_Z (cpu->AF.b[LO]&Z_Z80)
+#define IS_S (cpu->AF.b[LO]&S_Z80)
+
+#define CARRY IS_C
+
+#define IS_IX_IY (PRIV->shift==0xdd || PRIV->shift==0xfd)
+#define OFFSET(off) off=(IS_IX_IY ? (Z80Relative)FETCH_BYTE:0)
+
+#define TSTATE(n) PRIV->cycle+=n
+
+#define ADD_R(v) cpu->R=((cpu->R&0x80)|((cpu->R+(v))&0x7f))
+#define INC_R ADD_R(1)
+
+#ifdef ENABLE_ARRAY_MEMORY
+
+#define PUSH(REG) do \
+ { \
+ Z80Word pv=REG; \
+ cpu->SP-=2; \
+ POKE(cpu->SP,pv); \
+ POKE(cpu->SP+1,pv>>8); \
+ } while(0)
+
+#else
+
+#define PUSH(REG) do \
+ { \
+ Z80Word pushv=REG; \
+ cpu->SP-=2; \
+ PRIV->mwrite(cpu,cpu->SP,pushv); \
+ PRIV->mwrite(cpu,cpu->SP+1,pushv>>8);\
+ } while(0)
+#endif
+
+#define POP(REG) do \
+ { \
+ REG=PEEK(cpu->SP) | \
+ (Z80Word)PEEK(cpu->SP+1)<<8; \
+ cpu->SP+=2; \
+ } while(0)
+
+#define SETHIDDEN(res) cpu->AF.b[LO]=(cpu->AF.b[LO]&~(B3_Z80|B5_Z80))|\
+ ((res)&(B3_Z80|B5_Z80))
+
+#define CALL do \
+ { \
+ PUSH(cpu->PC+2); \
+ cpu->PC=PEEKW(cpu->PC); \
+ } while(0)
+
+#define NOCALL cpu->PC+=2
+#define JP cpu->PC=PEEKW(cpu->PC)
+#define NOJP cpu->PC+=2
+#define JR cpu->PC+=(Z80Relative)PEEK(cpu->PC)+1
+#define NOJR cpu->PC++
+
+#define OUT(P,V) do \
+ { \
+ if (PRIV->pwrite) \
+ PRIV->pwrite(cpu,P,V); \
+ } while(0)
+
+#define IN(P) (PRIV->pread?PRIV->pread(cpu,P):0)
+
+
+
+/* ---------------------------------------- LABELS
+*/
+extern Z80Label *z80_labels;
+
+
+/* ---------------------------------------- GLOBAL GENERAL OPCODES/ROUTINES
+*/
+void Z80_Decode(Z80 *cpu, Z80Byte opcode);
+void Z80_InitialiseInternals(void);
+
+
+/* ---------------------------------------- DISASSEMBLY
+*/
+#ifdef ENABLE_DISASSEM
+typedef void (*DIS_OP_CALLBACK)(Z80 *z80, Z80Byte op, Z80Word *pc);
+
+extern DIS_OP_CALLBACK dis_CB_opcode[];
+extern DIS_OP_CALLBACK dis_DD_opcode[];
+extern DIS_OP_CALLBACK dis_DD_CB_opcode[];
+extern DIS_OP_CALLBACK dis_ED_opcode[];
+extern DIS_OP_CALLBACK dis_FD_opcode[];
+extern DIS_OP_CALLBACK dis_FD_CB_opcode[];
+extern DIS_OP_CALLBACK dis_opcode_z80[];
+
+const char *Z80_Dis_Printf(const char *format, ...);
+
+Z80Byte Z80_Dis_FetchByte(Z80 *cpu, Z80Word *pc);
+Z80Word Z80_Dis_FetchWord(Z80 *cpu, Z80Word *pc);
+
+void Z80_Dis_Set(const char *op, const char *arg);
+const char *Z80_Dis_GetOp(void);
+const char *Z80_Dis_GetArg(void);
+#endif /* ENABLE_DISASSEM */
+
+#endif /* Z80_PRIVATE_H */
+
+/* END OF FILE */
diff --git a/arm9/source/config.c b/arm9/source/config.c
new file mode 100644
index 0000000..648834b
--- /dev/null
+++ b/arm9/source/config.c
@@ -0,0 +1,135 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+/* ---------------------------------------- PRIVATE DATA
+*/
+const char *conf_filename = "DS48.CFG";
+
+const char *conf_entry[DS48_NUM_CONFIG_ITEMS]=
+{
+ "sticky_caps_shift",
+ "sticky_symbol_shift",
+ "average_touchscreen"
+};
+
+
+/* ---------------------------------------- GLOBAL DATA
+*/
+int DS48_Config[DS48_NUM_CONFIG_ITEMS]=
+{
+ TRUE,
+ FALSE,
+ FALSE
+};
+
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+int LoadConfig(void)
+{
+ FILE *fp = NULL;
+
+#ifndef DS48_DISABLE_FAT
+ fp=fopen(conf_filename,"r");
+#endif
+
+ if (fp)
+ {
+ char line[80];
+
+ while(fgets(line, sizeof line, fp))
+ {
+ char *p;
+
+ if ((p = strchr(line, '=')))
+ {
+ int f;
+
+ for(f=0;f<DS48_NUM_CONFIG_ITEMS;f++)
+ {
+ if (strncmp(line, conf_entry[f],
+ strlen(conf_entry[f])) == 0)
+ {
+ DS48_Config[f] = (*(p+1) == '1');
+ }
+ }
+
+ }
+ }
+
+ fclose(fp);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int SaveConfig(void)
+{
+ FILE *fp = NULL;
+
+#ifndef DS48_DISABLE_FAT
+ fp=fopen(conf_filename,"w");
+#endif
+
+ if (fp)
+ {
+ int f;
+
+ for(f=0;f<DS48_NUM_CONFIG_ITEMS;f++)
+ {
+ fprintf(fp,"%s=%d\n",conf_entry[f],DS48_Config[f]);
+ }
+
+ fclose(fp);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+const char *ConfigDesc(DS48_ConfigItem item)
+{
+ switch(item)
+ {
+ case DS48_STICKY_CAPS:
+ return "STICKY CAPS SHIFT";
+
+ case DS48_STICKY_SYM:
+ return "STICKY SYMBOL SHIFT";
+
+ case DS48_AVERAGE_TOUCHSCREEN:
+ return "AVERAGE TOUCHSCREEN";
+
+ default:
+ return "UNKNOWN";
+ }
+}
+
diff --git a/arm9/source/framebuffer.c b/arm9/source/framebuffer.c
new file mode 100644
index 0000000..590b3d4
--- /dev/null
+++ b/arm9/source/framebuffer.c
@@ -0,0 +1,386 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "framebuffer.h"
+
+/* ---------------------------------------- STATIC DATA
+*/
+#define WIDTH 256
+#define SCAN 128
+#define HEIGHT 192
+
+static uint16 *buff;
+static uint16 *pal;
+
+static uint8 font[]=
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x00,
+ 0x00, 0x10, 0x7c, 0x14, 0x7c, 0x50, 0x7c, 0x10,
+ 0x00, 0x46, 0x26, 0x10, 0x08, 0x64, 0x62, 0x00,
+ 0x00, 0x08, 0x14, 0x08, 0x54, 0x22, 0x5c, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00,
+ 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00,
+ 0x00, 0x00, 0x28, 0x10, 0x7c, 0x10, 0x28, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00,
+ 0x00, 0x3c, 0x62, 0x52, 0x4a, 0x46, 0x3c, 0x00,
+ 0x00, 0x18, 0x14, 0x10, 0x10, 0x10, 0x7c, 0x00,
+ 0x00, 0x3c, 0x42, 0x40, 0x3c, 0x02, 0x7e, 0x00,
+ 0x00, 0x3c, 0x42, 0x30, 0x40, 0x42, 0x3c, 0x00,
+ 0x00, 0x10, 0x18, 0x14, 0x12, 0x7e, 0x10, 0x00,
+ 0x00, 0x7e, 0x02, 0x3e, 0x40, 0x42, 0x3c, 0x00,
+ 0x00, 0x3c, 0x02, 0x3e, 0x42, 0x42, 0x3c, 0x00,
+ 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x00,
+ 0x00, 0x3c, 0x42, 0x3c, 0x42, 0x42, 0x3c, 0x00,
+ 0x00, 0x3c, 0x42, 0x42, 0x7c, 0x40, 0x3c, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04,
+ 0x00, 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00,
+ 0x00, 0x3c, 0x42, 0x20, 0x10, 0x00, 0x10, 0x00,
+ 0x00, 0x3c, 0x52, 0x6a, 0x7a, 0x02, 0x3c, 0x00,
+ 0x00, 0x3c, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00,
+ 0x00, 0x3e, 0x42, 0x3e, 0x42, 0x42, 0x3e, 0x00,
+ 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00,
+ 0x00, 0x1e, 0x22, 0x42, 0x42, 0x22, 0x1e, 0x00,
+ 0x00, 0x7e, 0x02, 0x3e, 0x02, 0x02, 0x7e, 0x00,
+ 0x00, 0x7e, 0x02, 0x3e, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x3c, 0x00,
+ 0x00, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00,
+ 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00,
+ 0x00, 0x40, 0x40, 0x40, 0x42, 0x42, 0x3c, 0x00,
+ 0x00, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00,
+ 0x00, 0x42, 0x66, 0x5a, 0x42, 0x42, 0x42, 0x00,
+ 0x00, 0x42, 0x46, 0x4a, 0x52, 0x62, 0x42, 0x00,
+ 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00,
+ 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00,
+ 0x00, 0x3c, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x00,
+ 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x22, 0x42, 0x00,
+ 0x00, 0x3c, 0x02, 0x3c, 0x40, 0x42, 0x3c, 0x00,
+ 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
+ 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00,
+ 0x00, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00,
+ 0x00, 0x42, 0x42, 0x42, 0x42, 0x5a, 0x24, 0x00,
+ 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00,
+ 0x00, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x00,
+ 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00,
+ 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00,
+ 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00,
+ 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00,
+ 0x00, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x38, 0x44, 0x1e, 0x04, 0x04, 0x7e, 0x00,
+ 0x00, 0x00, 0x1c, 0x20, 0x3c, 0x22, 0x3c, 0x00,
+ 0x00, 0x04, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x00,
+ 0x00, 0x00, 0x38, 0x04, 0x04, 0x04, 0x38, 0x00,
+ 0x00, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x3c, 0x00,
+ 0x00, 0x00, 0x1c, 0x22, 0x1e, 0x02, 0x3c, 0x00,
+ 0x00, 0x30, 0x08, 0x18, 0x08, 0x08, 0x08, 0x00,
+ 0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x1c,
+ 0x00, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x00,
+ 0x00, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x1c, 0x00,
+ 0x00, 0x20, 0x00, 0x20, 0x20, 0x20, 0x24, 0x18,
+ 0x00, 0x04, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x00,
+ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x30, 0x00,
+ 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x2a, 0x00,
+ 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00,
+ 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00,
+ 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02,
+ 0x00, 0x00, 0x3c, 0x22, 0x22, 0x3c, 0x20, 0x60,
+ 0x00, 0x00, 0x38, 0x04, 0x04, 0x04, 0x04, 0x00,
+ 0x00, 0x00, 0x1c, 0x02, 0x1c, 0x20, 0x1e, 0x00,
+ 0x00, 0x08, 0x1c, 0x08, 0x08, 0x08, 0x30, 0x00,
+ 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00,
+ 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00,
+ 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00,
+ 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00,
+ 0x00, 0x00, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x1c,
+ 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00,
+ 0x00, 0x70, 0x10, 0x0c, 0x10, 0x10, 0x70, 0x00,
+ 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
+ 0x00, 0x0e, 0x08, 0x30, 0x08, 0x08, 0x0e, 0x00,
+ 0x00, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3c
+};
+
+
+/* ---------------------------------------- PRIVATE INTERFACES
+*/
+static inline void Plot(int x, int y, int col)
+{
+ uint16 *base;
+ uint16 cur;
+ int odd;
+
+ if (col == -1)
+ return;
+
+ odd = x&1;
+ x /= 2;
+
+ base = buff+x+y*SCAN;
+ cur = *base;
+
+ if (odd)
+ {
+ cur = (cur & 0xff) | (col<<8);
+ }
+ else
+ {
+ cur = (cur & 0xff00) | col;
+ }
+
+ *base = cur;
+}
+
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+void FB_Init(uint16 *vram, uint16 *palette)
+{
+ buff = vram;
+ pal = palette;
+
+ pal[COL_BLACK] = RGB15(0,0,0);
+ pal[COL_WHITE] = RGB15(31,31,31);
+ pal[COL_RED] = RGB15(31,0,0);
+ pal[COL_GREEN] = RGB15(0,31,0);
+ pal[COL_BLUE] = RGB15(0,0,31);
+ pal[COL_GUISELECT] = RGB15(8,8,31);
+ pal[COL_GREY] = RGB15(15,15,15);
+ pal[COL_LIGHTGREY] = RGB15(22,22,22);
+ pal[COL_DARKGREY] = RGB15(8,8,8);
+ pal[COL_YELLOW] = RGB15(31,31,0);
+}
+
+
+uint16 *FB_VRAM(void)
+{
+ return buff;
+}
+
+
+uint16 *FB_PALETTE(void)
+{
+ return pal;
+}
+
+
+void FB_LoadASCIITiles(uint16 *tiles)
+{
+ uint8 *src;
+ int c;
+ int row;
+ int val;
+ int mask;
+
+ src = font;
+
+ for(c = 32; c < 127; c++)
+ {
+ for(row = 0; row < 8; row++)
+ {
+ for(mask = 1; mask < 0xff; mask<<=1)
+ {
+ if (*src & mask)
+ {
+ val = COL_WHITE;
+ }
+ else
+ {
+ val = 0;
+ }
+
+ mask <<= 1;
+
+ if (*src & mask)
+ {
+ val |= COL_WHITE << 8;
+ }
+
+ *tiles++ = val;
+ }
+
+ src++;
+ }
+ }
+}
+
+
+void FB_Print(const char *text, int x, int y, FB_Colour colour, FB_Colour paper)
+{
+ int cx,cy;
+ int ch;
+
+ while(*text)
+ {
+ ch=((*text)-32)*8;
+
+ for(cy=0;cy<8;cy++)
+ {
+ for(cx=0;cx<8;cx++)
+ {
+ if (font[ch]&(1<<cx))
+ {
+ Plot(x+cx, y+cy, colour);
+ }
+ else
+ {
+ Plot(x+cx, y+cy, paper);
+ }
+ }
+
+ ch++;
+ }
+
+ x+=8;
+ text++;
+ }
+}
+
+
+void FB_Centre(const char *text, int y, FB_Colour colour, FB_Colour paper)
+{
+ FB_Print(text,WIDTH/2-strlen(text)*4,y,colour,paper);
+}
+
+
+void FB_printf(int x, int y, FB_Colour colour, FB_Colour paper,
+ const char *format, ...)
+{
+ char buff[80];
+ va_list va;
+
+ va_start(va,format);
+ vsnprintf(buff,sizeof buff,format,va);
+ va_end(va);
+
+ FB_Print(buff,x,y,colour,paper);
+}
+
+
+void FB_HLine(int x1, int x2, int y, FB_Colour colour)
+{
+ uint16 *line;
+
+ line=buff+y*WIDTH+x1;
+
+ while(x1<=x2)
+ {
+ Plot(x1++,y,colour);
+ }
+}
+
+
+void FB_VLine(int x, int y1, int y2, FB_Colour colour)
+{
+ while(y1<=y2)
+ {
+ Plot(x,y1++,colour);
+ }
+}
+
+
+void FB_Box(int x, int y, int w, int h, FB_Colour colour)
+{
+ FB_HLine(x,x+w-1,y,colour);
+ FB_HLine(x,x+w-1,y+h-1,colour);
+ FB_VLine(x,y,y+h-1,colour);
+ FB_VLine(x+w-1,y,y+h-1,colour);
+}
+
+
+void FB_FillBox(int x, int y, int w, int h, FB_Colour colour)
+{
+ while(h--)
+ {
+ FB_HLine(x,x+w-1,y++,colour);
+ }
+}
+
+
+void FB_Clear(void)
+{
+ uint16 *p;
+ int f;
+
+ f=WIDTH*HEIGHT/2;
+ p=buff;
+
+ while(f--)
+ {
+ *p++=0;
+ }
+}
+
+
+void FB_Blit(sImage *img, int x, int y, int offset)
+{
+ uint16 *dest;
+ uint16 *row;
+ uint8 *src;
+ uint16 pix;
+ int hww;
+ int ht;
+ int f;
+
+ x /= 2;
+
+ ht = img->height;
+ hww = img->width / 2;
+ dest = buff+x+y*SCAN;
+ src = img->image.data8;
+
+ for(f=0;f<16;f++)
+ {
+ pal[offset+f] = img->palette[f];
+ }
+
+ while(ht--)
+ {
+ row = dest;
+
+ for(f=0;f<hww;f++)
+ {
+ pix = *src++ + offset;
+ pix |= (*src++ + offset) << 8;
+
+ *row++ = pix;
+ }
+
+ dest += SCAN;
+ }
+}
diff --git a/arm9/source/gui.c b/arm9/source/gui.c
new file mode 100644
index 0000000..11096d3
--- /dev/null
+++ b/arm9/source/gui.c
@@ -0,0 +1,714 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <nds.h>
+
+#include <sys/dir.h>
+
+#include "framebuffer.h"
+#include "config.h"
+
+
+/* ---------------------------------------- PRIVATE INTERFACES - PATH HANDLING
+*/
+#define FSEL_FILENAME_LEN 20
+#define FSEL_LINES 16
+#define FSEL_MAX_FILES 512
+
+#define FSEL_LIST_Y 10
+#define FSEL_LIST_H FSEL_LINES*8
+
+typedef struct
+{
+ char name[FSEL_FILENAME_LEN+1];
+ int is_dir;
+ int size;
+} FSEL_File;
+
+static FSEL_File fsel[FSEL_MAX_FILES];
+
+
+static void CheckPath(char *path)
+{
+ size_t l;
+
+ l = strlen(path);
+
+ if (l == 1)
+ {
+ path[0] = '/';
+ }
+ else
+ {
+ if (path[l-1] != '/')
+ {
+ path[l] = '/';
+ path[l+1] = 0;
+ }
+ }
+}
+
+
+static void AddPath(char *path, const char *dir)
+{
+ if (strcmp(dir,"..") == 0)
+ {
+ size_t l;
+
+ l = strlen(path);
+
+ if (l > 1)
+ {
+ path[--l] = 0;
+
+ while(l && path[l] != '/')
+ {
+ path[l--] = 0;
+ }
+ }
+ }
+ else
+ {
+ strcat(path,dir);
+ strcat(path,"/");
+ }
+}
+
+
+
+
+static int SortFiles(const void *a, const void *b)
+{
+ const FSEL_File *f1;
+ const FSEL_File *f2;
+
+ f1 = (const FSEL_File *)a;
+ f2 = (const FSEL_File *)b;
+
+ if (f1->is_dir == f2->is_dir)
+ {
+ return strcasecmp(f1->name, f2->name);
+ }
+ else if (f1->is_dir)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+
+static int ValidFilename(const char *name, int is_dir, const char *filter)
+{
+ size_t l;
+ size_t f;
+
+ l = strlen(name);
+
+ if (l > FSEL_FILENAME_LEN)
+ return 0;
+
+ if (strcmp(name,".") == 0)
+ return 0;
+
+ if (is_dir || !filter)
+ return 1;
+
+ f = strlen(filter);
+
+ if (l > f)
+ {
+ if (strcasecmp(name+l-f,filter) == 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int LoadDir(const char *path, const char *filter)
+{
+ DIR_ITER *dir;
+ struct stat st;
+ char name[FILENAME_MAX];
+ int no = 0;
+
+ if ((dir = diropen(path)))
+ {
+ while(no < FSEL_MAX_FILES && dirnext(dir,name,&st) == 0)
+ {
+ if (ValidFilename(name, (st.st_mode & S_IFDIR), filter))
+ {
+ strcpy(fsel[no].name,name);
+ fsel[no].is_dir = (st.st_mode & S_IFDIR);
+ fsel[no].size = (int)st.st_size;
+ no++;
+ }
+ }
+
+ dirclose(dir);
+
+ qsort(fsel,no,sizeof fsel[0],SortFiles);
+ }
+
+ return no;
+}
+
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+int GUI_Menu(const char *opts[])
+{
+ int x,y;
+ int h;
+ int w;
+ int no;
+ int sel;
+ int f;
+ int done;
+ int defer;
+
+ w=0;
+ h=0;
+ sel=0;
+ done=FALSE;
+ defer=FALSE;
+
+ for(no=0;opts[no];no++)
+ {
+ h+=16;
+
+ if (strlen(opts[no])>w)
+ {
+ w=strlen(opts[no]);
+ }
+ }
+
+ w=w*8+16;
+
+ x=SCREEN_WIDTH/2-w/2;
+ y=SCREEN_HEIGHT/2-h/2;
+
+ while(!done)
+ {
+ uint32 key=0;
+
+ FB_FillBox(x,y,w,h,COL_BLACK);
+ FB_Box(x,y,w,h,COL_WHITE);
+ FB_FillBox(x+1,y+sel*16+1,w-2,14,COL_GUISELECT);
+
+ for(f=0;f<no;f++)
+ {
+ FB_Centre(opts[f],y+4+f*16,COL_WHITE,COL_TRANSPARENT);
+ }
+
+ do
+ {
+ swiWaitForVBlank();
+ } while(!defer && !(key=keysDownRepeat()));
+
+ if (defer)
+ {
+ do
+ {
+ swiWaitForVBlank();
+ } while (keysHeld()&KEY_TOUCH);
+ done=TRUE;
+ }
+ else
+ {
+ if (key & (KEY_A|KEY_B|KEY_X|KEY_Y))
+ {
+ done=TRUE;
+ }
+ else if ((key & KEY_UP) && sel)
+ {
+ sel--;
+ }
+ else if ((key & KEY_DOWN) && sel<no-1)
+ {
+ sel++;
+ }
+ else if (key & KEY_TOUCH)
+ {
+ touchPosition tp=touchReadXY();
+
+ if (tp.px>=x && tp.px<(w+w) && tp.py>=y && tp.py<(y+h))
+ {
+ defer=TRUE;
+ sel=(tp.py-y)/16;
+ }
+ }
+ }
+ }
+
+ return sel;
+}
+
+
+void GUI_Alert(int fatal, const char *text)
+{
+ char line[80];
+ int h;
+ const char *p;
+ char *d;
+
+ h=40;
+ p=text;
+
+ while(*p)
+ {
+ if (*p++=='\n')
+ {
+ h+=8;
+ }
+ }
+
+ FB_FillBox(0,0,SCREEN_WIDTH,h,COL_BLACK);
+ FB_Box(1,1,SCREEN_WIDTH-2,h-2,COL_WHITE);
+
+ p=text;
+ h=4;
+ d=line;
+
+ while(*p)
+ {
+ if (*p=='\n')
+ {
+ *d++=0;
+ p++;
+ FB_Centre(line,h,COL_WHITE,COL_TRANSPARENT);
+ h+=8;
+ d=line;
+ }
+ else
+ {
+ *d++=*p++;
+ }
+ }
+
+ if (d>line)
+ {
+ *d=0;
+ FB_Centre(line,h,COL_WHITE,COL_TRANSPARENT);
+ h+=8;
+ }
+
+ if (!fatal)
+ {
+ FB_Centre("PRESS ANY BUTTON OR SCREEN",h+16,COL_YELLOW,COL_TRANSPARENT);
+
+ while(!keysDown())
+ {
+ swiWaitForVBlank();
+ }
+
+ while(keysHeld())
+ {
+ swiWaitForVBlank();
+ }
+ }
+ else
+ {
+ FB_Centre("PLEASE RESET YOUR CONSOLE",h+16,COL_YELLOW,COL_TRANSPARENT);
+
+ while(1)
+ {
+ swiWaitForVBlank();
+ }
+ }
+}
+
+
+void GUI_Config(void)
+{
+ int sel;
+ DS48_ConfigItem f;
+ int done;
+ int save;
+
+ sel = 0;
+ done = FALSE;
+ save = FALSE;
+
+ FB_Clear();
+
+ FB_Centre("Up/Down to select",140,COL_YELLOW,COL_TRANSPARENT);
+ FB_Centre("A to toggle",150,COL_YELLOW,COL_TRANSPARENT);
+ FB_Centre("Or use touchscreen",160,COL_YELLOW,COL_TRANSPARENT);
+ FB_Centre("START to finish",170,COL_YELLOW,COL_TRANSPARENT);
+
+#ifndef DS48_DISABLE_FAT
+ FB_Centre("SELECT to finish and save",180,COL_YELLOW,COL_TRANSPARENT);
+#endif
+
+ for(f=0;f<DS48_NUM_CONFIG_ITEMS;f++)
+ {
+ FB_Print(ConfigDesc(f),14,20+f*14,COL_WHITE,COL_TRANSPARENT);
+ }
+
+ while(!done)
+ {
+ uint32 key=0;
+
+ for(f=0;f<DS48_NUM_CONFIG_ITEMS;f++)
+ {
+ FB_FillBox(2,20+f*14-1,10,10,
+ DS48_Config[f] ? COL_WHITE : COL_BLACK);
+
+ FB_Box(2,20+f*14-1,10,10,COL_GREY);
+ }
+
+ FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,COL_GUISELECT);
+
+ do
+ {
+ swiWaitForVBlank();
+ } while(!(key=keysDownRepeat()));
+
+ FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,COL_BLACK);
+
+ if (key & KEY_START)
+ {
+ done=TRUE;
+ }
+#ifndef DS48_DISABLE_FAT
+ else if (key & KEY_SELECT)
+ {
+ done=TRUE;
+ save=TRUE;
+ }
+#endif
+ else if (key & KEY_A)
+ {
+ DS48_Config[sel] = !DS48_Config[sel];
+ }
+ else if ((key & KEY_UP) && sel)
+ {
+ sel--;
+ }
+ else if ((key & KEY_DOWN) && sel<DS48_NUM_CONFIG_ITEMS-1)
+ {
+ sel++;
+ }
+ else if (key & KEY_TOUCH)
+ {
+ touchPosition tp = touchReadXY();
+ int nsel;
+
+ nsel = (tp.py-18)/14;
+
+ if (nsel>=0 && nsel<DS48_NUM_CONFIG_ITEMS)
+ {
+ sel = nsel;
+ DS48_Config[sel] = !DS48_Config[sel];
+ }
+ }
+ }
+
+ if (save)
+ {
+ SaveConfig();
+ }
+}
+
+
+int GUI_FileSelect(char pwd[], char selected_file[], const char *filter)
+{
+ int no;
+ int sel;
+ int top;
+ int bar_size;
+ double bar_step;
+ int done;
+ int ret;
+ FB_Colour paper;
+ int off;
+ int f;
+ int drag;
+ int drag_start;
+
+ CheckPath(pwd);
+
+ FB_Clear();
+
+ FB_printf(0,0,COL_BLACK,COL_LIGHTGREY,"%-32.32s",pwd);
+
+ FB_Centre("Use pad and A to select",140,COL_YELLOW,COL_TRANSPARENT);
+ FB_Centre("L and R to page up/down",150,COL_YELLOW,COL_TRANSPARENT);
+ FB_Centre("Or use touchscreen",160,COL_YELLOW,COL_TRANSPARENT);
+ FB_Centre("B to cancel",170,COL_YELLOW,COL_TRANSPARENT);
+
+ no = LoadDir(pwd,filter);
+
+ sel = 0;
+ top = 0;
+ done = FALSE;
+ ret = FALSE;
+ drag = FALSE;
+ drag_start = 0;
+
+ if (no<=FSEL_LINES)
+ {
+ bar_step = 0;
+ bar_size = FSEL_LIST_H;
+ }
+ else
+ {
+ bar_step = FSEL_LIST_H/(double)no;
+ bar_size = bar_step*FSEL_LINES;
+ }
+
+ while(!done)
+ {
+ uint32 key=0;
+
+ for (f=0;f<FSEL_LINES;f++)
+ {
+ off = f + top;
+
+ if (off<no)
+ {
+ if (off == sel)
+ {
+ paper = COL_GUISELECT;
+ }
+ else
+ {
+ paper = COL_BLACK;
+ }
+
+ FB_printf(8,FSEL_LIST_Y+f*8,COL_WHITE,paper,
+ "%-*s %s",
+ FSEL_FILENAME_LEN,
+ fsel[off].name,
+ fsel[off].is_dir ? "DIR" : " ");
+ }
+ else
+ {
+ FB_printf(8,FSEL_LIST_Y+f*8,COL_WHITE,COL_BLACK,
+ "%-*s %s",
+ FSEL_FILENAME_LEN,
+ off==0 ? "No Files!" : "",
+ " ");
+ }
+ }
+
+ FB_FillBox(240,FSEL_LIST_Y,16,FSEL_LIST_H,COL_DARKGREY);
+ FB_FillBox(240,FSEL_LIST_Y+top*bar_step,16,bar_size,COL_WHITE);
+
+ if (drag)
+ {
+ touchPosition tp = {0};
+ int diff = 0;
+
+ while (((key=keysHeld()) & KEY_TOUCH) && diff == 0)
+ {
+ tp = touchReadXY();
+ diff = tp.py - drag_start;
+ swiWaitForVBlank();
+ }
+
+ if (key & KEY_TOUCH)
+ {
+ int new_top;
+
+ new_top = top + diff / bar_step;
+
+ if (new_top > (no - FSEL_LINES))
+ {
+ new_top = no - FSEL_LINES;
+ }
+
+ if (new_top < 0)
+ {
+ new_top = 0;
+ }
+
+ if (new_top != top)
+ {
+ top = new_top;
+ sel = top;
+ drag_start = tp.py;
+ }
+ }
+ else
+ {
+ drag = FALSE;
+ }
+ }
+
+ if (!drag)
+ {
+ int activate = FALSE;
+
+ do
+ {
+ swiWaitForVBlank();
+ } while(!(key=keysDownRepeat()));
+
+ if (key & KEY_TOUCH)
+ {
+ touchPosition tp;
+
+ tp = touchReadXY();
+
+ if (tp.py >= FSEL_LIST_Y && tp.py <= (FSEL_LIST_Y+FSEL_LIST_H))
+ {
+ if (tp.px > 239)
+ {
+ drag = TRUE;
+ drag_start = tp.py;
+ }
+ else
+ {
+ int new_sel;
+
+ new_sel = top + (tp.py - FSEL_LIST_Y)/8;
+
+ if (new_sel < no)
+ {
+ if (new_sel == sel)
+ {
+ activate = TRUE;
+ }
+ else
+ {
+ sel = new_sel;
+ }
+ }
+ }
+ }
+ }
+ else if (key & KEY_UP)
+ {
+ if (sel)
+ {
+ sel--;
+
+ if (sel<top)
+ {
+ top--;
+ }
+ }
+ }
+ else if (key & KEY_DOWN)
+ {
+ if (sel < (no-1))
+ {
+ sel++;
+
+ if (sel >= (top+FSEL_LINES))
+ {
+ top++;
+ }
+ }
+ }
+ else if (key & KEY_L)
+ {
+ if (sel)
+ {
+ sel-=FSEL_LINES;
+
+ if (sel < 0)
+ {
+ sel = 0;
+ }
+
+ top = sel;
+ }
+ }
+ else if (key & KEY_R)
+ {
+ if (sel < (no-1))
+ {
+ sel+=FSEL_LINES;
+
+ if (sel > (no-1))
+ {
+ sel = no-1;
+ }
+
+ top = sel - FSEL_LINES + 1;
+
+ if (top < 0)
+ {
+ top = 0;
+ }
+ }
+ }
+ else if (key & KEY_A)
+ {
+ activate = TRUE;
+ }
+ else if (key & KEY_B)
+ {
+ done = TRUE;
+ }
+
+ if (activate)
+ {
+ if (fsel[sel].is_dir)
+ {
+ AddPath(pwd,fsel[sel].name);
+
+ FB_printf(0,0,COL_BLACK,COL_LIGHTGREY,"%-32.32s",pwd);
+
+ no = LoadDir(pwd,filter);
+
+ sel = 0;
+ top = 0;
+
+ if (no<=FSEL_LINES)
+ {
+ bar_step = 0;
+ bar_size = FSEL_LIST_H;
+ }
+ else
+ {
+ bar_step = FSEL_LIST_H/(double)no;
+ bar_size = bar_step*FSEL_LINES;
+ }
+ }
+ else
+ {
+ done = TRUE;
+ ret = TRUE;
+
+ strcpy(selected_file,pwd);
+ strcat(selected_file,fsel[sel].name);
+ }
+ }
+ }
+ }
+
+ while (keysHeld());
+
+ return ret;
+}
diff --git a/arm9/source/keyboard.c b/arm9/source/keyboard.c
new file mode 100644
index 0000000..f838bdd
--- /dev/null
+++ b/arm9/source/keyboard.c
@@ -0,0 +1,411 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+
+#include "keyboard.h"
+#include "framebuffer.h"
+#include "touchwrap.h"
+#include "keyb_bin.h"
+
+/* ---------------------------------------- STATIC DATA
+*/
+
+#define PAL_OFFSET 110
+
+static int is_dim = FALSE;
+static int selection_on = COL_WHITE;
+static int selection_off = COL_BLACK;
+
+static struct
+{
+ int state;
+ int new_state;
+ int handled;
+ int is_sticky;
+} key_state[NUM_SOFT_KEYS];
+
+static SoftKey pad_left_key = SK_5;
+static SoftKey pad_right_key = SK_8;
+static SoftKey pad_up_key = SK_7;
+static SoftKey pad_down_key = SK_6;
+static SoftKey pad_A_key = SK_0;
+static SoftKey pad_B_key = SK_ENTER;
+static SoftKey pad_X_key = NUM_SOFT_KEYS;
+static SoftKey pad_Y_key = NUM_SOFT_KEYS;
+static SoftKey pad_R_key = NUM_SOFT_KEYS;
+static SoftKey pad_L_key = NUM_SOFT_KEYS;
+static SoftKey pad_start_key = NUM_SOFT_KEYS;
+static SoftKey pad_select_key = NUM_SOFT_KEYS;
+
+#define CLEAR_STATE(SHORTCUT) \
+ do \
+ { \
+ if (SHORTCUT != NUM_SOFT_KEYS && \
+ !key_state[SHORTCUT].handled) \
+ { \
+ key_state[SHORTCUT].new_state = FALSE; \
+ } \
+ } while(0)
+
+#define CHECK_STATE(KEYS,BIT,CODE,SHORTCUT,USE_SHORTCUT) \
+ do \
+ { \
+ key_state[CODE].new_state = (KEYS & BIT); \
+ if (USE_SHORTCUT && SHORTCUT != NUM_SOFT_KEYS && \
+ !key_state[SHORTCUT].handled && (KEYS & BIT)) \
+ { \
+ key_state[SHORTCUT].new_state = TRUE; \
+ } \
+ } while(0)
+
+
+static const char *keynames[]=
+{
+ "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", "0",
+ "Q", "W", "E", "R", "T",
+ "Y", "U", "I", "O", "P",
+ "A", "S", "D", "F", "G",
+ "H", "J", "K", "L", "ENTER",
+ "CAPS SHIFT", "Z", "X", "C", "V",
+ "B", "N", "M", "SYMBOL SHIFT", "SPACE",
+
+ "ABOUT",
+ "CONFIG",
+ "JOYPAD UP",
+ "JOYPAD DOWN",
+ "JOYPAD LEFT",
+ "JOYPAD RIGHT",
+ "A BUTTON",
+ "B BUTTON",
+ "X BUTTON",
+ "Y BUTTON",
+ "RIGHT SHOULDER BUTTON",
+ "LEFT SHOULDER BUTTON",
+ "START BUTTON",
+ "SELECT BUTTON"
+};
+
+/* ---------------------------------------- PRIVATE INTERFACES
+*/
+static SoftKey LocatePress(const touchPosition *p)
+{
+ int kx=0,ky=0;
+ int py=0;
+ SoftKey key = NUM_SOFT_KEYS;
+
+ if (p->py > 36 && p->px > 2)
+ {
+ kx = (p->px - 3) / 25;
+ ky = p->py - 37;
+
+ py = ky % 30;
+ ky /= 30;
+
+ if (py<17 && kx >= 0 && kx<10 && ky>=0 && ky<=4)
+ {
+ key = kx + ky * 10;
+ }
+ }
+
+ if (key>SK_SPACE)
+ {
+ key = NUM_SOFT_KEYS;
+ }
+
+ return key;
+}
+
+
+static int GetEvent(SoftKeyEvent *ev, int map)
+{
+ static SoftKey last = NUM_SOFT_KEYS;
+ static int poll_index = -1;
+
+ /* Read the keys if this is a new loop
+ */
+ if (poll_index == -1)
+ {
+ int f;
+ uint32 keys;
+
+ keys = keysHeld();
+
+ /* Clear the non-sticky keys
+ */
+ for(f=SK_1; f<=SK_CONFIG; f++)
+ {
+ key_state[f].handled = FALSE;
+
+ if (key_state[f].is_sticky)
+ {
+ key_state[f].new_state = key_state[f].state;
+ }
+ else
+ {
+ key_state[f].new_state = FALSE;
+ }
+ }
+
+ /* Check the soft keyboard
+ */
+ if (keys & KEY_TOUCH)
+ {
+ touchPosition tp;
+
+ if (AllowTouch(&tp))
+ {
+ if (tp.py<21 || tp.py>165)
+ {
+ key_state[SK_CONFIG].new_state = TRUE;
+ }
+ else
+ {
+ SoftKey press;
+
+ press = LocatePress(&tp);
+
+ if (press != NUM_SOFT_KEYS)
+ {
+ key_state[press].handled = TRUE;
+
+ if (key_state[press].is_sticky)
+ {
+ if (last != press)
+ {
+ key_state[press].new_state =
+ !key_state[press].state;
+ }
+ }
+ else
+ {
+ key_state[press].new_state = TRUE;
+ }
+
+ last = press;
+ }
+ }
+ }
+ }
+ else
+ {
+ last = NUM_SOFT_KEYS;
+ }
+
+ /* Check non soft-keyboard controls
+ */
+ CHECK_STATE(keys, KEY_A, SK_PAD_A, pad_A_key, map);
+ CHECK_STATE(keys, KEY_B, SK_PAD_B, pad_B_key, map);
+ CHECK_STATE(keys, KEY_X, SK_PAD_X, pad_X_key, map);
+ CHECK_STATE(keys, KEY_Y, SK_PAD_Y, pad_Y_key, map);
+ CHECK_STATE(keys, KEY_R, SK_PAD_R, pad_R_key, map);
+ CHECK_STATE(keys, KEY_L, SK_PAD_L, pad_L_key, map);
+ CHECK_STATE(keys, KEY_START, SK_PAD_START, pad_start_key, map);
+ CHECK_STATE(keys, KEY_SELECT, SK_PAD_SELECT, pad_select_key, map);
+ CHECK_STATE(keys, KEY_UP, SK_PAD_UP, pad_up_key, map);
+ CHECK_STATE(keys, KEY_DOWN, SK_PAD_DOWN, pad_down_key, map);
+ CHECK_STATE(keys, KEY_LEFT, SK_PAD_LEFT, pad_left_key, map);
+ CHECK_STATE(keys, KEY_RIGHT, SK_PAD_RIGHT, pad_right_key, map);
+
+ /* Reset key event poll index
+ */
+ poll_index = 0;
+
+ /* Update any on-screen indicators
+ */
+ for(f=SK_1; f<SK_CONFIG; f++)
+ {
+ if (key_state[f].state != key_state[f].new_state)
+ {
+ int x,y;
+
+ x = 3 + (f % 10) * 25;
+ y = 37 + (f / 10) * 30;
+
+ FB_Box(x, y, 25, 18, key_state[f].new_state ?
+ selection_on : selection_off);
+ }
+ }
+ }
+
+ while(poll_index < NUM_SOFT_KEYS &&
+ key_state[poll_index].state == key_state[poll_index].new_state)
+ {
+ poll_index++;
+ }
+
+ if (poll_index < NUM_SOFT_KEYS)
+ {
+ key_state[poll_index].state = key_state[poll_index].new_state;
+
+ ev->key = poll_index;
+ ev->pressed = key_state[poll_index].state;
+
+ return TRUE;
+ }
+ else
+ {
+ poll_index = -1;
+ return FALSE;
+ }
+}
+
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+void SK_DisplayKeyboard(void)
+{
+ static sImage img;
+ static int loaded;
+
+ if (!loaded)
+ {
+ loadPCX(keyb_bin,&img);
+ loaded = true;
+ }
+
+ FB_Blit(&img,0,0,PAL_OFFSET);
+}
+
+
+void SK_SetDisplayBrightness(int dim)
+{
+ static uint16 saved_pal[16];
+ int f;
+ uint16 *pal;
+
+ pal = FB_PALETTE();
+
+ if (dim != is_dim)
+ {
+ is_dim = dim;
+
+ if (is_dim)
+ {
+ selection_on = COL_DARKGREY;
+
+ for(f=0;f<16;f++)
+ {
+ int r,g,b;
+
+ saved_pal[f] = pal[PAL_OFFSET + f];
+
+ r = saved_pal[f] & 0x1f;
+ g = (saved_pal[f]>>5) & 0x1f;
+ b = (saved_pal[f]>>10) & 0x1f;
+
+ r/=3;
+ g/=3;
+ b/=3;
+
+ pal[PAL_OFFSET + f] = RGB15(r,g,b);
+ }
+ }
+ else
+ {
+ selection_on = COL_WHITE;
+
+ for(f=0;f<16;f++)
+ {
+ pal[PAL_OFFSET + f] = saved_pal[f];
+ }
+ }
+ }
+}
+
+
+int SK_GetEvent(SoftKeyEvent *ev)
+{
+ return GetEvent(ev,TRUE);
+}
+
+
+int SK_GetBareEvent(SoftKeyEvent *ev)
+{
+ return GetEvent(ev,FALSE);
+}
+
+
+void SK_SetSticky(SoftKey key, int is_sticky)
+{
+ key_state[key].is_sticky = is_sticky;
+
+ if (!is_sticky)
+ {
+ key_state[key].new_state = FALSE;
+ }
+}
+
+
+void SK_DefinePad(SoftKey pad, SoftKey key)
+{
+ switch(pad)
+ {
+ case SK_PAD_LEFT:
+ pad_left_key = key;
+ break;
+ case SK_PAD_RIGHT:
+ pad_right_key = key;
+ break;
+ case SK_PAD_UP:
+ pad_up_key = key;
+ break;
+ case SK_PAD_DOWN:
+ pad_down_key = key;
+ break;
+ case SK_PAD_A:
+ pad_A_key = key;
+ break;
+ case SK_PAD_B:
+ pad_B_key = key;
+ break;
+ case SK_PAD_X:
+ pad_X_key = key;
+ break;
+ case SK_PAD_Y:
+ pad_Y_key = key;
+ break;
+ case SK_PAD_R:
+ pad_R_key = key;
+ break;
+ case SK_PAD_L:
+ pad_L_key = key;
+ break;
+ case SK_PAD_START:
+ pad_start_key = key;
+ break;
+ case SK_PAD_SELECT:
+ pad_select_key = key;
+ break;
+ default:
+ break;
+ }
+}
+
+
+const char *SK_KeyName(SoftKey k)
+{
+ return keynames[k];
+}
+
+
diff --git a/arm9/source/main.c b/arm9/source/main.c
new file mode 100644
index 0000000..b32174a
--- /dev/null
+++ b/arm9/source/main.c
@@ -0,0 +1,427 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <nds.h>
+#include <fat.h>
+
+#include "framebuffer.h"
+#include "gui.h"
+#include "keyboard.h"
+#include "z80.h"
+#include "config.h"
+#include "textmode.h"
+#include "monitor.h"
+#include "tapes.h"
+#include "spec.h"
+
+#include "splashimg_bin.h"
+
+#ifndef DS48_VERSION
+#define DS48_VERSION "DEV " __TIME__ "/" __DATE__
+#endif
+
+
+/* ---------------------------------------- STATIC DATA
+*/
+static const char *main_menu[]=
+ {
+ "Reset Spectrum",
+ "Select Tape",
+ "Configure",
+ "Map Joypad to Keys",
+ "Machine Code Monitor",
+ "Cancel",
+ NULL
+ };
+
+typedef enum
+{
+ MenuReset,
+ MenuSelectTape,
+ MenuConfigure,
+ MenuMapJoypad,
+ MenuMonitor,
+} MenuOpt;
+
+/* ---------------------------------------- IRQ FUNCS
+*/
+
+/* ---------------------------------------- DISPLAY FUNCS
+*/
+static void VBlankFunc(void)
+{
+ scanKeys();
+}
+
+static void Splash(void)
+{
+ static char scroller[]=
+ {
+ " "
+ "Welcome to DS48, a ZX Spectrum emulator for the Ninetendo DS. "
+ "You may note a cunning similarity to the ZX81 emulator, DS81, in "
+ "some of this emulator's appearance... "
+ "Any similarity is purely intentional. "
+ "Thanks, as ever, to Slay Radio for coding fuel."
+ };
+
+ static const char *text[]=
+ {
+ "DS48 \177 2006 Ian C",
+ " ",
+ "Spectrum ROM \177 Amstrad",
+ " ",
+ "Amstrad have kindly given",
+ "permission for the Spectrum",
+ "ROM to be distributed along",
+ "with emulators.",
+ " ",
+ "PRESS A TO CONTINUE",
+ " ",
+ "http://www.noddybox.co.uk/",
+ " ",
+ " ",
+ "Checking for FAT device...",
+ NULL
+ };
+
+ static const char *fat_text[]=
+ {
+ "Found a FAT device.",
+ "If you place tape files in",
+ "the top directory or /SPECGAME",
+ "then you should be able to load",
+ "with the command LOAD \"FILE\"",
+ NULL
+ };
+
+ static const char *no_fat_text[]=
+ {
+ "Sorry, but you dont have a",
+ "supported FAT device.",
+ "Only the internal tape",
+ "files can be used.",
+ NULL
+ };
+
+ sImage img;
+ int f;
+ int y;
+ int res=FALSE;
+ int scr_x=0;
+
+ SUB_BG2_XDX = 0x080;
+ SUB_BG2_YDY = 0x080;
+
+ TM_printf(0,11,"%-18.18s",scroller);
+
+ FB_Clear();
+
+ loadPCX(splashimg_bin,&img);
+
+ FB_Blit(&img,0,0,1);
+
+ y = 10;
+
+ for(f=0;text[f];f++)
+ {
+ FB_Centre(text[f],y,COL_WHITE,COL_TRANSPARENT);
+ y += 8;
+ }
+
+ y += 8;
+
+#ifndef DS48_DISABLE_FAT
+ res = fatInitDefault();
+#endif
+
+ if (res)
+ {
+ SPECEnableFileSystem(TRUE);
+
+ for(f=0;fat_text[f];f++)
+ {
+ FB_Centre(fat_text[f],y,COL_WHITE,COL_TRANSPARENT);
+ y += 8;
+ }
+ }
+ else
+ {
+ SPECEnableFileSystem(FALSE);
+
+ for(f=0;no_fat_text[f];f++)
+ {
+ FB_Centre(no_fat_text[f],y,COL_WHITE,COL_TRANSPARENT);
+ y += 8;
+ }
+ }
+
+ while(!(keysDown() & KEY_A))
+ {
+ swiWaitForVBlank();
+
+ if (++scr_x == 8)
+ {
+ size_t l = sizeof scroller;
+ char c;
+
+ scr_x = 0;
+
+ c = scroller[0];
+ memmove(scroller,scroller+1,l-2);
+ scroller[l-2] = c;
+
+ TM_printf(0,11,"%-18.18s",scroller);
+ }
+
+ SUB_BG2_CX = scr_x << 8;
+ }
+
+ SUB_BG2_XDX = 0x100;
+ SUB_BG2_YDY = 0x100;
+ SUB_BG2_CX = 0;
+
+ TM_Cls();
+}
+
+
+/* ---------------------------------------- JOYPAD MAPPING
+*/
+static void MapJoypad(void)
+{
+#if 0
+ SoftKeyEvent ev;
+ SoftKey pad = NUM_SOFT_KEYS;
+ int done = FALSE;
+ char text[256];
+
+ SK_DisplayKeyboard();
+
+ ZX SpectrumSuspendDisplay();
+
+ ZX SpectrumDisplayString("press the joypad button you want\n"
+ "to define and then the ZX Spectrum key\n"
+ "you want to use.\n\n"
+ "press on the config banner to\n"
+ "finish.");
+
+ while(!done)
+ {
+ while(SK_GetBareEvent(&ev))
+ {
+ if (ev.pressed)
+ {
+ if (ev.key==SK_ABOUT || ev.key==SK_CONFIG)
+ {
+ done = true;
+ }
+ }
+ else
+ {
+ if (ev.key>=SK_PAD_UP && ev.key<=SK_PAD_SELECT)
+ {
+ pad = ev.key;
+
+ /* Now, just how dumb was making % the inverse on/off...
+ */
+ sprintf(text,"defining\n %%%s%%",SK_KeyName(pad));
+ ZX SpectrumDisplayString(text);
+ }
+
+ if (ev.key<=SK_SPACE && pad!=NUM_SOFT_KEYS)
+ {
+ sprintf(text,"mapped\n %%%s%%\nto\n %%%s%%",
+ SK_KeyName(pad),SK_KeyName(ev.key));
+ ZX SpectrumDisplayString(text);
+
+ SK_DefinePad(pad,ev.key);
+
+ pad = NUM_SOFT_KEYS;
+ }
+ }
+ }
+
+ swiWaitForVBlank();
+ }
+
+ ZX SpectrumResumeDisplay();
+#endif
+}
+
+
+/* ---------------------------------------- MAIN
+*/
+int main(int argc, char *argv[])
+{
+ Z80 *z80;
+
+ powerON(POWER_ALL_2D);
+
+ /* Set up main screen for ZX Spectrum.
+ */
+ videoSetMode(MODE_3_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE);
+
+ vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
+ vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
+
+ BG0_CR = BG_COLOR_256 | BG_32x32 | BG_MAP_BASE(0) |
+ BG_TILE_BASE(1) | BG_PRIORITY(0);
+ BG0_X0 = 0;
+ BG0_Y0 = 0;
+
+ BG_PALETTE[0] = RGB15(31,31,31);
+ BG_PALETTE[1] = RGB15(0,0,0);
+
+ BG3_CR = BG_BMP16_256x256 | BG_BMP_BASE(2) | BG_PRIORITY(1);
+ BG3_XDX = 0x100;
+ BG3_XDY = 0;
+ BG3_YDX = 0;
+ BG3_YDY = 0x100;
+ BG3_CX = 0;
+ BG3_CY = 0;
+
+ /* Set up the sub-screen for rotation (basically for use as a framebuffer).
+ Now overlaid with a text screen for the monitor (I thought a bitmapped
+ printing routine would needlessly slow down the monitor when watching
+ the Spectrum run). Having said the overlay is currently a rotation map
+ for some pointless frippery! Still be quicker though.
+ */
+ videoSetModeSub(MODE_4_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG3_ACTIVE);
+ vramSetBankC(VRAM_C_SUB_BG_0x06200000);
+
+ SUB_BG2_CR = BG_COLOR_256 | BG_RS_32x32 | BG_MAP_BASE(4) |
+ BG_TILE_BASE(0) | BG_PRIORITY(0);
+ SUB_BG2_XDX = 0x100;
+ SUB_BG2_XDY = 0;
+ SUB_BG2_YDX = 0;
+ SUB_BG2_YDY = 0x100;
+ SUB_BG2_CX = 0;
+ SUB_BG2_CY = 0;
+
+ SUB_BG3_CR = BG_BMP8_256x256 | BG_BMP_BASE(1) | BG_PRIORITY(1);
+ SUB_BG3_XDX = 0x100;
+ SUB_BG3_XDY = 0;
+ SUB_BG3_YDX = 0;
+ SUB_BG3_YDY = 0x100;
+ SUB_BG3_CX = 0;
+ SUB_BG3_CY = 0;
+
+ /* Tell 'framebuffer' routines to use this
+ */
+ FB_Init((uint16*)BG_BMP_RAM_SUB(1), BG_PALETTE_SUB);
+
+ /* Set up lower screen text overlay
+ */
+ FB_LoadASCIITiles((uint16*)BG_TILE_RAM_SUB(0));
+ TM_Init((uint16*)BG_MAP_RAM_SUB(4),32,32,TRUE);
+
+ /* Set up interrupts and timers
+ */
+ irqInit();
+ irqSet(IRQ_VBLANK,VBlankFunc);
+ irqEnable(IRQ_VBLANK);
+
+ /* All required stuff initialised
+ */
+ keysSetRepeat(30,15);
+
+ z80 = Z80Init(SPECPeek,
+ SPECPoke,
+ SPECReadPort,
+ SPECWritePort,
+ SPECDisPeek);
+
+ if (!z80)
+ {
+ GUI_Alert(TRUE,"Failed to initialise\nthe Z80 CPU emulation!");
+ }
+
+ SPECInit((uint16*)BG_BMP_RAM(2), z80);
+
+ Splash();
+
+ LoadConfig();
+ SPECReconfigure();
+
+ SK_DisplayKeyboard();
+
+ SK_SetSticky(SK_CAPS_SHIFT,DS48_Config[DS48_STICKY_CAPS]);
+ SK_SetSticky(SK_SYMBOL_SHIFT,DS48_Config[DS48_STICKY_SYM]);
+
+ while(1)
+ {
+ SoftKeyEvent ev;
+
+ /* Z80Exec(z80); */
+
+ while(SK_GetEvent(&ev))
+ {
+ switch(ev.key)
+ {
+ case SK_ABOUT:
+ case SK_CONFIG:
+ if (ev.pressed)
+ {
+ switch(GUI_Menu(main_menu))
+ {
+ case MenuReset:
+ SPECReset(z80);
+ break;
+
+ case MenuSelectTape:
+ SelectTape();
+ break;
+
+ case MenuConfigure:
+ GUI_Config();
+ SK_SetSticky(SK_CAPS_SHIFT,
+ DS48_Config[DS48_STICKY_CAPS]);
+ SK_SetSticky(SK_SYMBOL_SHIFT,
+ DS48_Config[DS48_STICKY_SYM]);
+ SPECReconfigure();
+ break;
+
+ case MenuMapJoypad:
+ MapJoypad();
+ break;
+
+ case MenuMonitor:
+ MachineCodeMonitor(z80);
+ break;
+ }
+
+ SK_DisplayKeyboard();
+ }
+ break;
+
+ default:
+ SPECHandleKey(ev.key,ev.pressed);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/arm9/source/monitor.c b/arm9/source/monitor.c
new file mode 100644
index 0000000..4e29912
--- /dev/null
+++ b/arm9/source/monitor.c
@@ -0,0 +1,362 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+#include <stdlib.h>
+
+#include "monitor.h"
+#include "keyboard.h"
+#include "textmode.h"
+#include "framebuffer.h"
+#include "config.h"
+
+/* ---------------------------------------- PRIVATE DATA AND TYPES
+*/
+typedef enum
+{
+ DISPLAY_ADDR,
+ DISPLAY_HL,
+ DISPLAY_IX,
+ DISPLAY_SP,
+ DISPLAY_IY,
+ DISPLAY_BC,
+ DISPLAY_DE,
+ DISPLAY_PC,
+ DISPLAY_TYPE_COUNT
+} MemDisplayType;
+
+typedef enum
+{
+ MODE_CPU_STATE,
+ MODE_HEX,
+ MODE_ASSEM,
+ MODE_TYPE_COUNT
+} DisplayModeType;
+
+
+/* ---------------------------------------- STATIC INTERFACES
+*/
+static void DisplayHelp()
+{
+ static const char *help[]=
+ {
+ /* 12345678901234567890123456789012 */
+ "MONITOR HELP",
+ "",
+ "Click on the config bar to exit.",
+ "",
+ "Press START to toggle between",
+ "single step mode and running.",
+ "",
+ "Press SELECT to toggle between",
+ "CPU info and memory display.",
+ "",
+ "In single step mode press A",
+ "to execute next instruction.",
+ "",
+ "Use L/R (+ Y for larger jumps)",
+ "to alter address in mem display.",
+ "",
+ "Press B to cycle between address",
+ "and register memory display.",
+ "",
+ "Note that all numbers are in hex",
+ "and the all keyboard keys are",
+ "sticky until the monitor exits.",
+ "",
+ "Press X to continue",
+ NULL
+ };
+
+ int f;
+
+ TM_Cls();
+
+ for(f=0; help[f]; f++)
+ {
+ TM_Put(0,f,help[f]);
+ }
+
+ while(!(keysDownRepeat() & KEY_X))
+ {
+ swiWaitForVBlank();
+ }
+}
+
+static void DisplayRunningState(int running)
+{
+ if (running)
+ {
+ TM_Put(0,23,"RUNNING [PRESS X FOR HELP]");
+ }
+ else
+ {
+ TM_Put(0,23,"SINGLE STEP [PRESS X FOR HELP]");
+ }
+}
+
+
+static void DisplayCPU(Z80 *cpu)
+{
+ static const char *flag_char = "SZ5H3PNC";
+ Z80Word tmp;
+ int f;
+ char flags[]="--------";
+
+ tmp = cpu->PC;
+
+ /* Display disassembly
+ */
+ for(f=0;f<17;f++)
+ {
+ /* These may seem a bit convuluted, but there's no point being at home
+ to Mr Undefined Behaviour
+ */
+ TM_printf(0,f,"%c%4.4x:",f==0 ? '>':' ',tmp);
+ TM_Put(7,f,Z80Disassemble(cpu,&tmp));
+ }
+
+ /* Display process state
+ */
+ tmp = cpu->AF.b[Z80_LO_WORD];
+
+ for(f=0;f<8;f++)
+ {
+ if (tmp & 1<<(7-f))
+ {
+ flags[f] = flag_char[f];
+ }
+ }
+
+ TM_printf(0,18,"A:%2.2x F:%s IM:%2.2x",
+ cpu->AF.b[Z80_HI_WORD],flags,cpu->IM);
+
+ TM_printf(0,19,"BC:%4.4x DE:%4.4x HL:%4.4x",
+ cpu->BC.w,cpu->DE.w,cpu->HL.w);
+
+ TM_printf(0,20,"IX:%4.4x IY:%4.4x SP:%4.4x",
+ cpu->IX.w,cpu->IY.w,cpu->SP);
+
+ TM_printf(0,21,"PC:%4.4x IF:%d/%d IR:%2.2x%2.2x",
+ cpu->PC,cpu->IFF1,cpu->IFF2,cpu->I,cpu->R);
+}
+
+
+static void DisplayMem(Z80 *cpu, MemDisplayType disp, Z80Word addr, int as_hex)
+{
+ static const char *label[]=
+ {
+ "Address",
+ "HL",
+ "IX",
+ "SP",
+ "IY",
+ "BC",
+ "DE",
+ "PC"
+ };
+
+ int x,y;
+
+ switch(disp)
+ {
+ case DISPLAY_HL:
+ addr = cpu->HL.w;
+ break;
+
+ case DISPLAY_IX:
+ addr = cpu->IX.w;
+ break;
+
+ case DISPLAY_SP:
+ addr = cpu->SP;
+ break;
+
+ case DISPLAY_IY:
+ addr = cpu->IY.w;
+ break;
+
+ case DISPLAY_BC:
+ addr = cpu->BC.w;
+ break;
+
+ case DISPLAY_DE:
+ addr = cpu->DE.w;
+ break;
+
+ case DISPLAY_PC:
+ addr = cpu->PC;
+ break;
+
+ default:
+ break;
+ }
+
+ TM_printf(0,0,"%s: %4.4x",label[disp],addr);
+
+ if (as_hex)
+ {
+ for(y=0;y<20;y++)
+ {
+ TM_printf(0,y+2,"%4.4x:",addr);
+
+ for(x=0;x<8;x++)
+ {
+ /*TM_printf(6+x*3,y+2,"%2.2x",ZX81ReadDisassem(cpu,addr++));*/
+ }
+ }
+ }
+ else
+ {
+ for(y=0;y<20;y++)
+ {
+ TM_printf(0,y+2,"%4.4x:",addr);
+ TM_Put(7,y+2,Z80Disassemble(cpu,&addr));
+ }
+ }
+}
+
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+void MachineCodeMonitor(Z80 *cpu)
+{
+ static Z80Word display_address = 0x4000;
+ static MemDisplayType mem_display = DISPLAY_ADDR;
+ int done = FALSE;
+ int running = FALSE;
+ DisplayModeType display_mode = MODE_CPU_STATE;
+ int key;
+ SoftKey soft_key;
+
+ SK_DisplayKeyboard();
+ SK_SetDisplayBrightness(TRUE);
+
+ for(soft_key = SK_1; soft_key <= SK_SPACE; soft_key++)
+ {
+ SK_SetSticky(soft_key,TRUE);
+ }
+
+ while(!done)
+ {
+ TM_Cls();
+ DisplayRunningState(running);
+
+ switch(display_mode)
+ {
+ case MODE_CPU_STATE:
+ DisplayCPU(cpu);
+ break;
+ case MODE_HEX:
+ DisplayMem(cpu,mem_display,display_address,TRUE);
+ break;
+ case MODE_ASSEM:
+ DisplayMem(cpu,mem_display,display_address,FALSE);
+ break;
+ default:
+ TM_Put(0,0,"Oops!");
+ break;
+ }
+
+ do
+ {
+ SoftKeyEvent ev;
+
+ swiWaitForVBlank();
+
+ while(SK_GetBareEvent(&ev))
+ {
+ /*ZX81HandleKey(ev.key,ev.pressed);*/
+
+ if (ev.key == SK_CONFIG && ev.pressed)
+ {
+ done = TRUE;
+ }
+ }
+
+ key = (keysDownRepeat() & ~KEY_TOUCH);
+
+ } while (!done && !running && !key);
+
+ if (key & KEY_START)
+ {
+ running = !running;
+ }
+
+ if (key & KEY_X)
+ {
+ DisplayHelp();
+ }
+
+ if (key & KEY_SELECT)
+ {
+ display_mode = (display_mode+1) % MODE_TYPE_COUNT;
+ }
+
+ if (key & KEY_L)
+ {
+ if (keysHeld() & KEY_Y)
+ {
+ display_address -= 512;
+ }
+ else
+ {
+ display_address -= 64;
+ }
+ }
+
+ if (key & KEY_R)
+ {
+ if (keysHeld() & KEY_Y)
+ {
+ display_address += 512;
+ }
+ else
+ {
+ display_address += 64;
+ }
+ }
+
+ if (key & KEY_B)
+ {
+ mem_display = (mem_display+1) % DISPLAY_TYPE_COUNT;
+ }
+
+ if (running || (key & KEY_A))
+ {
+ Z80SingleStep(cpu);
+ }
+ }
+
+ SK_SetDisplayBrightness(FALSE);
+ TM_Cls();
+
+ for(soft_key = SK_1; soft_key <= SK_SPACE; soft_key++)
+ {
+ SK_SetSticky(soft_key,FALSE);
+ /* ZX81HandleKey(soft_key,FALSE); */
+ }
+
+ SK_SetSticky(SK_CAPS_SHIFT,DS48_Config[DS48_STICKY_CAPS]);
+ SK_SetSticky(SK_SYMBOL_SHIFT,DS48_Config[DS48_STICKY_SYM]);
+
+}
diff --git a/arm9/source/spec.c b/arm9/source/spec.c
new file mode 100644
index 0000000..70b1931
--- /dev/null
+++ b/arm9/source/spec.c
@@ -0,0 +1,507 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn
+
+ 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
+ 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.
+
+ $Id$
+
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <nds.h>
+
+#include "spec.h"
+#include "spec48_bin.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define HIBYTE(w) ((w)>>8)
+#define LOBYTE(w) ((w)&0xff)
+
+
+/* ---------------------------------------- STATICS
+*/
+static uint16 *vram;
+
+static const int ROMLEN=0x4000;
+static const int ROM_SAVE=0x4c6;
+static const int ROM_LOAD=0x562;
+
+#define LOAD_PATCH 0xf0
+#define SAVE_PATCH 0xf1
+
+/* The SPEC screen
+*/
+#define SCR_W 256
+#define SCR_H 192
+#define TXT_W 32
+#define TXT_H 24
+#define SCRDATA 0x4000
+#define ATTR 0x5800
+
+#define ATTR_AT(x,y) Z80_MEMORY[ATTR+(x)+((y)/8)*32]
+
+Z80Byte Z80_MEMORY[0x10000];
+
+/* Number of cycles per frame
+*/
+static Z80Val FRAME_CYCLES=69888;
+
+
+/* GFX vars
+*/
+#define FLASH 16 /* Frames per flash */
+
+static int flash=0;
+static int flashctr=0;
+
+#define NVAL 25 /* Normal RGB intensity */
+#define BVAL 31 /* Bright RGB intensity */
+
+static Z80Byte *line[SCR_H]; /* Accelerators to screen data */
+
+static struct
+{
+ uint16 col;
+ int r,g,b;
+} coltable[16]=
+{
+ {0, 0x00,0x00,0x00}, /* BLACK */
+ {0, 0x00,0x00,NVAL}, /* BLUE */
+ {0, NVAL,0x00,0x00}, /* RED */
+ {0, NVAL,0x00,NVAL}, /* MAGENTA */
+ {0, 0x00,NVAL,0x00}, /* GREEN */
+ {0, 0x00,NVAL,NVAL}, /* CYAN */
+ {0, NVAL,NVAL,0x00}, /* YELLOW */
+ {0, NVAL,NVAL,NVAL}, /* WHITE */
+
+ {0, 0x00,0x00,0x00}, /* BLACK */
+ {0, 0x00,0x00,BVAL}, /* BLUE */
+ {0, BVAL,0x00,0x00}, /* RED */
+ {0, BVAL,0x00,BVAL}, /* MAGENTA */
+ {0, 0x00,BVAL,0x00}, /* GREEN */
+ {0, 0x00,BVAL,BVAL}, /* CYAN */
+ {0, BVAL,BVAL,0x00}, /* YELLOW */
+ {0, BVAL,BVAL,BVAL}, /* WHITE */
+
+};
+
+
+/* The keyboard
+*/
+static Z80Byte matrix[8];
+
+static struct
+{
+ int row;
+ int bit;
+} key_matrix[]=
+ {
+ {3,0x01}, {3,0x02}, {3,0x04}, {3,0x08}, {3,0x10}, /* 1 - 5 */
+ {4,0x10}, {4,0x08}, {4,0x04}, {4,0x02}, {4,0x01}, /* 6 - 0 */
+ {2,0x01}, {2,0x02}, {2,0x04}, {2,0x08}, {2,0x10}, /* Q - T */
+ {5,0x10}, {5,0x08}, {5,0x04}, {5,0x02}, {5,0x01}, /* Y - P */
+ {1,0x01}, {1,0x02}, {1,0x04}, {1,0x08}, {1,0x10}, /* A - G */
+ {6,0x10}, {6,0x08}, {6,0x04}, {6,0x02}, {6,0x01}, /* H - NL */
+ {0,0x01}, {0,0x02}, {0,0x04}, {0,0x08}, {0,0x10}, /* CAPS - V */
+ {7,0x10}, {7,0x08}, {7,0x04}, {7,0x02}, {7,0x01} /* B - SPACE */
+ };
+
+static int debug_matrix = FALSE;
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void FillBox(int x, int y, int w, int h, int colour)
+{
+ int f;
+ uint16 *base;
+
+ colour|=0x8000;
+
+ base=vram+x+y*256;
+
+ while(h--)
+ {
+ for(f=0;f<w;f++)
+ {
+ *(base+f)=colour;
+ }
+
+ base+=256;
+ }
+}
+
+
+
+static void DrawScreen(void)
+{
+ int f,r;
+ int ink,paper,t;
+ int y;
+ Z80Byte *scr;
+ Z80Byte b;
+ Z80Byte att;
+ uint16 *vr;
+
+ vr=vram;
+
+ /* swiWaitForVBlank(); */
+
+ for(y=0;y<SCR_H;y++)
+ {
+ scr=line[y];
+
+ for(f=0;f<TXT_W;f++)
+ {
+ att=ATTR_AT(f,y);
+
+ ink=(att&0x07);
+ paper=(att&0x38)>>3;
+
+ if (att&0x40)
+ {
+ ink+=8;
+ paper+=8;
+ }
+
+ if ((att&0x80)&&(flash))
+ {
+ t=ink;
+ ink=paper;
+ paper=t;
+ }
+
+ b=*scr++;
+
+ for(r=0;r<8;r++)
+ {
+ if (b&(1<<(7-r)))
+ {
+ *vr++=coltable[ink].col;
+ }
+ else
+ {
+ *vr++=coltable[paper].col;
+ }
+ }
+ }
+ }
+
+ if (debug_matrix)
+ {
+ int m;
+ int b;
+
+ for(m=0;m<8;m++)
+ {
+ for(b=0;b<8;b++)
+ {
+ uint16 col;
+
+ if (matrix[m]&(1<<b))
+ {
+ col=RGB15(0,31,0);
+ }
+ else
+ {
+ col=RGB15(31,0,0);
+ }
+
+ FillBox((7-b)*5,150+m*5,4,4,col);
+ }
+ }
+ }
+}
+
+static void RomPatch(void)
+{
+ static const Z80Byte save[]=
+ {
+ 0xed, SAVE_PATCH, /* ED illegal op */
+ 0xc9, /* RET */
+ 0xff /* End of patch */
+ };
+
+ static const Z80Byte load[]=
+ {
+ 0x08, /* EX AF,AF' */
+ 0xed, LOAD_PATCH, /* ED illegal op */
+ 0xc9, /* RET */
+ 0xff /* End of patch */
+ };
+
+ int f;
+
+ for(f=0;save[f]!=0xff;f++)
+ Z80_MEMORY[ROM_SAVE+f]=save[f];
+
+ for(f=0;load[f]!=0xff;f++)
+ Z80_MEMORY[ROM_LOAD+f]=load[f];
+}
+
+
+Z80Byte SPECPeek(Z80 *cpu, Z80Word addr)
+{
+ return Z80_MEMORY[addr];
+}
+
+
+void SPECPoke(Z80 *cpu, Z80Word addr, Z80Byte val)
+{
+ if (addr>=ROMLEN)
+ Z80_MEMORY[addr]=val;
+}
+
+
+static int EDCallback(Z80 *z80, Z80Val data)
+{
+ switch((Z80Byte)data)
+ {
+ case SAVE_PATCH:
+ z80->AF.w&=~eZ80_Carry;
+ break;
+
+ case LOAD_PATCH:
+ /*
+ if (TAPLoad(HIBYTE(state.AF),
+ z80->IX,
+ z80->DE,
+ SnapPoke))
+ {
+ state.AF|=eZ80_Carry;
+ state.BC=0xb001;
+ }
+ else
+ {
+ state.AF&=~eZ80_Carry;
+ state.BC=0xff01;
+ }
+ */
+
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+static int CheckTimers(Z80 *z80, Z80Val val)
+{
+ if (val>FRAME_CYCLES)
+ {
+ Z80ResetCycles(z80,val-FRAME_CYCLES);
+
+ flashctr++;
+
+ if (flashctr==FLASH)
+ {
+ flash^=1;
+ flashctr=0;
+ }
+
+ Z80Interrupt(z80,0xff);
+
+ DrawScreen();
+
+ /* TODO: Process sound emulation */
+
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void SPECInit(uint16 *v, Z80 *z80)
+{
+ vram=v;
+
+ memcpy(Z80_MEMORY,spec48_bin,ROMLEN);
+
+ /* Patch the ROM
+ */
+ RomPatch();
+ Z80LodgeCallback(z80,eZ80_EDHook,EDCallback);
+ Z80LodgeCallback(z80,eZ80_Instruction,CheckTimers);
+
+ SPECReset(z80);
+}
+
+
+void SPECHandleKey(SoftKey key, int is_pressed)
+{
+ if (key<SK_CONFIG)
+ {
+ if (is_pressed)
+ {
+ matrix[key_matrix[key].row]&=~key_matrix[key].bit;
+ }
+ else
+ {
+ matrix[key_matrix[key].row]|=key_matrix[key].bit;
+ }
+ }
+ else
+ {
+ /* TODO: Joysticks! */
+
+ if (is_pressed && key==SK_PAD_SELECT)
+ {
+ debug_matrix = !debug_matrix;
+ }
+ }
+}
+
+
+void SPECEnableFileSystem(int enable)
+{
+}
+
+
+void SPECSetTape(const Z80Byte *image, int len)
+{
+}
+
+
+Z80Byte SPECReadPort(Z80 *z80, Z80Word port)
+{
+ Z80Byte lo=port&0xff;
+ Z80Byte hi=port>>8;
+ Z80Byte b=0xff;
+ int f;
+
+ switch(lo)
+ {
+ case 0x1f: /* Kempston joystick */
+ break;
+
+ case 0x7f: /* Fuller joystick */
+ break;
+
+ case 0xfb: /* ZX Printer */
+ break;
+
+ default: /* ULA */
+ if (!(lo&1))
+ {
+ /* Key matrix
+ */
+ b=0xff;
+
+ for(f=0;f<8;f++)
+ if (!(hi&(1<<f)))
+ b&=matrix[f];
+
+ b|=0xa0;
+
+ /* TODO: Emulation of contention? */
+ }
+ else
+ b=0xff;
+ break;
+ }
+
+ return b;
+}
+
+
+void SPECWritePort(Z80 *z80, Z80Word port, Z80Byte val)
+{
+ Z80Byte lo=port&0xff;
+
+ switch(lo)
+ {
+ case 0xfe: /* ULA */
+ break;
+
+ case 0xfb: /* ZX Printer */
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+void SPECReset(Z80 *z80)
+{
+ int f;
+ int c;
+ int r;
+
+ /* Set up the keyboard
+ */
+ for(f=0;f<8;f++)
+ {
+ matrix[f]=0x1f;
+ }
+
+ /* Set up the colours
+ */
+ for(f=0;f<16;f++)
+ {
+ coltable[f].col=0x8000|RGB15(coltable[f].r,coltable[f].g,coltable[f].b);
+ }
+
+ flash=0;
+ flashctr=0;
+
+ /* Set up screen
+ */
+ c=0;
+ r=0;
+ for(f=0;f<SCR_H;f++)
+ {
+ line[f]=Z80_MEMORY+SCRDATA+(c*8*TXT_W)+(r*TXT_W);
+
+ c++;
+
+ if ((c%8)==0)
+ {
+ if (++r==8)
+ r=0;
+ else
+ c-=8;
+ }
+ }
+
+ Z80ResetCycles(z80,0);
+ Z80Reset(z80);
+}
+
+
+void SPECReconfigure(void)
+{
+}
+
+
+/* END OF FILE */
diff --git a/arm9/source/tapes.c b/arm9/source/tapes.c
new file mode 100644
index 0000000..1ec8bc5
--- /dev/null
+++ b/arm9/source/tapes.c
@@ -0,0 +1,160 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+#include <stdlib.h>
+
+#include "tapes.h"
+#include "framebuffer.h"
+#include "keyboard.h"
+
+#include "ant_tape_bin.h"
+
+
+/* ---------------------------------------- STATIC DATA
+*/
+typedef struct
+{
+ const u8 *tape;
+ const u32 *tape_len;
+ SoftKey *keys;
+ const char **text;
+} Tape;
+
+#define NO_TAPES 1
+
+static SoftKey ant_keys[]=
+ {
+ SK_PAD_UP, SK_V,
+ SK_PAD_LEFT, SK_M,
+ SK_PAD_RIGHT, SK_SYMBOL_SHIFT,
+ SK_PAD_Y, SK_S,
+ SK_PAD_X, SK_D,
+ SK_PAD_A, SK_F,
+ SK_PAD_DOWN, SK_G,
+ SK_PAD_B, SK_C,
+ SK_PAD_L, SK_O,
+ SK_PAD_R, SK_P,
+ SK_PAD_START, SK_ENTER,
+ SK_PAD_SELECT, SK_SPACE,
+ NUM_SOFT_KEYS
+ };
+
+static const char *ant_text[]=
+ {
+ /* 01234567890123456789012345678901 */
+ "ANT ATTACK",
+ " ",
+ "(c) 1983",
+ "Sandy White & Angela Sutherland",
+ " ",
+ "Brave the city of Antescher.",
+ " ",
+ "Use left and right to turn, up",
+ "to go forwards and B to jump.",
+ " ",
+ "Y, X and A throw grenades near,",
+ "then further away. Down throws",
+ "as hard as you can.",
+ " ",
+ "Use the shoulder buttons, start",
+ "and select to alter the view.",
+ NULL
+ };
+
+static Tape tapes[NO_TAPES]=
+ {
+ {
+ ant_tape_bin,
+ &ant_tape_bin_size,
+ ant_keys,
+ ant_text
+ }
+ };
+
+
+static int current=0;
+
+/* ---------------------------------------- PRIVATE INTERFACES
+*/
+static void DisplayTape(Tape *t)
+{
+ int f;
+
+ FB_Clear();
+
+ for(f=0;t->text[f];f++)
+ {
+ FB_Centre(t->text[f],f*8,COL_WHITE,COL_TRANSPARENT);
+ }
+
+ FB_Centre("Press A to select this tape.",180,COL_YELLOW,COL_TRANSPARENT);
+}
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+void SelectTape(void)
+{
+ int done=FALSE;
+
+ while(!done)
+ {
+ uint32 key=0;
+
+ DisplayTape(tapes+current);
+
+ do
+ {
+ swiWaitForVBlank();
+ } while(!(key=keysDownRepeat()));
+
+ if (key & KEY_LEFT)
+ {
+ if (--current<0)
+ {
+ current=NO_TAPES-1;
+ }
+ }
+ else if (key & KEY_RIGHT)
+ {
+ current=(current+1)%NO_TAPES;
+ }
+ else if (key & KEY_A)
+ {
+ int f;
+
+ done=TRUE;
+ /* ZX81SetTape(tapes[current].tape,*tapes[current].tape_len); */
+
+ for(f=0;tapes[current].keys[f]!=NUM_SOFT_KEYS;f+=2)
+ {
+ SK_DefinePad(tapes[current].keys[f],
+ tapes[current].keys[f+1]);
+ }
+ }
+ else if (key & KEY_B)
+ {
+ done=TRUE;
+ }
+ }
+}
+
diff --git a/arm9/source/textmode.c b/arm9/source/textmode.c
new file mode 100644
index 0000000..5af7f98
--- /dev/null
+++ b/arm9/source/textmode.c
@@ -0,0 +1,157 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "textmode.h"
+
+/* ---------------------------------------- STATIC DATA
+*/
+static int mapw;
+static int maph;
+static uint16 *text;
+static int is_rot;
+static void (*draw_string)(const char *str, int x, int y);
+
+
+/* ---------------------------------------- PRIVATE INTERFACES
+*/
+static inline void Plot_Text(int x, int y, int c)
+{
+ int xw;
+ int yw;
+
+ xw = x/32;
+ yw = y/32;
+ x %= 32;
+ y %= 32;
+
+ *(text + x + y*32 + (xw+yw) * 1024) = c;
+}
+
+
+static inline void Plot_RS(int x, int y, int c)
+{
+ uint16 ch;
+ int odd;
+ uint16 *off;
+
+ odd = x&1;
+
+ off = text + x/2 + y*mapw/2;
+
+ ch = *off;
+
+ if (odd)
+ {
+ ch = (c<<8) | (ch&0xff);
+ }
+ else
+ {
+ ch = c | (ch&0xff00);
+ }
+
+ *off = ch;
+}
+
+
+static void Text_Put(const char *str, int x, int y)
+{
+ while(*str && x<mapw)
+ {
+ Plot_Text(x,y,*str - 32);
+ x++;
+ str++;
+ }
+}
+
+static void RS_Put(const char *str, int x, int y)
+{
+ while(*str && x<mapw)
+ {
+ Plot_RS(x,y,*str - 32);
+ x++;
+ str++;
+ }
+}
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+void TM_Init(uint16 *vram, int map_width, int map_height, int map_is_rotation)
+{
+ text = vram;
+
+ mapw = map_width;
+ maph = map_height;
+
+ is_rot = map_is_rotation;
+
+ draw_string = map_is_rotation ? RS_Put : Text_Put;
+
+ TM_Cls();
+}
+
+
+void TM_Cls(void)
+{
+ uint16 *scr;
+ int f;
+
+ scr = text;
+
+ if (is_rot)
+ {
+ for(f=0;f<mapw*maph/2;f++)
+ {
+ *scr++=0;
+ }
+ }
+ else
+ {
+ for(f=0;f<mapw*maph;f++)
+ {
+ *scr++=0;
+ }
+ }
+}
+
+
+void TM_Put(int x, int y, const char *str)
+{
+ draw_string(str,x,y);
+}
+
+
+void TM_printf(int x, int y, const char *format, ...)
+{
+ char buff[128];
+ va_list va;
+
+ va_start(va,format);
+ vsnprintf(buff,sizeof buff,format,va);
+ va_end(va);
+
+ draw_string(buff,x,y);
+}
diff --git a/arm9/source/touchwrap.c b/arm9/source/touchwrap.c
new file mode 100644
index 0000000..0115f77
--- /dev/null
+++ b/arm9/source/touchwrap.c
@@ -0,0 +1,55 @@
+/*
+ ds48 - Nintendo DS ZX Spectrum emulator.
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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
+ 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.
+
+ $Id$
+*/
+
+#include <nds.h>
+#include <stdlib.h>
+
+#include "touchwrap.h"
+#include "config.h"
+
+/* ---------------------------------------- PUBLIC INTERFACES
+*/
+int AllowTouch(touchPosition *tp)
+{
+ static touchPosition last;
+ int16 dx;
+ int16 dy;
+ int res;
+
+ *tp = touchReadXY();
+
+ if (DS48_Config[DS48_AVERAGE_TOUCHSCREEN])
+ {
+ dx = last.px - tp->px;
+ dy = last.py - tp->py;
+
+ res = (abs(dx) < 5 && abs(dy) < 5);
+ }
+ else
+ {
+ res = TRUE;
+ }
+
+ last = *tp;
+
+ return res;
+}
diff --git a/arm9/source/z80.c b/arm9/source/z80.c
new file mode 100644
index 0000000..b841b39
--- /dev/null
+++ b/arm9/source/z80.c
@@ -0,0 +1,331 @@
+/*
+
+ z80 - Z80 Emulator
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+ Z80
+
+*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "z80.h"
+#include "z80_private.h"
+
+static const char ident[]="$Id$";
+static const char ident_z80_header[]=Z80_H;
+static const char ident_z80_private_header[]=Z80_PRIVATE_H;
+
+Z80Label *z80_labels=NULL;
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void InitTables()
+{
+ static int init=FALSE;
+
+ if (init)
+ return;
+
+ init=TRUE;
+
+ Z80_InitialiseInternals();
+}
+
+static void Z80_CheckInterrupt(Z80 *cpu)
+{
+ /* Check interrupts
+ */
+ if (PRIV->raise)
+ {
+ if (PRIV->nmi)
+ {
+ if (PRIV->halt)
+ {
+ PRIV->halt=FALSE;
+ CALLBACK(eZ80_Halt,0);
+ cpu->PC++;
+ }
+
+ TSTATE(2);
+ cpu->IFF1=0;
+ PRIV->nmi=FALSE;
+ PUSH(cpu->PC);
+ cpu->PC=0x66;
+ }
+ else if (cpu->IFF1)
+ {
+ if (PRIV->halt)
+ {
+ PRIV->halt=FALSE;
+ CALLBACK(eZ80_Halt,0);
+ cpu->PC++;
+ }
+
+ TSTATE(2);
+
+ cpu->IFF1=0;
+ cpu->IFF2=0;
+
+ switch(cpu->IM)
+ {
+ default:
+ case 0:
+ INC_R;
+ Z80_Decode(cpu,PRIV->devbyte);
+ return;
+ break;
+
+ case 1:
+ PUSH(cpu->PC);
+ cpu->PC=0x38;
+ break;
+
+ case 2:
+ PUSH(cpu->PC);
+ cpu->PC=(Z80Word)cpu->I*256+PRIV->devbyte;
+ break;
+ }
+ }
+
+ PRIV->raise=FALSE;
+ }
+}
+
+
+/* ---------------------------------------- INTERFACES
+*/
+
+#ifdef ENABLE_ARRAY_MEMORY
+Z80 *Z80Init(Z80ReadPort read_port,
+ Z80WritePort write_port)
+#else
+Z80 *Z80Init(Z80ReadMemory read_memory,
+ Z80WriteMemory write_memory,
+ Z80ReadPort read_port,
+ Z80WritePort write_port,
+ Z80ReadMemory read_for_disassem)
+#endif
+{
+ Z80 *cpu;
+ int f;
+ int r;
+
+ InitTables();
+
+#ifndef ENABLE_ARRAY_MEMORY
+ if (!read_memory || !write_memory)
+ return NULL;
+#endif
+
+ cpu=malloc(sizeof *cpu);
+
+ if (cpu)
+ {
+ cpu->priv=malloc(sizeof *cpu->priv);
+
+ if (cpu->priv)
+ {
+#ifndef ENABLE_ARRAY_MEMORY
+ PRIV->mread=read_memory;
+ PRIV->mwrite=write_memory;
+ PRIV->disread=read_for_disassem;
+#endif
+ PRIV->pread=read_port;
+ PRIV->pwrite=write_port;
+
+ for(f=0;f<eZ80_NO_CALLBACK;f++)
+ for(r=0;r<MAX_PER_CALLBACK;r++)
+ PRIV->callback[f][r]=NULL;
+
+ Z80Reset(cpu);
+ }
+ else
+ {
+ free(cpu);
+ cpu=NULL;
+ }
+ }
+
+ return cpu;
+}
+
+
+void Z80Reset(Z80 *cpu)
+{
+ PRIV->cycle=0;
+ cpu->PC=0;
+
+ cpu->AF.w=0xffff;
+ cpu->BC.w=0xffff;
+ cpu->DE.w=0xffff;
+ cpu->HL.w=0xffff;
+ cpu->AF_=0xffff;
+ cpu->BC_=0xffff;
+ cpu->DE_=0xffff;
+ cpu->HL_=0xffff;
+
+ cpu->IX.w=0xffff;
+ cpu->IY.w=0xffff;
+
+ cpu->SP=0xffff;
+ cpu->IFF1=0;
+ cpu->IFF2=0;
+ cpu->IM=0;
+ cpu->I=0;
+ cpu->R=0;
+ PRIV->halt=0;
+
+ PRIV->raise=FALSE;
+ PRIV->nmi=FALSE;
+}
+
+
+Z80Val Z80Cycles(Z80 *cpu)
+{
+ return PRIV->cycle;
+}
+
+
+void Z80ResetCycles(Z80 *cpu, Z80Val cycles)
+{
+ PRIV->cycle=cycles;
+}
+
+
+int Z80LodgeCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback)
+{
+ int f;
+
+ for(f=0;f<MAX_PER_CALLBACK;f++)
+ {
+ if (!PRIV->callback[reason][f])
+ {
+ PRIV->callback[reason][f]=callback;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+void Z80RemoveCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback)
+{
+ int f;
+
+ for(f=0;f<MAX_PER_CALLBACK;f++)
+ {
+ if (PRIV->callback[reason][f]==callback)
+ {
+ PRIV->callback[reason][f]=NULL;
+ }
+ }
+}
+
+
+void Z80Interrupt(Z80 *cpu, Z80Byte devbyte)
+{
+ PRIV->raise=TRUE;
+ PRIV->devbyte=devbyte;
+ PRIV->nmi=FALSE;
+}
+
+
+void Z80NMI(Z80 *cpu)
+{
+ PRIV->raise=TRUE;
+ PRIV->nmi=TRUE;
+}
+
+
+int Z80SingleStep(Z80 *cpu)
+{
+ Z80Byte opcode;
+
+ PRIV->last_cb=TRUE;
+ PRIV->shift=0;
+
+ Z80_CheckInterrupt(cpu);
+
+ CALLBACK(eZ80_Instruction,PRIV->cycle);
+
+ INC_R;
+
+ opcode=FETCH_BYTE;
+
+ Z80_Decode(cpu,opcode);
+
+ return PRIV->last_cb;
+}
+
+
+void Z80Exec(Z80 *cpu)
+{
+ while (Z80SingleStep(cpu));
+}
+
+
+void Z80SetLabels(Z80Label labels[])
+{
+ z80_labels=labels;
+}
+
+
+const char *Z80Disassemble(Z80 *cpu, Z80Word *pc)
+{
+#ifdef ENABLE_DISASSEM
+ Z80Byte Z80_Dis_FetchByte(Z80 *cpu, Z80Word *pc);
+ static char s[80];
+ Z80Word opc,npc;
+ Z80Byte op;
+ int f;
+
+ opc=*pc;
+ op=Z80_Dis_FetchByte(cpu,pc);
+ dis_opcode_z80[op](cpu,op,pc);
+ npc=*pc;
+
+ strcpy(s,Z80_Dis_Printf("%-5s",Z80_Dis_GetOp()));
+ strcat(s,Z80_Dis_Printf("%-40s ;",Z80_Dis_GetArg()));
+
+ for(f=0;f<5 && opc!=npc;f++)
+ {
+#ifdef ENABLE_ARRAY_MEMORY
+ strcat(s,Z80_Dis_Printf(" %.2x",(int)Z80_MEMORY[opc++]));
+#else
+ strcat(s,Z80_Dis_Printf(" %.2x",(int)PRIV->disread(cpu,opc++)));
+#endif
+ }
+
+ if (opc!=npc)
+ for(f=1;f<3;f++)
+ s[strlen(s)-f]='.';
+
+ return s;
+#else
+ (*pc)+=4;
+ return "NO DISASSEMBLER";
+#endif
+}
+
+/* END OF FILE */
diff --git a/arm9/source/z80_decode.c b/arm9/source/z80_decode.c
new file mode 100644
index 0000000..4a24bd4
--- /dev/null
+++ b/arm9/source/z80_decode.c
@@ -0,0 +1,2533 @@
+/*
+
+ z80 - Z80 Emulator
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+*/
+#include <stdlib.h>
+#include <limits.h>
+
+#include "z80.h"
+#include "z80_private.h"
+
+static const char ident[]="$Id$";
+
+/* ---------------------------------------- TABLES AND INIT
+*/
+static Z80Byte PSZtable[512];
+static Z80Byte SZtable[512];
+static Z80Byte Ptable[512];
+static Z80Byte Stable[512];
+static Z80Byte Ztable[512];
+
+
+int Z80_HI_WORD;
+int Z80_LO_WORD;
+
+#define HI Z80_HI_WORD
+#define LO Z80_LO_WORD
+
+/* ---------------------------------------- MISC FUNCTIONS
+*/
+void Z80_InitialiseInternals(void)
+{
+ Z80Word f;
+ Z80Reg r;
+
+ /* Check endianness
+ */
+ r.w=0x1234;
+
+ if (r.b[0] == 0x12)
+ {
+ HI=0;
+ LO=1;
+ }
+ else if (r.b[1] == 0x12)
+ {
+ HI=1;
+ LO=0;
+ }
+ else
+ {
+ exit(1);
+ }
+
+ /* Check variable sizes
+ */
+ if (CHAR_BIT!=8 || sizeof(Z80Word)!=2)
+ {
+ exit(2);
+ }
+
+ /* Initialise flag tables
+ */
+ for(f=0;f<256;f++)
+ {
+ Z80Byte p,z,s;
+ int b;
+
+ p=0;
+
+ for(b=0;b<8;b++)
+ if (f&(1<<b))
+ p++;
+
+ if (p&1)
+ p=0;
+ else
+ p=P_Z80;
+
+ if (f)
+ z=0;
+ else
+ z=Z_Z80;
+
+ if (f&0x80)
+ s=S_Z80;
+ else
+ s=0;
+
+ Ptable[f]=p;
+ Stable[f]=s;
+ Ztable[f]=z;
+ SZtable[f]=z|s;
+ PSZtable[f]=z|s|p;
+
+ Ptable[f+256]=Ptable[f]|C_Z80;
+ Stable[f+256]=Stable[f]|C_Z80;
+ Ztable[f+256]=Ztable[f]|C_Z80;
+ SZtable[f+256]=SZtable[f]|C_Z80;
+ PSZtable[f+256]=PSZtable[f]|C_Z80;
+ }
+}
+
+#ifndef ENABLE_ARRAY_MEMORY
+static Z80Word FPEEKW(Z80 *cpu, Z80Word addr)
+{
+ return (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8);
+}
+
+
+static void FPOKEW(Z80 *cpu, Z80Word addr, Z80Word val)
+{
+ PRIV->mwrite(cpu,addr,val);
+ PRIV->mwrite(cpu,addr+1,val>>8);
+}
+#endif
+
+
+/* ---------------------------------------- GENERAL MACROS
+*/
+#define SWAP(A,B) \
+do { \
+ unsigned swap_tmp; \
+ swap_tmp=A; \
+ A=B; \
+ B=swap_tmp; \
+} while(0)
+
+
+/* ---------------------------------------- ARITHMETIC OPS
+*/
+#define ADD8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ unsigned w; \
+ w=cpu->AF.b[HI]+(unsigned)VAL; \
+ cpu->AF.b[LO]=SZtable[w]; \
+ if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
+ if ((VAL^cpu->AF.b[HI]^0x80)&(VAL^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
+ SETHIDDEN(w); \
+ cpu->AF.b[HI]=w; \
+} while(0)
+
+
+#define ADC8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ unsigned w; \
+ w=(cpu->AF.b[HI]+(unsigned)VAL+CARRY)&0x1ff; \
+ cpu->AF.b[LO]=SZtable[w]; \
+ if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
+ if ((VAL^cpu->AF.b[HI]^0x80)&(VAL^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
+ SETHIDDEN(w); \
+ cpu->AF.b[HI]=w; \
+} while(0)
+
+
+#define SUB8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ unsigned w; \
+ w=(cpu->AF.b[HI]-(unsigned)VAL)&0x1ff; \
+ cpu->AF.b[LO]=SZtable[w]|N_Z80; \
+ if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
+ if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
+ SETHIDDEN(w); \
+ cpu->AF.b[HI]=w; \
+} while(0)
+
+
+#define CMP8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ unsigned w; \
+ w=(cpu->AF.b[HI]-(unsigned)VAL)&0x1ff; \
+ cpu->AF.b[LO]=SZtable[w]|N_Z80; \
+ if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
+ if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
+ SETHIDDEN(VAL); \
+} while(0)
+
+
+#define SBC8(ONCE) \
+do { \
+ Z80Byte VAL=ONCE; \
+ unsigned w; \
+ w=(cpu->AF.b[HI]-(unsigned)VAL-CARRY)&0x1ff; \
+ cpu->AF.b[LO]=SZtable[w]|N_Z80; \
+ if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \
+ if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \
+ SETHIDDEN(w); \
+ cpu->AF.b[HI]=w; \
+} while(0)
+
+
+#define ADD16(REG,ONCE) \
+do { \
+ Z80Word VAL=ONCE; \
+ Z80Val w; \
+ w=(REG)+(Z80Val)VAL; \
+ cpu->AF.b[LO]&=(S_Z80|Z_Z80|V_Z80); \
+ if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \
+ if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \
+ SETHIDDEN(w>>8); \
+ (REG)=w; \
+} while(0)
+
+
+#define ADC16(REG, ONCE) \
+do { \
+ Z80Word VAL=ONCE; \
+ Z80Val w; \
+ w=(REG)+(Z80Val)VAL+CARRY; \
+ cpu->AF.b[LO]=0; \
+ if ((w&0xffff)==0) cpu->AF.b[LO]=Z_Z80; \
+ if (w&0x8000) cpu->AF.b[LO]|=S_Z80; \
+ if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \
+ if ((VAL^(REG)^0x8000)&((REG)^w)&0x8000) cpu->AF.b[LO]|=P_Z80; \
+ if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \
+ SETHIDDEN(w>>8); \
+ (REG)=w; \
+} while(0)
+
+
+#define SBC16(REG, ONCE) \
+do { \
+ Z80Word VAL=ONCE; \
+ Z80Val w; \
+ w=(REG)-(Z80Val)VAL-CARRY; \
+ cpu->AF.b[LO]=N_Z80; \
+ if (w&0x8000) cpu->AF.b[LO]|=S_Z80; \
+ if ((w&0xffff)==0) cpu->AF.b[LO]|=Z_Z80; \
+ if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \
+ if ((VAL^(REG))&((REG)^w)&0x8000) cpu->AF.b[LO]|=P_Z80; \
+ if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \
+ SETHIDDEN(w>>8); \
+ (REG)=w; \
+} while(0)
+
+
+#define INC8(REG) \
+do { \
+ (REG)++; \
+ cpu->AF.b[LO]=CARRY|SZtable[(REG)]; \
+ if ((REG)==0x80) cpu->AF.b[LO]|=P_Z80; \
+ if (((REG)&0x0f)==0) cpu->AF.b[LO]|=H_Z80; \
+} while(0)
+
+
+#define DEC8(REG) \
+do { \
+ (REG)--; \
+ cpu->AF.b[LO]=N_Z80|CARRY; \
+ if ((REG)==0x7f) cpu->AF.b[LO]|=P_Z80; \
+ if (((REG)&0x0f)==0x0f) cpu->AF.b[LO]|=H_Z80; \
+ cpu->AF.b[LO]|=SZtable[(REG)]; \
+} while(0)
+
+
+#define OP_ON_MEM(OP,addr) \
+do { \
+ Z80Byte memop=PEEK(addr); \
+ OP(memop); \
+ POKE(addr,memop); \
+} while(0)
+
+
+#define OP_ON_MEM_WITH_ARG(OP,addr,arg) \
+do { \
+ Z80Byte memop=PEEK(addr); \
+ OP(memop,arg); \
+ POKE(addr,memop); \
+} while(0)
+
+
+#define OP_ON_MEM_WITH_COPY(OP,addr,copy) \
+do { \
+ Z80Byte memop=PEEK(addr); \
+ OP(memop); \
+ copy=memop; \
+ POKE(addr,memop); \
+} while(0)
+
+
+#define OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,arg,copy) \
+do { \
+ Z80Byte memop=PEEK(addr); \
+ OP(memop,arg); \
+ copy=memop; \
+ POKE(addr,memop); \
+} while(0)
+
+
+/* ---------------------------------------- ROTATE AND SHIFT OPS
+*/
+#define RRCA \
+do { \
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]&C_Z80); \
+ cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(cpu->AF.b[HI]<<7); \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define RRA \
+do { \
+ Z80Byte c; \
+ c=CARRY; \
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]&C_Z80); \
+ cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(c<<7); \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define RRC(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)&C_Z80; \
+ (REG)=((REG)>>1)|((REG)<<7); \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define RR(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)&C_Z80; \
+ (REG)=((REG)>>1)|(CARRY<<7); \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define RLCA \
+do { \
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]>>7); \
+ cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|(cpu->AF.b[HI]>>7); \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define RLA \
+do { \
+ Z80Byte c; \
+ c=CARRY; \
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]>>7); \
+ cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|c; \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define RLC(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)>>7; \
+ (REG)=((REG)<<1)|c; \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define RL(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)>>7; \
+ (REG)=((REG)<<1)|CARRY; \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define SRL(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)&C_Z80; \
+ (REG)>>=1; \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define SRA(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)&C_Z80; \
+ (REG)=((REG)>>1)|((REG)&0x80); \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define SLL(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)>>7; \
+ (REG)=((REG)<<1)|1; \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+#define SLA(REG) \
+do { \
+ Z80Byte c; \
+ c=(REG)>>7; \
+ (REG)=(REG)<<1; \
+ cpu->AF.b[LO]=PSZtable[(REG)]|c; \
+ SETHIDDEN(REG); \
+} while(0)
+
+
+/* ---------------------------------------- BOOLEAN OPS
+*/
+#define AND(VAL) \
+do { \
+ cpu->AF.b[HI]&=VAL; \
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]|H_Z80; \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define OR(VAL) \
+do { \
+ cpu->AF.b[HI]|=VAL; \
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]; \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define XOR(VAL) \
+do { \
+ cpu->AF.b[HI]^=VAL; \
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]; \
+ SETHIDDEN(cpu->AF.b[HI]); \
+} while(0)
+
+
+#define BIT(REG,B) \
+do { \
+ cpu->AF.b[LO]=CARRY|H_Z80; \
+ if ((REG)&(1<<B)) \
+ { \
+ if (B==7 && (REG&S_Z80)) cpu->AF.b[LO]|=S_Z80; \
+ if (B==5 && (REG&B5_Z80)) cpu->AF.b[LO]|=B5_Z80; \
+ if (B==3 && (REG&B3_Z80)) cpu->AF.b[LO]|=B3_Z80; \
+ } \
+ else \
+ { \
+ cpu->AF.b[LO]|=Z_Z80; \
+ cpu->AF.b[LO]|=P_Z80; \
+ } \
+} while(0)
+
+#define BIT_SET(REG,B) (REG)|=(1<<B)
+#define BIT_RES(REG,B) (REG)&=~(1<<B)
+
+
+/* ---------------------------------------- JUMP OPERATIONS
+*/
+#define JR_COND(COND) \
+do { \
+ if (COND) \
+ { \
+ TSTATE(12); \
+ JR; \
+ } \
+ else \
+ { \
+ TSTATE(7); \
+ NOJR; \
+ } \
+} while(0)
+
+
+#define JP_COND(COND) \
+do { \
+ TSTATE(10); \
+ if (COND) \
+ { \
+ JP; \
+ } \
+ else \
+ { \
+ NOJP; \
+ } \
+} while(0)
+
+
+#define CALL_COND(COND) \
+do { \
+ if (COND) \
+ { \
+ TSTATE(17); \
+ CALL; \
+ } \
+ else \
+ { \
+ TSTATE(10); \
+ NOCALL; \
+ } \
+} while(0)
+
+
+#define RET_COND(COND) \
+do { \
+ if (COND) \
+ { \
+ TSTATE(11); \
+ POP(cpu->PC); \
+ } \
+ else \
+ { \
+ TSTATE(5); \
+ } \
+} while(0)
+
+
+#define RST(ADDR) \
+ TSTATE(11); \
+ PUSH(cpu->PC); \
+ cpu->PC=ADDR
+
+/* ---------------------------------------- BLOCK OPERATIONS
+*/
+#define LDI \
+do { \
+ Z80Byte b; \
+ \
+ b=PEEK(cpu->HL.w); \
+ POKE(cpu->DE.w,b); \
+ cpu->DE.w++; \
+ cpu->HL.w++; \
+ cpu->BC.w--; \
+ \
+ CLRFLAG(H_Z80); \
+ CLRFLAG(N_Z80); \
+ \
+ if (cpu->BC.w) \
+ SETFLAG(P_Z80); \
+ else \
+ CLRFLAG(P_Z80); \
+ \
+ SETHIDDEN(cpu->AF.b[HI]+b); \
+} while(0)
+
+#define LDD \
+do { \
+ Z80Byte b; \
+ \
+ b=PEEK(cpu->HL.w); \
+ POKE(cpu->DE.w,b); \
+ cpu->DE.w--; \
+ cpu->HL.w--; \
+ cpu->BC.w--; \
+ \
+ CLRFLAG(H_Z80); \
+ CLRFLAG(N_Z80); \
+ \
+ if (cpu->BC.w) \
+ SETFLAG(P_Z80); \
+ else \
+ CLRFLAG(P_Z80); \
+ \
+ SETHIDDEN(cpu->AF.b[HI]+b); \
+} while(0)
+
+#define CPI \
+do { \
+ Z80Byte c,b; \
+ \
+ c=CARRY; \
+ b=PEEK(cpu->HL.w); \
+ \
+ CMP8(b); \
+ \
+ if (c) \
+ SETFLAG(C_Z80); \
+ else \
+ CLRFLAG(C_Z80); \
+ \
+ cpu->HL.w++; \
+ cpu->BC.w--; \
+ \
+ if (cpu->BC.w) \
+ SETFLAG(P_Z80); \
+ else \
+ CLRFLAG(P_Z80); \
+} while(0)
+
+#define CPD \
+do { \
+ Z80Byte c,b; \
+ \
+ c=CARRY; \
+ b=PEEK(cpu->HL.w); \
+ \
+ CMP8(b); \
+ \
+ if (c) \
+ SETFLAG(C_Z80); \
+ else \
+ CLRFLAG(C_Z80); \
+ \
+ cpu->HL.w--; \
+ cpu->BC.w--; \
+ \
+ if (cpu->BC.w) \
+ SETFLAG(P_Z80); \
+ else \
+ CLRFLAG(P_Z80); \
+} while(0)
+
+#define INI \
+do { \
+ Z80Word w; \
+ Z80Byte b; \
+ \
+ b=IN(cpu->BC.w); \
+ POKE(cpu->HL.w,b); \
+ \
+ cpu->BC.b[HI]--; \
+ cpu->HL.w++; \
+ \
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
+ SETHIDDEN(cpu->BC.b[HI]); \
+ \
+ w=(((Z80Word)cpu->BC.b[LO])&0xff)+b; \
+ \
+ if (b&0x80) \
+ SETFLAG(N_Z80); \
+ \
+ if (w&0x100) \
+ { \
+ SETFLAG(C_Z80); \
+ SETFLAG(H_Z80); \
+ } \
+ else \
+ { \
+ CLRFLAG(C_Z80); \
+ CLRFLAG(H_Z80); \
+ } \
+} while(0)
+
+#define IND \
+do { \
+ Z80Word w; \
+ Z80Byte b; \
+ \
+ b=IN(cpu->BC.w); \
+ POKE(cpu->HL.w,b); \
+ \
+ cpu->BC.b[HI]--; \
+ cpu->HL.w--; \
+ \
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
+ SETHIDDEN(cpu->BC.b[HI]); \
+ \
+ w=(((Z80Word)cpu->BC.b[LO])&0xff)+b; \
+ \
+ if (b&0x80) \
+ SETFLAG(N_Z80); \
+ \
+ if (w&0x100) \
+ { \
+ SETFLAG(C_Z80); \
+ SETFLAG(H_Z80); \
+ } \
+ else \
+ { \
+ CLRFLAG(C_Z80); \
+ CLRFLAG(H_Z80); \
+ } \
+} while(0) \
+
+#define OUTI \
+do { \
+ OUT(cpu->BC.w,PEEK(cpu->HL.w)); \
+ \
+ cpu->HL.w++; \
+ cpu->BC.b[HI]--; \
+ \
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
+ SETHIDDEN(cpu->BC.b[HI]); \
+} while(0)
+
+#define OUTD \
+do { \
+ OUT(cpu->BC.w,PEEK(cpu->HL.w)); \
+ \
+ cpu->HL.w--; \
+ cpu->BC.b[HI]--; \
+ \
+ cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \
+ SETFLAG(N_Z80); \
+ SETHIDDEN(cpu->BC.b[HI]); \
+} while(0)
+
+
+/* ---------------------------------------- BASE OPCODE SHORT-HAND BLOCKS
+*/
+
+#define LD_BLOCK(BASE,DEST,DEST2) \
+ case BASE: /* LD DEST,B */ \
+ TSTATE(4); \
+ DEST=cpu->BC.b[HI]; \
+ break; \
+ \
+ case BASE+1: /* LD DEST,C */ \
+ TSTATE(4); \
+ DEST=cpu->BC.b[LO]; \
+ break; \
+ \
+ case BASE+2: /* LD DEST,D */ \
+ TSTATE(4); \
+ DEST=cpu->DE.b[HI]; \
+ break; \
+ \
+ case BASE+3: /* LD DEST,E */ \
+ TSTATE(4); \
+ DEST=cpu->DE.b[LO]; \
+ break; \
+ \
+ case BASE+4: /* LD DEST,H */ \
+ TSTATE(4); \
+ DEST=*H; \
+ break; \
+ \
+ case BASE+5: /* LD DEST,L */ \
+ TSTATE(4); \
+ DEST=*L; \
+ break; \
+ \
+ case BASE+6: /* LD DEST,(HL) */ \
+ TSTATE(7); \
+ OFFSET(off); \
+ DEST2=PEEK(*HL+off); \
+ break; \
+ \
+ case BASE+7: /* LD DEST,A */ \
+ TSTATE(4); \
+ DEST=cpu->AF.b[HI]; \
+ break;
+
+#define ALU_BLOCK(BASE,OP) \
+ case BASE: /* OP A,B */ \
+ TSTATE(4); \
+ OP(cpu->BC.b[HI]); \
+ break; \
+ \
+ case BASE+1: /* OP A,C */ \
+ TSTATE(4); \
+ OP(cpu->BC.b[LO]); \
+ break; \
+ \
+ case BASE+2: /* OP A,D */ \
+ TSTATE(4); \
+ OP(cpu->DE.b[HI]); \
+ break; \
+ \
+ case BASE+3: /* OP A,E */ \
+ TSTATE(4); \
+ OP(cpu->DE.b[LO]); \
+ break; \
+ \
+ case BASE+4: /* OP A,H */ \
+ TSTATE(4); \
+ OP(*H); \
+ break; \
+ \
+ case BASE+5: /* OP A,L */ \
+ TSTATE(4); \
+ OP(*L); \
+ break; \
+ \
+ case BASE+6: /* OP A,(HL) */ \
+ TSTATE(7); \
+ OFFSET(off); \
+ OP_ON_MEM(OP,*HL+off); \
+ break; \
+ \
+ case BASE+7: /* OP A,A */ \
+ TSTATE(4); \
+ OP(cpu->AF.b[HI]); \
+ break;
+
+
+/* ---------------------------------------- CB OPCODE SHORT-HAND BLOCKS
+*/
+
+#define CB_ALU_BLOCK(BASE,OP) \
+ case BASE: /* OP B */ \
+ TSTATE(8); \
+ OP(cpu->BC.b[HI]); \
+ break; \
+ \
+ case BASE+1: /* OP C */ \
+ TSTATE(8); \
+ OP(cpu->BC.b[LO]); \
+ break; \
+ \
+ case BASE+2: /* OP D */ \
+ TSTATE(8); \
+ OP(cpu->DE.b[HI]); \
+ break; \
+ \
+ case BASE+3: /* OP E */ \
+ TSTATE(8); \
+ OP(cpu->DE.b[LO]); \
+ break; \
+ \
+ case BASE+4: /* OP H */ \
+ TSTATE(8); \
+ OP(cpu->HL.b[HI]); \
+ break; \
+ \
+ case BASE+5: /* OP L */ \
+ TSTATE(8); \
+ OP(cpu->HL.b[LO]); \
+ break; \
+ \
+ case BASE+6: /* OP (HL) */ \
+ TSTATE(15); \
+ OP_ON_MEM(OP,cpu->HL.w); \
+ break; \
+ \
+ case BASE+7: /* OP A */ \
+ TSTATE(8); \
+ OP(cpu->AF.b[HI]); \
+ break;
+
+#define CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \
+ case BASE: /* OP B */ \
+ TSTATE(8); \
+ OP(cpu->BC.b[HI],BIT_NO); \
+ break; \
+ \
+ case BASE+1: /* OP C */ \
+ TSTATE(8); \
+ OP(cpu->BC.b[LO],BIT_NO); \
+ break; \
+ \
+ case BASE+2: /* OP D */ \
+ TSTATE(8); \
+ OP(cpu->DE.b[HI],BIT_NO); \
+ break; \
+ \
+ case BASE+3: /* OP E */ \
+ TSTATE(8); \
+ OP(cpu->DE.b[LO],BIT_NO); \
+ break; \
+ \
+ case BASE+4: /* OP H */ \
+ TSTATE(8); \
+ OP(cpu->HL.b[HI],BIT_NO); \
+ break; \
+ \
+ case BASE+5: /* OP L */ \
+ TSTATE(8); \
+ OP(cpu->HL.b[LO],BIT_NO); \
+ break; \
+ \
+ case BASE+6: /* OP (HL) */ \
+ TSTATE(12); \
+ OP_ON_MEM_WITH_ARG(OP,cpu->HL.w,BIT_NO); \
+ break; \
+ \
+ case BASE+7: /* OP A */ \
+ TSTATE(8); \
+ OP(cpu->AF.b[HI],BIT_NO); \
+ break;
+
+/* ---------------------------------------- SHIFTED CB OPCODE SHORT-HAND BLOCKS
+*/
+
+#define SHIFTED_CB_ALU_BLOCK(BASE,OP) \
+ case BASE: /* OP B */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->BC.b[HI]); \
+ break; \
+ \
+ case BASE+1: /* OP C */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->BC.b[LO]); \
+ break; \
+ \
+ case BASE+2: /* OP D */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->DE.b[HI]); \
+ break; \
+ \
+ case BASE+3: /* OP E */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->DE.b[LO]); \
+ break; \
+ \
+ case BASE+4: /* OP H */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->HL.b[HI]); \
+ break; \
+ \
+ case BASE+5: /* OP L */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->HL.b[LO]); \
+ break; \
+ \
+ case BASE+6: /* OP (HL) */ \
+ TSTATE(15); \
+ OP_ON_MEM(OP,addr); \
+ break; \
+ \
+ case BASE+7: /* OP A */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_COPY(OP,addr,cpu->AF.b[HI]); \
+ break;
+
+#define SHIFTED_CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \
+ case BASE: /* OP B */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->BC.b[HI]); \
+ break; \
+ \
+ case BASE+1: /* OP C */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->BC.b[LO]); \
+ break; \
+ \
+ case BASE+2: /* OP D */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->DE.b[HI]); \
+ break; \
+ \
+ case BASE+3: /* OP E */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->DE.b[LO]); \
+ break; \
+ \
+ case BASE+4: /* OP H */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->HL.b[HI]); \
+ break; \
+ \
+ case BASE+5: /* OP L */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->HL.b[LO]); \
+ break; \
+ \
+ case BASE+6: /* OP (HL) */ \
+ TSTATE(12); \
+ OP_ON_MEM_WITH_ARG(OP,addr,BIT_NO); \
+ break; \
+ \
+ case BASE+7: /* OP A */ \
+ TSTATE(8); \
+ OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->AF.b[HI]); \
+ break;
+
+/* ---------------------------------------- DAA
+*/
+
+/* This alogrithm is based on info from
+ http://www.worldofspectrum.org/faq/reference/z80reference.htm
+*/
+static void DAA (Z80 *cpu)
+{
+ Z80Byte add=0;
+ Z80Byte carry=0;
+ Z80Byte nf=cpu->AF.b[LO]&N_Z80;
+ Z80Byte acc=cpu->AF.b[HI];
+
+ if (acc>0x99 || IS_C)
+ {
+ add|=0x60;
+ carry=C_Z80;
+ }
+
+ if ((acc&0xf)>0x9 || IS_H)
+ {
+ add|=0x06;
+ }
+
+ if (nf)
+ {
+ cpu->AF.b[HI]-=add;
+ }
+ else
+ {
+ cpu->AF.b[HI]+=add;
+ }
+
+ cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]
+ | carry
+ | nf
+ | ((acc^cpu->AF.b[HI])&H_Z80)
+ | (cpu->AF.b[HI]&(B3_Z80|B5_Z80));
+}
+
+/* ---------------------------------------- HANDLERS FOR ED OPCODES
+*/
+static void DecodeED(Z80 *cpu, Z80Byte opcode)
+{
+ switch(opcode)
+ {
+ case 0x40: /* IN B,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->BC.b[HI]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->BC.b[HI]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
+ break;
+
+ case 0x41: /* OUT (C),B */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->BC.b[HI]);
+ break;
+
+ case 0x42: /* SBC HL,BC */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->BC.w);
+ break;
+
+ case 0x43: /* LD (nnnn),BC */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->BC.w);
+ break;
+
+ case 0x44: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x45: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x46: /* IM 0 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
+
+ case 0x47: /* LD I,A */
+ TSTATE(9);
+ cpu->I=cpu->AF.b[HI];
+ break;
+
+ case 0x48: /* IN C,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->BC.b[LO]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->BC.b[LO]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[LO]];
+ SETHIDDEN(cpu->BC.b[LO]);
+ break;
+
+ case 0x49: /* OUT (C),C */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->BC.b[LO]);
+ break;
+
+ case 0x4a: /* ADC HL,BC */
+ TSTATE(15);
+ ADC16(cpu->HL.w,cpu->BC.w);
+ break;
+
+ case 0x4b: /* LD BC,(nnnn) */
+ TSTATE(20);
+ cpu->BC.w=PEEKW(FETCH_WORD);
+ break;
+
+ case 0x4c: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x4d: /* RETI */
+ TSTATE(14);
+ CALLBACK(eZ80_RETI,0);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x4e: /* IM 0/1 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
+
+ case 0x4f: /* LD R,A */
+ TSTATE(9);
+ cpu->R=cpu->AF.b[HI];
+ break;
+
+ case 0x50: /* IN D,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->DE.b[HI]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->DE.b[HI]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[HI]];
+ SETHIDDEN(cpu->BC.b[HI]);
+ break;
+
+ case 0x51: /* OUT (C),D */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->DE.b[HI]);
+ break;
+
+ case 0x52: /* SBC HL,DE */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->DE.w);
+ break;
+
+ case 0x53: /* LD (nnnn),DE */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->DE.w);
+ break;
+
+ case 0x54: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x55: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x56: /* IM 1 */
+ TSTATE(8);
+ cpu->IM=1;
+ break;
+
+ case 0x57: /* LD A,I */
+ TSTATE(9);
+ cpu->AF.b[HI]=cpu->I;
+ break;
+
+ case 0x58: /* IN E,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->DE.b[LO]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->BC.b[LO]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[LO]];
+ SETHIDDEN(cpu->DE.b[LO]);
+ break;
+
+ case 0x59: /* OUT (C),E */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->DE.b[LO]);
+ break;
+
+ case 0x5a: /* ADC HL,DE */
+ TSTATE(15);
+ ADC16(cpu->HL.w,cpu->DE.w);
+ break;
+
+ case 0x5b: /* LD DE,(nnnn) */
+ TSTATE(20);
+ cpu->DE.w=PEEKW(FETCH_WORD);
+ break;
+
+ case 0x5c: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x5d: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x5e: /* IM 2 */
+ TSTATE(8);
+ cpu->IM=2;
+ break;
+
+ case 0x5f: /* LD A,R */
+ TSTATE(9);
+ cpu->AF.b[HI]=cpu->R;
+ break;
+
+ case 0x60: /* IN H,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->HL.b[HI]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->HL.b[HI]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->HL.b[HI]];
+ SETHIDDEN(cpu->HL.b[HI]);
+ break;
+
+ case 0x61: /* OUT (C),H */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->HL.b[HI]);
+ break;
+
+ case 0x62: /* SBC HL,HL */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->HL.w);
+ break;
+
+ case 0x63: /* LD (nnnn),HL */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->HL.w);
+ break;
+
+ case 0x64: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x65: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x66: /* IM 0 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
+
+ case 0x67: /* RRD */
+ {
+ Z80Byte b;
+
+ TSTATE(18);
+
+ b=PEEK(cpu->HL.w);
+
+ POKE(cpu->HL.w,(b>>4)|(cpu->AF.b[HI]<<4));
+ cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b&0x0f);
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+ }
+
+ case 0x68: /* IN L,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->HL.b[LO]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->HL.b[LO]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->HL.b[LO]];
+ SETHIDDEN(cpu->HL.b[LO]);
+ break;
+
+ case 0x69: /* OUT (C),L */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->HL.b[LO]);
+ break;
+
+ case 0x6a: /* ADC HL,HL */
+ TSTATE(15);
+ ADC16(cpu->HL.w,cpu->HL.w);
+ break;
+
+ case 0x6b: /* LD HL,(nnnn) */
+ TSTATE(20);
+ cpu->HL.w=PEEKW(FETCH_WORD);
+ break;
+
+ case 0x6c: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x6d: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x6e: /* IM 0/1 */
+ TSTATE(8);
+ cpu->IM=0;
+ break;
+
+ case 0x6f: /* RLD */
+ {
+ Z80Byte b;
+
+ TSTATE(18);
+
+ b=PEEK(cpu->HL.w);
+
+ POKE(cpu->HL.w,(b<<4)|(cpu->AF.b[HI]&0x0f));
+ cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b>>4);
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+ }
+
+ case 0x70: /* IN (C) */
+ {
+ Z80Byte b;
+
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ b=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ b=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[b];
+ SETHIDDEN(b);
+ break;
+ }
+
+ case 0x71: /* OUT (C) */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,0);
+ break;
+
+ case 0x72: /* SBC HL,SP */
+ TSTATE(15);
+ SBC16(cpu->HL.w,cpu->SP);
+ break;
+
+ case 0x73: /* LD (nnnn),SP */
+ TSTATE(20);
+ POKEW(FETCH_WORD,cpu->SP);
+ break;
+
+ case 0x74: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x75: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x76: /* IM 1 */
+ TSTATE(8);
+ cpu->IM=1;
+ break;
+
+ case 0x77: /* NOP */
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+
+ case 0x78: /* IN A,(C) */
+ TSTATE(12);
+
+ if (PRIV->pread)
+ {
+ cpu->AF.b[HI]=PRIV->pread(cpu,cpu->BC.w);
+ }
+ else
+ {
+ cpu->AF.b[HI]=0;
+ }
+
+ cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]];
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+
+ case 0x79: /* OUT (C),A */
+ TSTATE(12);
+ if (PRIV->pwrite) PRIV->pwrite(cpu,cpu->BC.w,cpu->AF.b[HI]);
+ break;
+
+ case 0x7a: /* ADC HL,SP */
+ TSTATE(15);
+ ADC16(cpu->HL.w,cpu->SP);
+ break;
+
+ case 0x7b: /* LD SP,(nnnn) */
+ TSTATE(20);
+ cpu->SP=PEEKW(FETCH_WORD);
+ break;
+
+ case 0x7c: /* NEG */
+ {
+ Z80Byte b;
+
+ TSTATE(8);
+
+ b=cpu->AF.b[HI];
+ cpu->AF.b[HI]=0;
+ SUB8(b);
+ break;
+ }
+
+ case 0x7d: /* RETN */
+ TSTATE(14);
+ cpu->IFF1=cpu->IFF2;
+ POP(cpu->PC);
+ break;
+
+ case 0x7e: /* IM 2 */
+ TSTATE(8);
+ cpu->IM=2;
+ break;
+
+ case 0x7f: /* NOP */
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+
+ case 0xa0: /* LDI */
+ TSTATE(16);
+ LDI;
+ break;
+
+ case 0xa1: /* CPI */
+ TSTATE(16);
+ CPI;
+ break;
+
+ case 0xa2: /* INI */
+ TSTATE(16);
+ INI;
+ break;
+
+ case 0xa3: /* OUTI */
+ TSTATE(16);
+ OUTI;
+ break;
+
+ case 0xa8: /* LDD */
+ TSTATE(16);
+ LDD;
+ break;
+
+ case 0xa9: /* CPD */
+ TSTATE(16);
+ CPD;
+ break;
+
+ case 0xaa: /* IND */
+ TSTATE(16);
+ IND;
+ break;
+
+ case 0xab: /* OUTD */
+ TSTATE(16);
+ OUTD;
+ break;
+
+ case 0xb0: /* LDIR */
+ TSTATE(16);
+ LDI;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xb1: /* CPIR */
+ TSTATE(16);
+ CPI;
+ if (cpu->BC.w && !IS_Z)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xb2: /* INIR */
+ TSTATE(16);
+ INI;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xb3: /* OTIR */
+ TSTATE(16);
+ OUTI;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xb8: /* LDDR */
+ TSTATE(16);
+ LDD;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xb9: /* CPDR */
+ TSTATE(16);
+ CPD;
+ if (cpu->BC.w && !IS_Z)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xba: /* INDR */
+ TSTATE(16);
+ IND;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ case 0xbb: /* OTDR */
+ TSTATE(16);
+ OUTD;
+ if (cpu->BC.w)
+ {
+ TSTATE(5);
+ cpu->PC-=2;
+ }
+ break;
+
+ /* All the rest are NOP/invalid
+ */
+ default:
+ TSTATE(8);
+ CALLBACK(eZ80_EDHook,opcode);
+ break;
+ }
+}
+
+
+/* ---------------------------------------- HANDLERS FOR CB OPCODES
+*/
+static void DecodeCB(Z80 *cpu, Z80Byte opcode)
+{
+ switch(opcode)
+ {
+ CB_ALU_BLOCK(0x00,RLC)
+ CB_ALU_BLOCK(0x08,RRC)
+ CB_ALU_BLOCK(0x10,RL)
+ CB_ALU_BLOCK(0x18,RR)
+ CB_ALU_BLOCK(0x20,SLA)
+ CB_ALU_BLOCK(0x28,SRA)
+ CB_ALU_BLOCK(0x30,SLL)
+ CB_ALU_BLOCK(0x38,SRL)
+
+ CB_BITMANIP_BLOCK(0x40,BIT,0)
+ CB_BITMANIP_BLOCK(0x48,BIT,1)
+ CB_BITMANIP_BLOCK(0x50,BIT,2)
+ CB_BITMANIP_BLOCK(0x58,BIT,3)
+ CB_BITMANIP_BLOCK(0x60,BIT,4)
+ CB_BITMANIP_BLOCK(0x68,BIT,5)
+ CB_BITMANIP_BLOCK(0x70,BIT,6)
+ CB_BITMANIP_BLOCK(0x78,BIT,7)
+
+ CB_BITMANIP_BLOCK(0x80,BIT_RES,0)
+ CB_BITMANIP_BLOCK(0x88,BIT_RES,1)
+ CB_BITMANIP_BLOCK(0x90,BIT_RES,2)
+ CB_BITMANIP_BLOCK(0x98,BIT_RES,3)
+ CB_BITMANIP_BLOCK(0xa0,BIT_RES,4)
+ CB_BITMANIP_BLOCK(0xa8,BIT_RES,5)
+ CB_BITMANIP_BLOCK(0xb0,BIT_RES,6)
+ CB_BITMANIP_BLOCK(0xb8,BIT_RES,7)
+
+ CB_BITMANIP_BLOCK(0xc0,BIT_SET,0)
+ CB_BITMANIP_BLOCK(0xc8,BIT_SET,1)
+ CB_BITMANIP_BLOCK(0xd0,BIT_SET,2)
+ CB_BITMANIP_BLOCK(0xd8,BIT_SET,3)
+ CB_BITMANIP_BLOCK(0xe0,BIT_SET,4)
+ CB_BITMANIP_BLOCK(0xe8,BIT_SET,5)
+ CB_BITMANIP_BLOCK(0xf0,BIT_SET,6)
+ CB_BITMANIP_BLOCK(0xf8,BIT_SET,7)
+ }
+}
+
+
+static void ShiftedDecodeCB(Z80 *cpu, Z80Byte opcode, Z80Relative offset)
+{
+ Z80Word addr;
+
+ /* See if we've come here from a IX/IY shift.
+ */
+ switch (PRIV->shift)
+ {
+ case 0xdd:
+ addr=cpu->IX.w+offset;
+ break;
+ case 0xfd:
+ addr=cpu->IY.w+offset;
+ break;
+ default:
+ addr=cpu->HL.w; /* Play safe... */
+ break;
+ }
+
+ switch(opcode)
+ {
+ SHIFTED_CB_ALU_BLOCK(0x00,RLC)
+ SHIFTED_CB_ALU_BLOCK(0x08,RRC)
+ SHIFTED_CB_ALU_BLOCK(0x10,RL)
+ SHIFTED_CB_ALU_BLOCK(0x18,RR)
+ SHIFTED_CB_ALU_BLOCK(0x20,SLA)
+ SHIFTED_CB_ALU_BLOCK(0x28,SRA)
+ SHIFTED_CB_ALU_BLOCK(0x30,SLL)
+ SHIFTED_CB_ALU_BLOCK(0x38,SRL)
+
+ SHIFTED_CB_BITMANIP_BLOCK(0x40,BIT,0)
+ SHIFTED_CB_BITMANIP_BLOCK(0x48,BIT,1)
+ SHIFTED_CB_BITMANIP_BLOCK(0x50,BIT,2)
+ SHIFTED_CB_BITMANIP_BLOCK(0x58,BIT,3)
+ SHIFTED_CB_BITMANIP_BLOCK(0x60,BIT,4)
+ SHIFTED_CB_BITMANIP_BLOCK(0x68,BIT,5)
+ SHIFTED_CB_BITMANIP_BLOCK(0x70,BIT,6)
+ SHIFTED_CB_BITMANIP_BLOCK(0x78,BIT,7)
+
+ SHIFTED_CB_BITMANIP_BLOCK(0x80,BIT_RES,0)
+ SHIFTED_CB_BITMANIP_BLOCK(0x88,BIT_RES,1)
+ SHIFTED_CB_BITMANIP_BLOCK(0x90,BIT_RES,2)
+ SHIFTED_CB_BITMANIP_BLOCK(0x98,BIT_RES,3)
+ SHIFTED_CB_BITMANIP_BLOCK(0xa0,BIT_RES,4)
+ SHIFTED_CB_BITMANIP_BLOCK(0xa8,BIT_RES,5)
+ SHIFTED_CB_BITMANIP_BLOCK(0xb0,BIT_RES,6)
+ SHIFTED_CB_BITMANIP_BLOCK(0xb8,BIT_RES,7)
+
+ SHIFTED_CB_BITMANIP_BLOCK(0xc0,BIT_SET,0)
+ SHIFTED_CB_BITMANIP_BLOCK(0xc8,BIT_SET,1)
+ SHIFTED_CB_BITMANIP_BLOCK(0xd0,BIT_SET,2)
+ SHIFTED_CB_BITMANIP_BLOCK(0xd8,BIT_SET,3)
+ SHIFTED_CB_BITMANIP_BLOCK(0xe0,BIT_SET,4)
+ SHIFTED_CB_BITMANIP_BLOCK(0xe8,BIT_SET,5)
+ SHIFTED_CB_BITMANIP_BLOCK(0xf0,BIT_SET,6)
+ SHIFTED_CB_BITMANIP_BLOCK(0xf8,BIT_SET,7)
+ }
+}
+
+
+/* ---------------------------------------- NORMAL OPCODE DECODER
+*/
+void Z80_Decode(Z80 *cpu, Z80Byte opcode)
+{
+ Z80Word *HL;
+ Z80Byte *H;
+ Z80Byte *L;
+ Z80Relative off;
+
+ /* See if we've come here from a IX/IY shift
+ */
+ switch (PRIV->shift)
+ {
+ case 0xdd:
+ HL=&(cpu->IX.w);
+ L=cpu->IX.b+LO;
+ H=cpu->IX.b+HI;
+ break;
+ case 0xfd:
+ HL=&(cpu->IY.w);
+ L=cpu->IY.b+LO;
+ H=cpu->IY.b+HI;
+ break;
+ default:
+ HL=&(cpu->HL.w);
+ L=cpu->HL.b+LO;
+ H=cpu->HL.b+HI;
+ break;
+ }
+
+ switch(opcode)
+ {
+ case 0x00: /* NOP */
+ TSTATE(4);
+ break;
+
+ case 0x01: /* LD BC,nnnn */
+ TSTATE(10);
+ cpu->BC.w=FETCH_WORD;
+ break;
+
+ case 0x02: /* LD (BC),A */
+ TSTATE(7);
+ POKE(cpu->BC.w,cpu->AF.b[HI]);
+ break;
+
+ case 0x03: /* INC BC */
+ TSTATE(6);
+ cpu->BC.w++;
+ break;
+
+ case 0x04: /* INC B */
+ TSTATE(4);
+ INC8(cpu->BC.b[HI]);
+ break;
+
+ case 0x05: /* DEC B */
+ TSTATE(4);
+ DEC8(cpu->BC.b[HI]);
+ break;
+
+ case 0x06: /* LD B,n */
+ TSTATE(7);
+ cpu->BC.b[HI]=FETCH_BYTE;
+ break;
+
+ case 0x07: /* RLCA */
+ TSTATE(4);
+ RLCA;
+ break;
+
+ case 0x08: /* EX AF,AF' */
+ TSTATE(4);
+ SWAP(cpu->AF.w,cpu->AF_);
+ break;
+
+ case 0x09: /* ADD HL,BC */
+ TSTATE(11);
+ ADD16(*HL,cpu->BC.w);
+ break;
+
+ case 0x0a: /* LD A,(BC) */
+ TSTATE(7);
+ cpu->AF.b[HI]=PEEK(cpu->BC.w);
+ break;
+
+ case 0x0b: /* DEC BC */
+ TSTATE(6);
+ cpu->BC.w--;
+ break;
+
+ case 0x0c: /* INC C */
+ TSTATE(4);
+ INC8(cpu->BC.b[LO]);
+ break;
+
+ case 0x0d: /* DEC C */
+ TSTATE(4);
+ DEC8(cpu->BC.b[LO]);
+ break;
+
+ case 0x0e: /* LD C,n */
+ TSTATE(7);
+ cpu->BC.b[LO]=FETCH_BYTE;
+ break;
+
+ case 0x0f: /* RRCA */
+ TSTATE(4);
+ RRCA;
+ break;
+
+ case 0x10: /* DJNZ */
+ if (--(cpu->BC.b[HI]))
+ {
+ TSTATE(13);
+ JR;
+ }
+ else
+ {
+ TSTATE(8);
+ NOJR;
+ }
+ break;
+
+ case 0x11: /* LD DE,nnnn */
+ TSTATE(10);
+ cpu->DE.w=FETCH_WORD;
+ break;
+
+ case 0x12: /* LD (DE),A */
+ TSTATE(7);
+ POKE(cpu->DE.w,cpu->AF.b[HI]);
+ break;
+
+ case 0x13: /* INC DE */
+ TSTATE(6);
+ cpu->DE.w++;
+ break;
+
+ case 0x14: /* INC D */
+ TSTATE(4);
+ INC8(cpu->DE.b[HI]);
+ break;
+
+ case 0x15: /* DEC D */
+ TSTATE(4);
+ DEC8(cpu->DE.b[HI]);
+ break;
+
+ case 0x16: /* LD D,n */
+ TSTATE(7);
+ cpu->DE.b[HI]=FETCH_BYTE;
+ break;
+
+ case 0x17: /* RLA */
+ TSTATE(4);
+ RLA;
+ break;
+
+ case 0x18: /* JR d */
+ TSTATE(12);
+ JR;
+ break;
+
+ case 0x19: /* ADD HL,DE */
+ TSTATE(11);
+ ADD16(*HL,cpu->DE.w);
+ break;
+
+ case 0x1a: /* LD A,(DE) */
+ TSTATE(7);
+ cpu->AF.b[HI]=PEEK(cpu->DE.w);
+ break;
+
+ case 0x1b: /* DEC DE */
+ TSTATE(6);
+ cpu->DE.w--;
+ break;
+
+ case 0x1c: /* INC E */
+ TSTATE(4);
+ INC8(cpu->DE.b[LO]);
+ break;
+
+ case 0x1d: /* DEC E */
+ TSTATE(4);
+ DEC8(cpu->DE.b[LO]);
+ break;
+
+ case 0x1e: /* LD E,n */
+ TSTATE(7);
+ cpu->DE.b[LO]=FETCH_BYTE;
+ break;
+
+ case 0x1f: /* RRA */
+ TSTATE(4);
+ RRA;
+ break;
+
+ case 0x20: /* JR NZ,e */
+ JR_COND(!IS_Z);
+ break;
+
+ case 0x21: /* LD HL,nnnn */
+ TSTATE(10);
+ *HL=FETCH_WORD;
+ break;
+
+ case 0x22: /* LD (nnnn),HL */
+ TSTATE(16);
+ POKEW(FETCH_WORD,*HL);
+ break;
+
+ case 0x23: /* INC HL */
+ TSTATE(6);
+ (*HL)++;
+ break;
+
+ case 0x24: /* INC H */
+ TSTATE(4);
+ INC8(*H);
+ break;
+
+ case 0x25: /* DEC H */
+ TSTATE(4);
+ DEC8(*H);
+ break;
+
+ case 0x26: /* LD H,n */
+ TSTATE(7);
+ *H=FETCH_BYTE;
+ break;
+
+ case 0x27: /* DAA */
+ TSTATE(4);
+ DAA(cpu);
+ break;
+
+ case 0x28: /* JR Z,d */
+ JR_COND(IS_Z);
+ break;
+
+ case 0x29: /* ADD HL,HL */
+ TSTATE(11);
+ ADD16(*HL,*HL);
+ break;
+
+ case 0x2a: /* LD HL,(nnnn) */
+ TSTATE(7);
+ *HL=PEEKW(FETCH_WORD);
+ break;
+
+ case 0x2b: /* DEC HL */
+ TSTATE(6);
+ (*HL)--;
+ break;
+
+ case 0x2c: /* INC L */
+ TSTATE(4);
+ INC8(*L);
+ break;
+
+ case 0x2d: /* DEC L */
+ TSTATE(4);
+ DEC8(*L);
+ break;
+
+ case 0x2e: /* LD L,n */
+ TSTATE(7);
+ *L=FETCH_BYTE;
+ break;
+
+ case 0x2f: /* CPL */
+ TSTATE(4);
+ cpu->AF.b[HI]^=0xff;
+ SETFLAG(H_Z80);
+ SETFLAG(N_Z80);
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+
+ case 0x30: /* JR NC,d */
+ JR_COND(!IS_C);
+ break;
+
+ case 0x31: /* LD SP,nnnn */
+ TSTATE(10);
+ cpu->SP=FETCH_WORD;
+ break;
+
+ case 0x32: /* LD (nnnn),A */
+ TSTATE(13);
+ POKE(FETCH_WORD,cpu->AF.b[HI]);
+ break;
+
+ case 0x33: /* INC SP */
+ TSTATE(6);
+ cpu->SP++;
+ break;
+
+ case 0x34: /* INC (HL) */
+ TSTATE(11);
+ OFFSET(off);
+ OP_ON_MEM(INC8,*HL+off);
+ break;
+
+ case 0x35: /* DEC (HL) */
+ TSTATE(11);
+ OFFSET(off);
+ OP_ON_MEM(DEC8,*HL+off);
+ break;
+
+ case 0x36: /* LD (HL),n */
+ TSTATE(10);
+ OFFSET(off);
+ POKE(*HL+off,FETCH_BYTE);
+ break;
+
+ case 0x37: /* SCF */
+ TSTATE(4);
+ cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))
+ | C_Z80
+ | (cpu->AF.b[HI]&(B3_Z80|B5_Z80));
+ break;
+
+ case 0x38: /* JR C,d */
+ JR_COND(IS_C);
+ break;
+
+ case 0x39: /* ADD HL,SP */
+ TSTATE(11);
+ ADD16(*HL,cpu->SP);
+ break;
+
+ case 0x3a: /* LD A,(nnnn) */
+ TSTATE(13);
+ cpu->AF.b[HI]=PEEK(FETCH_WORD);
+ break;
+
+ case 0x3b: /* DEC SP */
+ TSTATE(6);
+ cpu->SP--;
+ break;
+
+ case 0x3c: /* INC A */
+ TSTATE(4);
+ INC8(cpu->AF.b[HI]);
+ break;
+
+ case 0x3d: /* DEC A */
+ TSTATE(4);
+ DEC8(cpu->AF.b[HI]);
+ break;
+
+ case 0x3e: /* LD A,n */
+ TSTATE(7);
+ cpu->AF.b[HI]=FETCH_BYTE;
+ break;
+
+ case 0x3f: /* CCF */
+ TSTATE(4);
+
+ if (CARRY)
+ SETFLAG(H_Z80);
+ else
+ CLRFLAG(H_Z80);
+
+ cpu->AF.b[LO]^=C_Z80;
+ SETHIDDEN(cpu->AF.b[HI]);
+ break;
+
+ LD_BLOCK(0x40,cpu->BC.b[HI],cpu->BC.b[HI])
+ LD_BLOCK(0x48,cpu->BC.b[LO],cpu->BC.b[LO])
+ LD_BLOCK(0x50,cpu->DE.b[HI],cpu->DE.b[HI])
+ LD_BLOCK(0x58,cpu->DE.b[LO],cpu->DE.b[LO])
+ LD_BLOCK(0x60,*H,cpu->HL.b[HI])
+ LD_BLOCK(0x68,*L,cpu->HL.b[LO])
+
+ case 0x70: /* LD (HL),B */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->BC.b[HI]);
+ break;
+
+ case 0x71: /* LD (HL),C */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->BC.b[LO]);
+ break;
+
+ case 0x72: /* LD (HL),D */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->DE.b[HI]);
+ break;
+
+ case 0x73: /* LD (HL),E */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->DE.b[LO]);
+ break;
+
+ case 0x74: /* LD (HL),H */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->HL.b[HI]);
+ break;
+
+ case 0x75: /* LD (HL),L */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->HL.b[LO]);
+ break;
+
+ case 0x76: /* HALT */
+ TSTATE(4);
+ cpu->PC--;
+
+ if (!PRIV->halt)
+ CALLBACK(eZ80_Halt,1);
+
+ PRIV->halt=TRUE;
+ break;
+
+ case 0x77: /* LD (HL),A */
+ TSTATE(7);
+ OFFSET(off);
+ POKE(*HL+off,cpu->AF.b[HI]);
+ break;
+
+ LD_BLOCK(0x78,cpu->AF.b[HI],cpu->AF.b[HI])
+
+ ALU_BLOCK(0x80,ADD8)
+ ALU_BLOCK(0x88,ADC8)
+ ALU_BLOCK(0x90,SUB8)
+ ALU_BLOCK(0x98,SBC8)
+ ALU_BLOCK(0xa0,AND)
+ ALU_BLOCK(0xa8,XOR)
+ ALU_BLOCK(0xb0,OR)
+ ALU_BLOCK(0xb8,CMP8)
+
+ case 0xc0: /* RET NZ */
+ RET_COND(!IS_Z);
+ break;
+
+ case 0xc1: /* POP BC */
+ TSTATE(10);
+ POP(cpu->BC.w);
+ break;
+
+ case 0xc2: /* JP NZ,nnnn */
+ JP_COND(!IS_Z);
+ break;
+
+ case 0xc3: /* JP nnnn */
+ JP_COND(1);
+ break;
+
+ case 0xc4: /* CALL NZ,nnnn */
+ CALL_COND(!IS_Z);
+ break;
+
+ case 0xc5: /* PUSH BC */
+ TSTATE(10);
+ PUSH(cpu->BC.w);
+ break;
+
+ case 0xc6: /* ADD A,n */
+ TSTATE(7);
+ ADD8(FETCH_BYTE);
+ break;
+
+ case 0xc7: /* RST 0 */
+ RST(0);
+ break;
+
+ case 0xc8: /* RET Z */
+ RET_COND(IS_Z);
+ break;
+
+ case 0xc9: /* RET */
+ TSTATE(10);
+ POP(cpu->PC);
+ break;
+
+ case 0xca: /* JP Z,nnnn */
+ JP_COND(IS_Z);
+ break;
+
+ case 0xcb: /* CB PREFIX */
+ INC_R;
+
+ /* Check for previous IX/IY shift.
+ */
+ if (PRIV->shift!=0)
+ {
+ Z80Relative cb_offset;
+
+ TSTATE(4); /* Wild stab in the dark! */
+ cb_offset=FETCH_BYTE;
+ ShiftedDecodeCB(cpu,FETCH_BYTE,cb_offset);
+ }
+ else
+ {
+ DecodeCB(cpu,FETCH_BYTE);
+ }
+ break;
+
+ case 0xcc: /* CALL Z,nnnn */
+ CALL_COND(IS_Z);
+ break;
+
+ case 0xcd: /* CALL nnnn */
+ CALL_COND(1);
+ break;
+
+ case 0xce: /* ADC A,n */
+ ADC8(FETCH_BYTE);
+ break;
+
+ case 0xcf: /* RST 8 */
+ RST(8);
+ break;
+
+ case 0xd0: /* RET NC */
+ RET_COND(!IS_C);
+ break;
+
+ case 0xd1: /* POP DE */
+ TSTATE(10);
+ POP(cpu->DE.w);
+ break;
+
+ case 0xd2: /* JP NC,nnnn */
+ JP_COND(!IS_C);
+ break;
+
+ case 0xd3: /* OUT (n),A */
+ TSTATE(11);
+ if (PRIV->pwrite)
+ {
+ Z80Word port;
+
+ port=FETCH_BYTE;
+ port|=(Z80Word)cpu->AF.b[HI]<<8;
+ PRIV->pwrite(cpu,port,cpu->AF.b[HI]);
+ }
+ else
+ cpu->PC++;
+ break;
+
+ case 0xd4: /* CALL NC,nnnn */
+ CALL_COND(!IS_C);
+ break;
+
+ case 0xd5: /* PUSH DE */
+ TSTATE(11);
+ PUSH(cpu->DE.w);
+ break;
+
+ case 0xd6: /* SUB A,n */
+ TSTATE(7);
+ SUB8(FETCH_BYTE);
+ break;
+
+ case 0xd7: /* RST 10 */
+ RST(0x10);
+ break;
+
+ case 0xd8: /* RET C */
+ RET_COND(IS_C);
+ break;
+
+ case 0xd9: /* EXX */
+ TSTATE(4);
+ SWAP(cpu->BC.w,cpu->BC_);
+ SWAP(cpu->DE.w,cpu->DE_);
+ SWAP(cpu->HL.w,cpu->HL_);
+ break;
+
+ case 0xda: /* JP C,nnnn */
+ JP_COND(IS_C);
+ break;
+
+ case 0xdb: /* IN A,(n) */
+ TSTATE(11);
+ if (PRIV->pread)
+ {
+ Z80Word port;
+
+ port=FETCH_BYTE;
+ port|=(Z80Word)cpu->AF.b[HI]<<8;
+ cpu->AF.b[HI]=PRIV->pread(cpu,port);
+ }
+ else
+ cpu->PC++;
+ break;
+
+ case 0xdc: /* CALL C,nnnn */
+ CALL_COND(IS_C);
+ break;
+
+ case 0xdd: /* DD PREFIX */
+ TSTATE(4);
+ INC_R;
+
+ PRIV->shift=opcode;
+ Z80_Decode(cpu,FETCH_BYTE);
+ break;
+
+ case 0xde: /* SBC A,n */
+ TSTATE(7);
+ SBC8(FETCH_BYTE);
+ break;
+
+ case 0xdf: /* RST 18 */
+ RST(0x18);
+ break;
+
+ case 0xe0: /* RET PO */
+ RET_COND(!IS_P);
+ break;
+
+ case 0xe1: /* POP HL */
+ TSTATE(10);
+ POP(*HL);
+ break;
+
+ case 0xe2: /* JP PO,nnnn */
+ JP_COND(!IS_P);
+ break;
+
+ case 0xe3: /* EX (SP),HL */
+ {
+ Z80Word tmp;
+ TSTATE(19);
+ POP(tmp);
+ PUSH(*HL);
+ *HL=tmp;
+ }
+ break;
+
+ case 0xe4: /* CALL PO,nnnn */
+ CALL_COND(!IS_P);
+ break;
+
+ case 0xe5: /* PUSH HL */
+ TSTATE(10);
+ PUSH(*HL);
+ break;
+
+ case 0xe6: /* AND A,n */
+ TSTATE(7);
+ AND(FETCH_BYTE);
+ break;
+
+ case 0xe7: /* RST 20 */
+ RST(0x20);
+ break;
+
+ case 0xe8: /* RET PE */
+ RET_COND(IS_P);
+ break;
+
+ case 0xe9: /* JP (HL) */
+ TSTATE(4);
+ cpu->PC=*HL;
+ break;
+
+ case 0xea: /* JP PE,nnnn */
+ JP_COND(IS_P);
+ break;
+
+ case 0xeb: /* EX DE,HL */
+ TSTATE(4);
+ SWAP(cpu->DE.w,*HL);
+ break;
+
+ case 0xec: /* CALL PE,nnnn */
+ CALL_COND(IS_P);
+ break;
+
+ case 0xed: /* ED PREFIX */
+ INC_R;
+ DecodeED(cpu,FETCH_BYTE);
+ break;
+
+ case 0xee: /* XOR A,n */
+ TSTATE(7);
+ XOR(FETCH_BYTE);
+ break;
+
+ case 0xef: /* RST 28 */
+ RST(0x28);
+ break;
+
+ case 0xf0: /* RET P */
+ RET_COND(!IS_S);
+ break;
+
+ case 0xf1: /* POP AF */
+ TSTATE(10);
+ POP(cpu->AF.w);
+ break;
+
+ case 0xf2: /* JP P,nnnn */
+ JP_COND(!IS_S);
+ break;
+
+ case 0xf3: /* DI */
+ TSTATE(4);
+ cpu->IFF1=0;
+ cpu->IFF2=0;
+ break;
+
+ case 0xf4: /* CALL P,nnnn */
+ CALL_COND(!IS_S);
+ break;
+
+ case 0xf5: /* PUSH AF */
+ TSTATE(10);
+ PUSH(cpu->AF.w);
+ break;
+
+ case 0xf6: /* OR A,n */
+ TSTATE(7);
+ OR(FETCH_BYTE);
+ break;
+
+ case 0xf7: /* RST 30 */
+ RST(0x30);
+ break;
+
+ case 0xf8: /* RET M */
+ RET_COND(IS_S);
+ break;
+
+ case 0xf9: /* LD SP,HL */
+ TSTATE(6);
+ cpu->SP=*HL;
+ break;
+
+ case 0xfa: /* JP M,nnnn */
+ JP_COND(IS_S);
+ break;
+
+ case 0xfb: /* EI */
+ TSTATE(4);
+ cpu->IFF1=1;
+ cpu->IFF2=1;
+ break;
+
+ case 0xfc: /* CALL M,nnnn */
+ CALL_COND(IS_S);
+ break;
+
+ case 0xfd: /* FD PREFIX */
+ TSTATE(4);
+ INC_R;
+
+ PRIV->shift=opcode;
+ Z80_Decode(cpu,FETCH_BYTE);
+ break;
+
+ case 0xfe: /* CP A,n */
+ TSTATE(7);
+ CMP8(FETCH_BYTE);
+ break;
+
+ case 0xff: /* RST 38 */
+ RST(0x38);
+ break;
+
+ }
+}
+
+
+/* END OF FILE */
diff --git a/arm9/source/z80_dis.c b/arm9/source/z80_dis.c
new file mode 100644
index 0000000..730edd0
--- /dev/null
+++ b/arm9/source/z80_dis.c
@@ -0,0 +1,2494 @@
+/*
+
+ z80 - Z80 Emulator
+
+ Copyright (C) 2007 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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 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
+
+ -------------------------------------------------------------------------
+
+ $Id$
+
+*/
+static const char ident[]="$Id$";
+
+#include "z80_config.h"
+
+#ifdef ENABLE_DISASSEM
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "z80.h"
+#include "z80_private.h"
+
+static Z80Relative cb_off;
+
+/* ---------------------------------------- SHARED ROUTINES
+*/
+static const char *z80_dis_reg8[]={"b","c","d","e","h","l","(hl)","a"};
+static const char *z80_dis_reg16[]={"bc","de","hl","sp"};
+static const char *z80_dis_condition[]={"nz","z","nc","c","po","pe","p","m"};
+
+static const char *dis_op;
+static const char *dis_arg;
+
+const char *Z80_Dis_Printf(const char *format, ...)
+{
+ static int p=0;
+ static char s[16][80];
+ va_list arg;
+
+ va_start(arg,format);
+ p=(p+1)%16;
+ vsprintf(s[p],format,arg);
+ va_end(arg);
+
+ return s[p];
+}
+
+
+Z80Byte Z80_Dis_FetchByte(Z80 *cpu, Z80Word *pc)
+{
+#ifdef ENABLE_ARRAY_MEMORY
+ return Z80_MEMORY[(*pc)++];
+#else
+ return cpu->priv->disread(cpu,(*pc)++);
+#endif
+}
+
+
+Z80Word Z80_Dis_FetchWord(Z80 *cpu, Z80Word *pc)
+{
+ Z80Byte l,h;
+
+ l=Z80_Dis_FetchByte(cpu,pc);
+ h=Z80_Dis_FetchByte(cpu,pc);
+
+ return ((Z80Word)h<<8)|l;
+}
+
+
+void Z80_Dis_Set(const char *op, const char *arg)
+{
+ dis_op=op;
+ dis_arg=arg;
+}
+
+
+const char *Z80_Dis_GetOp(void)
+{
+ return dis_op ? dis_op : "";
+}
+
+
+const char *Z80_Dis_GetArg(void)
+{
+ return dis_arg ? dis_arg : "";
+}
+
+
+static const char *GetLabel(Z80Word w)
+{
+ if (z80_labels)
+ {
+ int f;
+
+ for(f=0;z80_labels[f].label;f++)
+ {
+ if (z80_labels[f].address==w)
+ {
+ return z80_labels[f].label;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+
+/* ---------------------------------------- CB xx BYTE OPCODES
+*/
+static void DIS_RLC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("rlc",reg);
+}
+
+static void DIS_RRC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("rrc",reg);
+}
+
+static void DIS_RL_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("rl",reg);
+}
+
+static void DIS_RR_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("rr",reg);
+}
+
+static void DIS_SLA_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("sla",reg);
+}
+
+static void DIS_SRA_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("sra",reg);
+}
+
+static void DIS_SLL_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("sll",reg);
+}
+
+static void DIS_SRL_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("srl",reg);
+}
+
+static void DIS_BIT_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+ int bit;
+
+ reg=z80_dis_reg8[op%8];
+ bit=(op-0x40)/8;
+ Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s",bit,reg));
+}
+
+static void DIS_RES_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+ int bit;
+
+ reg=z80_dis_reg8[op%8];
+ bit=(op-0x80)/8;
+ Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s",bit,reg));
+}
+
+static void DIS_SET_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+ int bit;
+
+ reg=z80_dis_reg8[op%8];
+ bit=(op-0xc0)/8;
+ Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s",bit,reg));
+}
+
+/* ---------------------------------------- DD OPCODES
+*/
+
+static const char *IX_RelStr(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ static char s[80];
+ Z80Relative r;
+
+ r=(Z80Relative)Z80_Dis_FetchByte(z80,pc);
+
+ if (r<0)
+ sprintf(s,"(ix-$%.2x)",-r);
+ else
+ sprintf(s,"(ix+$%.2x)",r);
+
+ return(s);
+}
+
+
+static const char *IX_RelStrCB(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ static char s[80];
+ Z80Relative r;
+
+ r=(Z80Relative)cb_off;
+
+ if (r<0)
+ sprintf(s,"(ix-$%.2x)",-r);
+ else
+ sprintf(s,"(ix+$%.2x)",r);
+
+ return(s);
+}
+
+
+static const char *XR8(Z80 *z80, int reg, Z80Word *pc)
+{
+ switch(reg)
+ {
+ case 0:
+ return("b");
+ break;
+ case 1:
+ return("c");
+ break;
+ case 2:
+ return("d");
+ break;
+ case 3:
+ return("e");
+ break;
+ case 4:
+ return("ixh");
+ break;
+ case 5:
+ return("ixl");
+ break;
+ case 6:
+ return(IX_RelStr(z80,0,pc));
+ break;
+ case 7:
+ return("a");
+ break;
+ default:
+ return(Z80_Dis_Printf("BUG %d",reg));
+ break;
+ }
+}
+
+static void DIS_DD_NOP(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ dis_opcode_z80[op](z80,op,pc);
+}
+
+static void DIS_ADD_IX_BC(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","ix,bc");
+}
+
+static void DIS_ADD_IX_DE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","ix,de");
+}
+
+static void DIS_LD_IX_WORD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld",Z80_Dis_Printf("ix,$%.4x",Z80_Dis_FetchWord(z80,pc)));
+}
+
+static void DIS_LD_ADDR_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),ix",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),ix",w));
+}
+
+static void DIS_INC_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc","ix");
+}
+
+static void DIS_INC_IXH(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc","ixh");
+}
+
+static void DIS_DEC_IXH(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec","ixh");
+}
+
+static void DIS_LD_IXH_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld",Z80_Dis_Printf("ixh,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_ADD_IX_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","ix,ix");
+}
+
+static void DIS_LD_IX_ADDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("ix,(%s)",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("ix,($%.4x)",w));
+}
+
+static void DIS_DEC_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec","ix");
+}
+
+static void DIS_INC_IXL(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc","ixl");
+}
+
+static void DIS_DEC_IXL(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec","ixl");
+}
+
+static void DIS_LD_IXL_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld",Z80_Dis_Printf("ixl,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_INC_IIX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc",Z80_Dis_Printf("%s",IX_RelStr(z80,op,pc)));
+}
+
+static void DIS_DEC_IIX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec",Z80_Dis_Printf("%s",IX_RelStr(z80,op,pc)));
+}
+
+static void DIS_LD_IIX_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *rel;
+ int b;
+
+ rel=IX_RelStr(z80,op,pc);
+ b=Z80_Dis_FetchByte(z80,pc);
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.2x",rel,b));
+}
+
+
+static void DIS_ADD_IX_SP(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","ix,sp");
+}
+
+static void DIS_XLD_R8_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int src_r,dest_r;
+ const char *src,*dest;
+
+ dest_r=(op-0x40)/8;
+ src_r=op%8;
+
+ /* IX can't be used as source and destination when reading z80ory
+ */
+ if (dest_r==6)
+ {
+ dest=XR8(z80,dest_r,pc);
+ src=z80_dis_reg8[src_r];
+ }
+ else if (((dest_r==4)||(dest_r==5))&&(src_r==6))
+ {
+ dest=z80_dis_reg8[dest_r];
+ src=XR8(z80,src_r,pc);
+ }
+ else
+ {
+ dest=XR8(z80,dest_r,pc);
+ src=XR8(z80,src_r,pc);
+ }
+
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src));
+}
+
+static void DIS_XADD_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_XADC_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("adc",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_XSUB_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sub",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_XSBC_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sbc",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_XAND_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("and",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_XXOR_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("xor",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_X_OR_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("or",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_XCP_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cp",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc)));
+}
+
+static void DIS_POP_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("pop","ix");
+}
+
+static void DIS_EX_ISP_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ex","(sp),ix");
+}
+
+static void DIS_PUSH_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("push","ix");
+}
+
+static void DIS_JP_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("jp","(ix)");
+}
+
+static void DIS_LD_SP_IX(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","sp,ix");
+}
+
+static void DIS_DD_CB_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ cb_off=(Z80Relative)Z80_Dis_FetchByte(z80,pc);
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_DD_CB_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_DD_DD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_DD_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_DD_ED_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_ED_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_DD_FD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_FD_opcode[nop](z80,nop,pc);
+}
+
+
+/* ---------------------------------------- DD CB OPCODES
+*/
+
+static void DIS_RLC_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rlc",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ {
+ Z80_Dis_Set("rlc",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+ }
+}
+
+static void DIS_RRC_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rrc",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rrc",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RL_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rl",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rl",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RR_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rr",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rr",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SLA_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("sla",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("sla",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SRA_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("sra",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("sra",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SRL_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("srl",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("srl",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SLL_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("sll",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("sll",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_BIT_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+ int bit;
+
+ reg=(op%8);
+ bit=(op-0x40)/8;
+
+ if (reg==6)
+ Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s",bit,IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s[%s]",bit,IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RES_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+ int bit;
+
+ reg=(op%8);
+ bit=(op-0x80)/8;
+
+ if (reg==6)
+ Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s",bit,IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s[%s]",bit,IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SET_IX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+ int bit;
+
+ reg=(op%8);
+ bit=(op-0xc0)/8;
+
+ if (reg==6)
+ Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s",bit,IX_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s[%s]",bit,IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+
+/* ---------------------------------------- ED OPCODES
+*/
+
+static const char *ER8(int reg)
+{
+ switch(reg)
+ {
+ case 0:
+ return("b");
+ break;
+ case 1:
+ return("c");
+ break;
+ case 2:
+ return("d");
+ break;
+ case 3:
+ return("e");
+ break;
+ case 4:
+ return("h");
+ break;
+ case 5:
+ return("l");
+ break;
+ case 6:
+ return("0");
+ break;
+ case 7:
+ return("a");
+ break;
+ }
+
+ return "?";
+}
+
+/* Assumes illegal ED ops are being used for break points
+*/
+static void DIS_ED_NOP(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("brk",Z80_Dis_Printf("$%.2x",op));
+}
+
+static void DIS_IN_R8_C(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("in",Z80_Dis_Printf("%s,(c)",ER8((op-0x40)/8)));
+}
+
+static void DIS_OUT_C_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("out",Z80_Dis_Printf("(c),%s",ER8((op-0x40)/8)));
+}
+
+static void DIS_SBC_HL_R16(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sbc",Z80_Dis_Printf("hl,%s",z80_dis_reg16[(op-0x40)/16]));
+}
+
+static void DIS_ED_LD_ADDR_R16(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),%s",p,z80_dis_reg16[(op-0x40)/16]));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),%s",w,z80_dis_reg16[(op-0x40)/16]));
+}
+
+static void DIS_NEG(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("neg",NULL);
+}
+
+static void DIS_RETN(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("retn",NULL);
+}
+
+static void DIS_IM_0(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("im","0");
+}
+
+static void DIS_LD_I_A(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","i,a");
+}
+
+static void DIS_ADC_HL_R16(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("adc",Z80_Dis_Printf("hl,%s",z80_dis_reg16[(op-0x40)/16]));
+}
+
+static void DIS_ED_LD_R16_ADDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,(%s)",z80_dis_reg16[(op-0x40)/16],p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,($%.4x)",z80_dis_reg16[(op-0x40)/16],w));
+}
+
+static void DIS_RETI(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("reti",NULL);
+}
+
+static void DIS_LD_R_A(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","r,a");
+}
+
+static void DIS_IM_1(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("im","1");
+}
+
+static void DIS_LD_A_I(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","a,i");
+}
+
+static void DIS_IM_2(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("im","2");
+}
+
+static void DIS_LD_A_R(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","a,r");
+}
+
+static void DIS_RRD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("rrd",NULL);
+}
+
+static void DIS_RLD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("rld",NULL);
+}
+
+static void DIS_LDI(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ldi",NULL);
+}
+
+static void DIS_CPI(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cpi",NULL);
+}
+
+static void DIS_INI(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ini",NULL);
+}
+
+static void DIS_OUTI(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("outi",NULL);
+}
+
+static void DIS_LDD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ldd",NULL);
+}
+
+static void DIS_CPD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cpd",NULL);
+}
+
+static void DIS_IND(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ind",NULL);
+}
+
+static void DIS_OUTD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("outd",NULL);
+}
+
+static void DIS_LDIR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ldir",NULL);
+}
+
+static void DIS_CPIR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cpir",NULL);
+}
+
+static void DIS_INIR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inir",NULL);
+}
+
+static void DIS_OTIR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("otir",NULL);
+}
+
+static void DIS_LDDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("lddr",NULL);
+}
+
+static void DIS_CPDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cpdr",NULL);
+}
+
+static void DIS_INDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("indr",NULL);
+}
+
+static void DIS_OTDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("otdr",NULL);
+}
+
+
+/* ---------------------------------------- FD OPCODES
+*/
+
+static const char *IY_RelStr(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ static char s[80];
+ Z80Relative r;
+
+ r=(Z80Relative)Z80_Dis_FetchByte(z80,pc);
+
+ if (r<0)
+ sprintf(s,"(iy-$%.2x)",-r);
+ else
+ sprintf(s,"(iy+$%.2x)",r);
+
+ return(s);
+}
+
+
+static const char *IY_RelStrCB(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ static char s[80];
+ Z80Relative r;
+
+ r=(Z80Relative)cb_off;
+
+ if (r<0)
+ sprintf(s,"(iy-$%.2x)",-r);
+ else
+ sprintf(s,"(iy+$%.2x)",r);
+
+ return(s);
+}
+
+
+static const char *YR8(Z80 *z80, int reg, Z80Word *pc)
+{
+ switch(reg)
+ {
+ case 0:
+ return("b");
+ break;
+ case 1:
+ return("c");
+ break;
+ case 2:
+ return("d");
+ break;
+ case 3:
+ return("e");
+ break;
+ case 4:
+ return("iyh");
+ break;
+ case 5:
+ return("iyl");
+ break;
+ case 6:
+ return(IY_RelStr(z80,0,pc));
+ break;
+ case 7:
+ return("a");
+ break;
+ default:
+ return(Z80_Dis_Printf("BUG %d",reg));
+ break;
+ }
+}
+
+static void DIS_FD_NOP(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ dis_opcode_z80[op](z80,op,pc);
+}
+
+static void DIS_ADD_IY_BC(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","iy,bc");
+}
+
+static void DIS_ADD_IY_DE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","iy,de");
+}
+
+static void DIS_LD_IY_WORD(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld",Z80_Dis_Printf("iy,$%.4x",Z80_Dis_FetchWord(z80,pc)));
+}
+
+static void DIS_LD_ADDR_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),iy",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),iy",w));
+}
+
+static void DIS_INC_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc","iy");
+}
+
+static void DIS_INC_IYH(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc","iyh");
+}
+
+static void DIS_DEC_IYH(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec","iyh");
+}
+
+static void DIS_LD_IYH_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld",Z80_Dis_Printf("iyh,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_ADD_IY_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","iy,iy");
+}
+
+static void DIS_LD_IY_ADDR(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("iy,(%s)",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("iy,($%.4x)",w));
+}
+
+static void DIS_DEC_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec","iy");
+}
+
+static void DIS_INC_IYL(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc","iyl");
+}
+
+static void DIS_DEC_IYL(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec","iyl");
+}
+
+static void DIS_LD_IYL_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld",Z80_Dis_Printf("iyl,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_INC_IIY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("inc",Z80_Dis_Printf("%s",IY_RelStr(z80,op,pc)));
+}
+
+static void DIS_DEC_IIY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("dec",Z80_Dis_Printf("%s",IY_RelStr(z80,op,pc)));
+}
+
+static void DIS_LD_IIY_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *rel;
+ int b;
+
+ rel=IY_RelStr(z80,op,pc);
+ b=Z80_Dis_FetchByte(z80,pc);
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.2x",rel,b));
+}
+
+
+static void DIS_ADD_IY_SP(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add","iy,sp");
+}
+
+static void DIS_YLD_R8_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int src_r,dest_r;
+ const char *src,*dest;
+
+ dest_r=(op-0x40)/8;
+ src_r=op%8;
+
+ /* IY can't be used as source and destination when reading z80ory
+ */
+ if (dest_r==6)
+ {
+ dest=YR8(z80,dest_r,pc);
+ src=z80_dis_reg8[src_r];
+ }
+ else if (((dest_r==4)||(dest_r==5))&&(src_r==6))
+ {
+ dest=z80_dis_reg8[dest_r];
+ src=YR8(z80,src_r,pc);
+ }
+ else
+ {
+ dest=YR8(z80,dest_r,pc);
+ src=YR8(z80,src_r,pc);
+ }
+
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src));
+}
+
+static void DIS_YADD_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_YADC_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("adc",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_YSUB_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sub",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_YSBC_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sbc",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_YAND_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("and",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_YYOR_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("xor",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_Y_OR_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("or",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_YCP_R8(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cp",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc)));
+}
+
+static void DIS_POP_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("pop","iy");
+}
+
+static void DIS_EY_ISP_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ex","(sp),iy");
+}
+
+static void DIS_PUSH_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("push","iy");
+}
+
+static void DIS_JP_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("jp","(iy)");
+}
+
+static void DIS_LD_SP_IY(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","sp,iy");
+}
+
+static void DIS_FD_CB_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ cb_off=(Z80Relative)Z80_Dis_FetchByte(z80,pc);
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_FD_CB_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_FD_DD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_DD_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_FD_ED_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_ED_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_FD_FD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_FD_opcode[nop](z80,nop,pc);
+}
+
+
+/* ---------------------------------------- FD CB OPCODES
+*/
+
+static void DIS_RLC_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rlc",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rlc",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RRC_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rrc",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rrc",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RL_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rl",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rl",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RR_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("rr",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("rr",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SLA_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("sla",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("sla",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SRA_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("sra",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("sra",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SRL_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("srl",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("srl",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SLL_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+
+ reg=(op%8);
+
+ if (reg==6)
+ Z80_Dis_Set("sll",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("sll",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_BIT_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+ int bit;
+
+ reg=(op%8);
+ bit=(op-0x40)/8;
+
+ if (reg==6)
+ Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s",bit,IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s[%s]",bit,IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_RES_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+ int bit;
+
+ reg=(op%8);
+ bit=(op-0x80)/8;
+
+ if (reg==6)
+ Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s",bit,IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s[%s]",bit,IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+static void DIS_SET_IY (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int reg;
+ int bit;
+
+ reg=(op%8);
+ bit=(op-0xc0)/8;
+
+ if (reg==6)
+ Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s",bit,IY_RelStrCB(z80,op,pc)));
+ else
+ Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s[%s]",bit,IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg]));
+}
+
+
+/* ---------------------------------------- SINGLE BYTE OPCODES
+*/
+static void DIS_NOP (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("nop",NULL);
+}
+
+static void DIS_LD_R16_WORD (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op&0x30)/0x10];
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.4x",reg,Z80_Dis_FetchWord(z80,pc)));
+}
+
+static void DIS_LD_R16_A (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op&0x30)/0x10];
+ Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),a",reg));
+}
+
+static void DIS_INC_R16 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op&0x30)/0x10];
+ Z80_Dis_Set("inc",reg);
+}
+
+static void DIS_INC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[(op&0x38)/0x8];
+ Z80_Dis_Set("inc",reg);
+}
+
+static void DIS_DEC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[(op&0x38)/0x8];
+ Z80_Dis_Set("dec",reg);
+}
+
+static void DIS_LD_R8_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[(op&0x38)/0x8];
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.2x",reg,Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_RLCA (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("rlca",NULL);
+}
+
+static void DIS_EX_AF_AF (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ex","af,af'");
+}
+
+static void DIS_ADD_HL_R16 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op&0x30)/0x10];
+ Z80_Dis_Set("add",Z80_Dis_Printf("hl,%s",reg));
+}
+
+static void DIS_LD_A_R16 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op&0x30)/0x10];
+ Z80_Dis_Set("ld",Z80_Dis_Printf("a,(%s)",reg));
+}
+
+static void DIS_DEC_R16 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op&0x30)/0x10];
+ Z80_Dis_Set("dec",reg);
+}
+
+static void DIS_RRCA (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("rrca",NULL);
+}
+
+static void DIS_DJNZ (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word new;
+
+#ifdef ENABLE_ARRAY_MEMORY
+ new=*pc+(Z80Relative)Z80_MEMORY[*pc]+1;
+#else
+ new=*pc+(Z80Relative)z80->priv->disread(z80,*pc)+1;
+#endif
+ (*pc)++;
+ Z80_Dis_Set("djnz",Z80_Dis_Printf("$%.4x",new));
+}
+
+static void DIS_RLA (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("rla",NULL);
+}
+
+static void DIS_JR (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word new;
+ const char *p;
+
+#ifdef ENABLE_ARRAY_MEMORY
+ new=*pc+(Z80Relative)Z80_MEMORY[*pc]+1;
+#else
+ new=*pc+(Z80Relative)z80->priv->disread(z80,*pc)+1;
+#endif
+ (*pc)++;
+
+ if ((p=GetLabel(new)))
+ Z80_Dis_Set("jr",Z80_Dis_Printf("%s",p));
+ else
+ Z80_Dis_Set("jr",Z80_Dis_Printf("$%.4x",new));
+}
+
+static void DIS_RRA (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("rra",NULL);
+}
+
+static void DIS_JR_CO (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *con;
+ Z80Word new;
+ const char *p;
+
+ con=z80_dis_condition[(op-0x20)/8];
+#ifdef ENABLE_ARRAY_MEMORY
+ new=*pc+(Z80Relative)Z80_MEMORY[*pc]+1;
+#else
+ new=*pc+(Z80Relative)z80->priv->disread(z80,*pc)+1;
+#endif
+ (*pc)++;
+
+ if ((p=GetLabel(new)))
+ Z80_Dis_Set("jr",Z80_Dis_Printf("%s,%s",con,p));
+ else
+ Z80_Dis_Set("jr",Z80_Dis_Printf("%s,$%.4x",con,new));
+}
+
+static void DIS_LD_ADDR_HL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),hl",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),hl",w));
+}
+
+static void DIS_DAA (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("daa",NULL);
+}
+
+static void DIS_LD_HL_ADDR (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("hl,(%s)",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("hl,($%.4x)",w));
+}
+
+static void DIS_CPL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cpl",NULL);
+}
+
+static void DIS_LD_ADDR_A (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),a",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),a",w));
+}
+
+static void DIS_SCF (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("scf",NULL);
+}
+
+static void DIS_LD_A_ADDR (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("ld",Z80_Dis_Printf("a,(%s)",p));
+ else
+ Z80_Dis_Set("ld",Z80_Dis_Printf("a,($%.4x)",w));
+}
+
+static void DIS_CCF (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ccf",NULL);
+}
+
+static void DIS_LD_R8_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *src,*dest;
+
+ dest=z80_dis_reg8[(op-0x40)/8];
+ src=z80_dis_reg8[op%8];
+ Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src));
+}
+
+static void DIS_HALT (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("halt",NULL);
+}
+
+static void DIS_ADD_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("add",Z80_Dis_Printf("a,%s",reg));
+}
+
+static void DIS_ADC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("adc",Z80_Dis_Printf("a,%s",reg));
+}
+
+static void DIS_SUB_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("sub",Z80_Dis_Printf("a,%s",reg));
+}
+
+static void DIS_SBC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("sbc",Z80_Dis_Printf("a,%s",reg));
+}
+
+static void DIS_AND_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("and",Z80_Dis_Printf("%s",reg));
+}
+
+static void DIS_XOR_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("xor",Z80_Dis_Printf("%s",reg));
+}
+
+static void DIS_OR_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("or",Z80_Dis_Printf("%s",reg));
+}
+
+static void DIS_CP_R8 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg8[op%8];
+ Z80_Dis_Set("cp",Z80_Dis_Printf("%s",reg));
+}
+
+
+static void DIS_RET_CO (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *con;
+
+ con=z80_dis_condition[(op-0xc0)/8];
+ Z80_Dis_Set("ret",con);
+}
+
+static void DIS_POP_R16 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op-0xc0)/16];
+
+ if (!strcmp(reg,"sp"))
+ reg="af";
+
+ Z80_Dis_Set("pop",reg);
+}
+
+static void DIS_JP (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("jp",Z80_Dis_Printf("%s",p));
+ else
+ Z80_Dis_Set("jp",Z80_Dis_Printf("$%.4x",w));
+}
+
+static void DIS_PUSH_R16 (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *reg;
+
+ reg=z80_dis_reg16[(op-0xc0)/16];
+
+ if (!strcmp(reg,"sp"))
+ reg="af";
+
+ Z80_Dis_Set("push",reg);
+}
+
+static void DIS_ADD_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("add",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_RST (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int add;
+
+ add=(op&0x3f)-7;
+ Z80_Dis_Set("rst",Z80_Dis_Printf("%.2xh",add));
+}
+
+static void DIS_RET (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ret",NULL);
+}
+
+static void DIS_JP_CO (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *con;
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+ con=z80_dis_condition[(op-0xc0)/8];
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("jp",Z80_Dis_Printf("%s,%s",con,p));
+ else
+ Z80_Dis_Set("jp",Z80_Dis_Printf("%s,$%.4x",con,w));
+}
+
+static void DIS_CB_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_CB_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_CALL_CO (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ const char *con;
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+ con=z80_dis_condition[(op-0xc0)/8];
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("call",Z80_Dis_Printf("%s,%s",con,p));
+ else
+ Z80_Dis_Set("call",Z80_Dis_Printf("%s,$%.4x",con,w));
+}
+
+static void DIS_CALL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80Word w;
+ const char *p;
+
+ w=Z80_Dis_FetchWord(z80,pc);
+
+ if ((p=GetLabel(w)))
+ Z80_Dis_Set("call",Z80_Dis_Printf("%s",p));
+ else
+ Z80_Dis_Set("call",Z80_Dis_Printf("$%.4x",w));
+}
+
+static void DIS_ADC_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("adc",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_OUT_BYTE_A (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("out",Z80_Dis_Printf("($%.2x),a",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_SUB_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sub",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_EXX (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("exx",NULL);
+}
+
+static void DIS_IN_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("in",Z80_Dis_Printf("a,($%.2x)",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_DD_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_DD_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_SBC_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("sbc",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+
+static void DIS_EX_ISP_HL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ex","(sp),hl");
+}
+
+static void DIS_AND_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("and",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_JP_HL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("jp","(hl)");
+}
+
+static void DIS_EX_DE_HL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ex","de,hl");
+}
+
+static void DIS_ED_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_ED_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_XOR_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("xor",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_DI (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("di",NULL);
+}
+
+static void DIS_OR_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("or",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+static void DIS_LD_SP_HL (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ld","sp,hl");
+}
+
+static void DIS_EI (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("ei",NULL);
+}
+
+static void DIS_FD_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ int nop;
+
+ nop=Z80_Dis_FetchByte(z80,pc);
+ dis_FD_opcode[nop](z80,nop,pc);
+}
+
+static void DIS_CP_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc)
+{
+ Z80_Dis_Set("cp",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc)));
+}
+
+
+/* ---------------------------------------- TABLES
+*/
+
+/* CB opcodes
+*/
+DIS_OP_CALLBACK dis_CB_opcode[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8,
+/* 0x04 - 0x07 */ DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8,
+/* 0x08 - 0x0b */ DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8,
+/* 0x0c - 0x0f */ DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8,
+
+/* 0x10 - 0x13 */ DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, DIS_RL_R8,
+/* 0x14 - 0x17 */ DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, DIS_RL_R8,
+/* 0x18 - 0x1b */ DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, DIS_RR_R8,
+/* 0x1c - 0x1f */ DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, DIS_RR_R8,
+
+/* 0x20 - 0x23 */ DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8,
+/* 0x24 - 0x27 */ DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8,
+/* 0x28 - 0x2b */ DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8,
+/* 0x2c - 0x2f */ DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8,
+
+/* 0x30 - 0x33 */ DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8,
+/* 0x34 - 0x37 */ DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8,
+/* 0x38 - 0x3b */ DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8,
+/* 0x3c - 0x3f */ DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8,
+
+/* 0x40 - 0x43 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x44 - 0x47 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x48 - 0x4b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x4c - 0x4f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+
+/* 0x50 - 0x53 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x54 - 0x57 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x58 - 0x5b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x5c - 0x5f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+
+/* 0x60 - 0x63 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x64 - 0x67 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x68 - 0x6b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x6c - 0x6f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+
+/* 0x70 - 0x73 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x74 - 0x77 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x78 - 0x7b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+/* 0x7c - 0x7f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8,
+
+/* 0x80 - 0x83 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0x84 - 0x87 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0x88 - 0x8b */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0x8c - 0x8f */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+
+/* 0x90 - 0x93 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0x94 - 0x97 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0x98 - 0x9b */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0x9c - 0x9f */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+
+/* 0xa0 - 0xa3 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0xa4 - 0xa7 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0xa8 - 0xab */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0xac - 0xaf */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+
+/* 0xb0 - 0xb3 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0xb4 - 0xb7 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0xb8 - 0xbb */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+/* 0xbc - 0xbf */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8,
+
+/* 0xc0 - 0xc3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xc4 - 0xc7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xc8 - 0xcb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xcc - 0xcf */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+
+/* 0xd0 - 0xd3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xd4 - 0xd7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xd8 - 0xdb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xdc - 0xdf */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+
+/* 0xe0 - 0xe3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xe4 - 0xe7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xe8 - 0xeb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xec - 0xef */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+
+/* 0xf0 - 0xf3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xf4 - 0xf7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xf8 - 0xfb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+/* 0xfc - 0xff */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8,
+ };
+
+/* DIS_DD opcodes
+*/
+DIS_OP_CALLBACK dis_DD_opcode[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x04 - 0x07 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x08 - 0x0b */ DIS_DD_NOP, DIS_ADD_IX_BC, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x0c - 0x0f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+
+/* 0x10 - 0x13 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x14 - 0x17 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x18 - 0x1b */ DIS_DD_NOP, DIS_ADD_IX_DE, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x1c - 0x1f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+
+/* 0x20 - 0x23 */ DIS_DD_NOP, DIS_LD_IX_WORD, DIS_LD_ADDR_IX, DIS_INC_IX,
+/* 0x24 - 0x27 */ DIS_INC_IXH, DIS_DEC_IXH, DIS_LD_IXH_BYTE, DIS_DD_NOP,
+/* 0x28 - 0x2b */ DIS_DD_NOP, DIS_ADD_IX_IX, DIS_LD_IX_ADDR, DIS_DEC_IX,
+/* 0x2c - 0x2f */ DIS_INC_IXL, DIS_DEC_IXL, DIS_LD_IXL_BYTE, DIS_DD_NOP,
+
+/* 0x30 - 0x33 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x34 - 0x37 */ DIS_INC_IIX, DIS_DEC_IIX, DIS_LD_IIX_BYTE, DIS_DD_NOP,
+/* 0x38 - 0x3b */ DIS_DD_NOP, DIS_ADD_IX_SP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x3c - 0x3f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+
+/* 0x40 - 0x43 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x44 - 0x47 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP,
+/* 0x48 - 0x4b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x4c - 0x4f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP,
+
+/* 0x50 - 0x53 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x54 - 0x57 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP,
+/* 0x58 - 0x5b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x5c - 0x5f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP,
+
+/* 0x60 - 0x63 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8,
+/* 0x64 - 0x67 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8,
+/* 0x68 - 0x6b */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8,
+/* 0x6c - 0x6f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8,
+
+/* 0x70 - 0x73 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8,
+/* 0x74 - 0x77 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, DIS_XLD_R8_R8,
+/* 0x78 - 0x7b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x7c - 0x7f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP,
+
+/* 0x80 - 0x83 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x84 - 0x87 */ DIS_XADD_R8, DIS_XADD_R8, DIS_XADD_R8, DIS_DD_NOP,
+/* 0x88 - 0x8b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x8c - 0x8f */ DIS_XADC_R8, DIS_XADC_R8, DIS_XADC_R8, DIS_DD_NOP,
+
+/* 0x90 - 0x93 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x94 - 0x97 */ DIS_XSUB_R8, DIS_XSUB_R8, DIS_XSUB_R8, DIS_DD_NOP,
+/* 0x98 - 0x9b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0x9c - 0x9f */ DIS_XSBC_R8, DIS_XSBC_R8, DIS_XSBC_R8, DIS_DD_NOP,
+
+/* 0xa0 - 0xa3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xa4 - 0xa7 */ DIS_XAND_R8, DIS_XAND_R8, DIS_XAND_R8, DIS_DD_NOP,
+/* 0xa8 - 0xab */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xac - 0xaf */ DIS_XXOR_R8, DIS_XXOR_R8, DIS_XXOR_R8, DIS_DD_NOP,
+
+/* 0xb0 - 0xb3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xb4 - 0xb7 */ DIS_X_OR_R8, DIS_X_OR_R8, DIS_X_OR_R8, DIS_DD_NOP,
+/* 0xb8 - 0xbb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xbc - 0xbf */ DIS_XCP_R8, DIS_XCP_R8, DIS_XCP_R8, DIS_DD_NOP,
+
+/* 0xc0 - 0xc3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xc4 - 0xc7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xc8 - 0xcb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_CB_DECODE,
+/* 0xcc - 0xcf */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+
+/* 0xd0 - 0xd3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xd4 - 0xd7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xd8 - 0xdb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xdc - 0xdf */ DIS_DD_NOP, DIS_DD_DD_DECODE, DIS_DD_NOP, DIS_DD_NOP,
+
+/* 0xe0 - 0xe3 */ DIS_DD_NOP, DIS_POP_IX, DIS_DD_NOP, DIS_EX_ISP_IX,
+/* 0xe4 - 0xe7 */ DIS_DD_NOP, DIS_PUSH_IX, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xe8 - 0xeb */ DIS_DD_NOP, DIS_JP_IX, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xec - 0xef */ DIS_DD_NOP, DIS_DD_ED_DECODE, DIS_DD_NOP, DIS_DD_NOP,
+
+/* 0xf0 - 0xf3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xf4 - 0xf7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xf8 - 0xfb */ DIS_DD_NOP, DIS_LD_SP_IX, DIS_DD_NOP, DIS_DD_NOP,
+/* 0xfc - 0xff */ DIS_DD_NOP, DIS_DD_FD_DECODE, DIS_DD_NOP, DIS_DD_NOP,
+ };
+
+
+/* DIS_DD DIS_CB opcodes
+*/
+DIS_OP_CALLBACK dis_DD_CB_opcode[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX,
+/* 0x04 - 0x07 */ DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX,
+/* 0x08 - 0x0b */ DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX,
+/* 0x0c - 0x0f */ DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX,
+
+/* 0x10 - 0x13 */ DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, DIS_RL_IX,
+/* 0x14 - 0x17 */ DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, DIS_RL_IX,
+/* 0x18 - 0x1b */ DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, DIS_RR_IX,
+/* 0x1c - 0x1f */ DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, DIS_RR_IX,
+
+/* 0x20 - 0x23 */ DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX,
+/* 0x24 - 0x27 */ DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX,
+/* 0x28 - 0x2b */ DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX,
+/* 0x2c - 0x2f */ DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX,
+
+/* 0x30 - 0x33 */ DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX,
+/* 0x34 - 0x37 */ DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX,
+/* 0x38 - 0x3b */ DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX,
+/* 0x3c - 0x3f */ DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX,
+
+/* 0x40 - 0x43 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x44 - 0x47 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x48 - 0x4b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x4c - 0x4f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+
+/* 0x50 - 0x53 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x54 - 0x57 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x58 - 0x5b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x5c - 0x5f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+
+/* 0x60 - 0x63 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x64 - 0x67 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x68 - 0x6b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x6c - 0x6f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+
+/* 0x70 - 0x73 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x74 - 0x77 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x78 - 0x7b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+/* 0x7c - 0x7f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX,
+
+/* 0x80 - 0x83 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0x84 - 0x87 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0x88 - 0x8b */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0x8c - 0x8f */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+
+/* 0x90 - 0x93 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0x94 - 0x97 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0x98 - 0x9b */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0x9c - 0x9f */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+
+/* 0xa0 - 0xa3 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0xa4 - 0xa7 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0xa8 - 0xab */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0xac - 0xaf */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+
+/* 0xb0 - 0xb3 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0xb4 - 0xb7 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0xb8 - 0xbb */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+/* 0xbc - 0xbf */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX,
+
+/* 0xc0 - 0xc3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xc4 - 0xc7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xc8 - 0xcb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xcc - 0xcf */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+
+/* 0xd0 - 0xd3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xd4 - 0xd7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xd8 - 0xdb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xdc - 0xdf */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+
+/* 0xe0 - 0xe3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xe4 - 0xe7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xe8 - 0xeb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xec - 0xef */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+
+/* 0xf0 - 0xf3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xf4 - 0xf7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xf8 - 0xfb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+/* 0xfc - 0xff */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX,
+ };
+
+/* DIS_ED opcodes
+*/
+DIS_OP_CALLBACK dis_ED_opcode[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x04 - 0x07 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x08 - 0x0b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x0c - 0x0f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0x10 - 0x13 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x14 - 0x17 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x18 - 0x1b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x1c - 0x1f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0x20 - 0x23 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x24 - 0x27 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x28 - 0x2b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x2c - 0x2f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0x30 - 0x33 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x34 - 0x37 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x38 - 0x3b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x3c - 0x3f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0x40 - 0x43 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16,
+/* 0x44 - 0x47 */ DIS_NEG, DIS_RETN, DIS_IM_0, DIS_LD_I_A,
+/* 0x48 - 0x4b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR,
+/* 0x4c - 0x4f */ DIS_NEG, DIS_RETI, DIS_IM_0, DIS_LD_R_A,
+
+/* 0x50 - 0x53 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16,
+/* 0x54 - 0x57 */ DIS_NEG, DIS_RETN, DIS_IM_1, DIS_LD_A_I,
+/* 0x58 - 0x5b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR,
+/* 0x5c - 0x5f */ DIS_NEG, DIS_RETI, DIS_IM_2, DIS_LD_A_R,
+
+/* 0x60 - 0x63 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16,
+/* 0x64 - 0x67 */ DIS_NEG, DIS_RETN, DIS_IM_0, DIS_RRD,
+/* 0x68 - 0x6b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR,
+/* 0x6c - 0x6f */ DIS_NEG, DIS_RETI, DIS_IM_0, DIS_RLD,
+
+/* 0x70 - 0x73 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16,
+/* 0x74 - 0x77 */ DIS_NEG, DIS_RETN, DIS_IM_1, DIS_ED_NOP,
+/* 0x78 - 0x7b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR,
+/* 0x7c - 0x7f */ DIS_NEG, DIS_RETI, DIS_IM_2, DIS_ED_NOP,
+
+/* 0x80 - 0x83 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x84 - 0x87 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x88 - 0x8b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x8c - 0x8f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0x90 - 0x93 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x94 - 0x97 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x98 - 0x9b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0x9c - 0x9f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0xa0 - 0xa3 */ DIS_LDI, DIS_CPI, DIS_INI, DIS_OUTI,
+/* 0xa4 - 0xa7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xa8 - 0xab */ DIS_LDD, DIS_CPD, DIS_IND, DIS_OUTD,
+/* 0xac - 0xaf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0xb0 - 0xb3 */ DIS_LDIR, DIS_CPIR, DIS_INIR, DIS_OTIR,
+/* 0xb4 - 0xb7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xb8 - 0xbb */ DIS_LDDR, DIS_CPDR, DIS_INDR, DIS_OTDR,
+/* 0xbc - 0xbf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0xc0 - 0xc3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xc4 - 0xc7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xc8 - 0xcb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xcc - 0xcf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0xd0 - 0xd3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xd4 - 0xd7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xd8 - 0xdb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xdc - 0xdf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0xe0 - 0xe3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xe4 - 0xe7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xe8 - 0xeb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xec - 0xef */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+
+/* 0xf0 - 0xf3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xf4 - 0xf7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xf8 - 0xfb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+/* 0xfc - 0xff */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP,
+ };
+
+/* DIS_FD opcodes
+*/
+DIS_OP_CALLBACK dis_FD_opcode[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x04 - 0x07 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x08 - 0x0b */ DIS_FD_NOP, DIS_ADD_IY_BC, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x0c - 0x0f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+
+/* 0x10 - 0x13 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x14 - 0x17 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x18 - 0x1b */ DIS_FD_NOP, DIS_ADD_IY_DE, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x1c - 0x1f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+
+/* 0x20 - 0x23 */ DIS_FD_NOP, DIS_LD_IY_WORD, DIS_LD_ADDR_IY, DIS_INC_IY,
+/* 0x24 - 0x27 */ DIS_INC_IYH, DIS_DEC_IYH, DIS_LD_IYH_BYTE, DIS_FD_NOP,
+/* 0x28 - 0x2b */ DIS_FD_NOP, DIS_ADD_IY_IY, DIS_LD_IY_ADDR, DIS_DEC_IY,
+/* 0x2c - 0x2f */ DIS_INC_IYL, DIS_DEC_IYL, DIS_LD_IYL_BYTE, DIS_FD_NOP,
+
+/* 0x30 - 0x33 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x34 - 0x37 */ DIS_INC_IIY, DIS_DEC_IIY, DIS_LD_IIY_BYTE, DIS_FD_NOP,
+/* 0x38 - 0x3b */ DIS_FD_NOP, DIS_ADD_IY_SP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x3c - 0x3f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+
+/* 0x40 - 0x43 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x44 - 0x47 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP,
+/* 0x48 - 0x4b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x4c - 0x4f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP,
+
+/* 0x50 - 0x53 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x54 - 0x57 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP,
+/* 0x58 - 0x5b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x5c - 0x5f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP,
+
+/* 0x60 - 0x63 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8,
+/* 0x64 - 0x67 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8,
+/* 0x68 - 0x6b */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8,
+/* 0x6c - 0x6f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8,
+
+/* 0x70 - 0x73 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8,
+/* 0x74 - 0x77 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, DIS_YLD_R8_R8,
+/* 0x78 - 0x7b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x7c - 0x7f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP,
+
+/* 0x80 - 0x83 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x84 - 0x87 */ DIS_YADD_R8, DIS_YADD_R8, DIS_YADD_R8, DIS_FD_NOP,
+/* 0x88 - 0x8b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x8c - 0x8f */ DIS_YADC_R8, DIS_YADC_R8, DIS_YADC_R8, DIS_FD_NOP,
+
+/* 0x90 - 0x93 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x94 - 0x97 */ DIS_YSUB_R8, DIS_YSUB_R8, DIS_YSUB_R8, DIS_FD_NOP,
+/* 0x98 - 0x9b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0x9c - 0x9f */ DIS_YSBC_R8, DIS_YSBC_R8, DIS_YSBC_R8, DIS_FD_NOP,
+
+/* 0xa0 - 0xa3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xa4 - 0xa7 */ DIS_YAND_R8, DIS_YAND_R8, DIS_YAND_R8, DIS_FD_NOP,
+/* 0xa8 - 0xab */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xac - 0xaf */ DIS_YYOR_R8, DIS_YYOR_R8, DIS_YYOR_R8, DIS_FD_NOP,
+
+/* 0xb0 - 0xb3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xb4 - 0xb7 */ DIS_Y_OR_R8, DIS_Y_OR_R8, DIS_Y_OR_R8, DIS_FD_NOP,
+/* 0xb8 - 0xbb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xbc - 0xbf */ DIS_YCP_R8, DIS_YCP_R8, DIS_YCP_R8, DIS_FD_NOP,
+
+/* 0xc0 - 0xc3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xc4 - 0xc7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xc8 - 0xcb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_CB_DECODE,
+/* 0xcc - 0xcf */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+
+/* 0xd0 - 0xd3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xd4 - 0xd7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xd8 - 0xdb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xdc - 0xdf */ DIS_FD_NOP, DIS_FD_DD_DECODE, DIS_FD_NOP, DIS_FD_NOP,
+
+/* 0xe0 - 0xe3 */ DIS_FD_NOP, DIS_POP_IY, DIS_FD_NOP, DIS_EY_ISP_IY,
+/* 0xe4 - 0xe7 */ DIS_FD_NOP, DIS_PUSH_IY, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xe8 - 0xeb */ DIS_FD_NOP, DIS_JP_IY, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xec - 0xef */ DIS_FD_NOP, DIS_FD_ED_DECODE, DIS_FD_NOP, DIS_FD_NOP,
+
+/* 0xf0 - 0xf3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xf4 - 0xf7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xf8 - 0xfb */ DIS_FD_NOP, DIS_LD_SP_IY, DIS_FD_NOP, DIS_FD_NOP,
+/* 0xfc - 0xff */ DIS_FD_NOP, DIS_FD_FD_DECODE, DIS_FD_NOP, DIS_FD_NOP,
+ };
+
+
+/* DIS_FD DIS_CB opcodes
+*/
+DIS_OP_CALLBACK dis_FD_CB_opcode[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY,
+/* 0x04 - 0x07 */ DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY,
+/* 0x08 - 0x0b */ DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY,
+/* 0x0c - 0x0f */ DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY,
+
+/* 0x10 - 0x13 */ DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, DIS_RL_IY,
+/* 0x14 - 0x17 */ DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, DIS_RL_IY,
+/* 0x18 - 0x1b */ DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, DIS_RR_IY,
+/* 0x1c - 0x1f */ DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, DIS_RR_IY,
+
+/* 0x20 - 0x23 */ DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY,
+/* 0x24 - 0x27 */ DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY,
+/* 0x28 - 0x2b */ DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY,
+/* 0x2c - 0x2f */ DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY,
+
+/* 0x30 - 0x33 */ DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY,
+/* 0x34 - 0x37 */ DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY,
+/* 0x38 - 0x3b */ DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY,
+/* 0x3c - 0x3f */ DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY,
+
+/* 0x40 - 0x43 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x44 - 0x47 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x48 - 0x4b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x4c - 0x4f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+
+/* 0x50 - 0x53 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x54 - 0x57 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x58 - 0x5b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x5c - 0x5f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+
+/* 0x60 - 0x63 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x64 - 0x67 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x68 - 0x6b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x6c - 0x6f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+
+/* 0x70 - 0x73 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x74 - 0x77 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x78 - 0x7b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+/* 0x7c - 0x7f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY,
+
+/* 0x80 - 0x83 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0x84 - 0x87 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0x88 - 0x8b */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0x8c - 0x8f */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+
+/* 0x90 - 0x93 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0x94 - 0x97 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0x98 - 0x9b */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0x9c - 0x9f */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+
+/* 0xa0 - 0xa3 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0xa4 - 0xa7 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0xa8 - 0xab */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0xac - 0xaf */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+
+/* 0xb0 - 0xb3 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0xb4 - 0xb7 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0xb8 - 0xbb */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+/* 0xbc - 0xbf */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY,
+
+/* 0xc0 - 0xc3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xc4 - 0xc7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xc8 - 0xcb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xcc - 0xcf */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+
+/* 0xd0 - 0xd3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xd4 - 0xd7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xd8 - 0xdb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xdc - 0xdf */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+
+/* 0xe0 - 0xe3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xe4 - 0xe7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xe8 - 0xeb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xec - 0xef */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+
+/* 0xf0 - 0xf3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xf4 - 0xf7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xf8 - 0xfb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+/* 0xfc - 0xff */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY,
+ };
+
+/* DIS_First/single byte opcodes
+*/
+DIS_OP_CALLBACK dis_opcode_z80[0x100]=
+ {
+/* 0x00 - 0x03 */ DIS_NOP, DIS_LD_R16_WORD, DIS_LD_R16_A, DIS_INC_R16,
+/* 0x04 - 0x07 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RLCA,
+/* 0x08 - 0x0b */ DIS_EX_AF_AF, DIS_ADD_HL_R16, DIS_LD_A_R16, DIS_DEC_R16,
+/* 0x0c - 0x0f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RRCA,
+
+/* 0x10 - 0x13 */ DIS_DJNZ, DIS_LD_R16_WORD, DIS_LD_R16_A, DIS_INC_R16,
+/* 0x14 - 0x17 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RLA,
+/* 0x18 - 0x1b */ DIS_JR, DIS_ADD_HL_R16, DIS_LD_A_R16, DIS_DEC_R16,
+/* 0x1c - 0x1f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RRA,
+
+/* 0x20 - 0x23 */ DIS_JR_CO, DIS_LD_R16_WORD, DIS_LD_ADDR_HL, DIS_INC_R16,
+/* 0x24 - 0x27 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_DAA,
+/* 0x28 - 0x2b */ DIS_JR_CO, DIS_ADD_HL_R16, DIS_LD_HL_ADDR, DIS_DEC_R16,
+/* 0x2c - 0x2f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_CPL,
+
+/* 0x30 - 0x33 */ DIS_JR_CO, DIS_LD_R16_WORD, DIS_LD_ADDR_A, DIS_INC_R16,
+/* 0x34 - 0x37 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_SCF,
+/* 0x38 - 0x3b */ DIS_JR_CO, DIS_ADD_HL_R16, DIS_LD_A_ADDR, DIS_DEC_R16,
+/* 0x3c - 0x3f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_CCF,
+
+/* 0x40 - 0x43 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x44 - 0x47 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x48 - 0x4b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x4c - 0x4f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+
+/* 0x50 - 0x53 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x54 - 0x57 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x58 - 0x5b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x5c - 0x5f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+
+/* 0x60 - 0x63 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x64 - 0x67 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x68 - 0x6b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x6c - 0x6f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+
+/* 0x70 - 0x73 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x74 - 0x77 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_HALT, DIS_LD_R8_R8,
+/* 0x78 - 0x7b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+/* 0x7c - 0x7f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8,
+
+/* 0x80 - 0x83 */ DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8,
+/* 0x84 - 0x87 */ DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8,
+/* 0x88 - 0x8b */ DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8,
+/* 0x8c - 0x8f */ DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8,
+
+/* 0x90 - 0x93 */ DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8,
+/* 0x94 - 0x97 */ DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8,
+/* 0x98 - 0x9b */ DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8,
+/* 0x9c - 0x9f */ DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8,
+
+/* 0xa0 - 0xa3 */ DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, DIS_AND_R8,
+/* 0xa4 - 0xa7 */ DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, DIS_AND_R8,
+/* 0xa8 - 0xab */ DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8,
+/* 0xac - 0xaf */ DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8,
+
+/* 0xb0 - 0xb3 */ DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, DIS_OR_R8,
+/* 0xb4 - 0xb7 */ DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, DIS_OR_R8,
+/* 0xb8 - 0xbb */ DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, DIS_CP_R8,
+/* 0xbc - 0xbf */ DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, DIS_CP_R8,
+
+/* 0xc0 - 0xc3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_JP,
+/* 0xc4 - 0xc7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_ADD_A_BYTE, DIS_RST,
+/* 0xc8 - 0xcb */ DIS_RET_CO, DIS_RET, DIS_JP_CO, DIS_CB_DECODE,
+/* 0xcc - 0xcf */ DIS_CALL_CO, DIS_CALL, DIS_ADC_A_BYTE, DIS_RST,
+
+/* 0xd0 - 0xd3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_OUT_BYTE_A,
+/* 0xd4 - 0xd7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_SUB_A_BYTE, DIS_RST,
+/* 0xd8 - 0xdb */ DIS_RET_CO, DIS_EXX, DIS_JP_CO, DIS_IN_A_BYTE,
+/* 0xdc - 0xdf */ DIS_CALL_CO, DIS_DD_DECODE, DIS_SBC_A_BYTE, DIS_RST,
+
+/* 0xe0 - 0xe3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_EX_ISP_HL,
+/* 0xe4 - 0xe7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_AND_A_BYTE, DIS_RST,
+/* 0xe8 - 0xeb */ DIS_RET_CO, DIS_JP_HL, DIS_JP_CO, DIS_EX_DE_HL,
+/* 0xec - 0xef */ DIS_CALL_CO, DIS_ED_DECODE, DIS_XOR_A_BYTE, DIS_RST,
+
+/* 0xf0 - 0xf3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_DI,
+/* 0xf4 - 0xf7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_OR_A_BYTE, DIS_RST,
+/* 0xf8 - 0xfb */ DIS_RET_CO, DIS_LD_SP_HL, DIS_JP_CO, DIS_EI,
+/* 0xfc - 0xff */ DIS_CALL_CO, DIS_FD_DECODE, DIS_CP_A_BYTE, DIS_RST,
+ };
+
+
+#endif
+
+/* END OF FILE */