From a814584c87fef79038f6b0f311cfc70fb51d1b95 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sat, 11 Mar 2006 15:44:35 +0000 Subject: pacbox - a Pacman arcade machine emulator. Currently working for all colour targets and the iriver H1x0. Requires the Pacman arcade machine ROMs in /.rockbox/pacman/ git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9001 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 8 + apps/plugin.h | 12 +- apps/plugins/Makefile | 6 + apps/plugins/pacbox/Makefile | 113 + apps/plugins/pacbox/arcade.c | 577 +++ apps/plugins/pacbox/arcade.h | 199 + apps/plugins/pacbox/hardware.c | 197 + apps/plugins/pacbox/hardware.h | 141 + apps/plugins/pacbox/pacbox.c | 534 +++ apps/plugins/pacbox/readme.txt | 13 + apps/plugins/pacbox/z80.c | 8058 ++++++++++++++++++++++++++++++++++++ apps/plugins/pacbox/z80.h | 160 + apps/plugins/pacbox/z80_internal.h | 1062 +++++ 13 files changed, 11079 insertions(+), 1 deletion(-) create mode 100644 apps/plugins/pacbox/Makefile create mode 100644 apps/plugins/pacbox/arcade.c create mode 100644 apps/plugins/pacbox/arcade.h create mode 100644 apps/plugins/pacbox/hardware.c create mode 100644 apps/plugins/pacbox/hardware.h create mode 100644 apps/plugins/pacbox/pacbox.c create mode 100644 apps/plugins/pacbox/readme.txt create mode 100644 apps/plugins/pacbox/z80.c create mode 100644 apps/plugins/pacbox/z80.h create mode 100644 apps/plugins/pacbox/z80_internal.h diff --git a/apps/plugin.c b/apps/plugin.c index e7758df51c..7aa30c9ea2 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -410,6 +410,14 @@ static const struct plugin_api rockbox_api = { /* new stuff at the end, sort into place next time the API gets incompatible */ + +#if CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IPOD_4G_PAD + /* NOTE: This is already in the plugin api for the H100 - but we put it + at the end for other targets to keep the plugin api compatible */ + button_hold, +#endif + /* options */ + set_option, }; int plugin_load(const char* plugin, void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index df23ed1c00..9ebe31f806 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -99,7 +99,7 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 11 +#define PLUGIN_API_VERSION 12 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -476,6 +476,16 @@ struct plugin_api { /* new stuff at the end, sort into place next time the API gets incompatible */ +#if CONFIG_KEYPAD == IRIVER_H300_PAD || CONFIG_KEYPAD == IPOD_4G_PAD + /* NOTE: This is already in the plugin api for the H100 - but we put it + at the end for other targets to keep the plugin api compatible */ + bool (*button_hold)(void); +#endif + /* options */ + bool (*set_option)(const char* string, void* variable, + enum optiontype type, const struct opt_items* options, + int numoptions, void (*function)(int)); + }; /* plugin header */ diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile index 8c72294709..b591432646 100644 --- a/apps/plugins/Makefile +++ b/apps/plugins/Makefile @@ -77,6 +77,12 @@ ifneq (-DIRIVER_IFP7XX,$(TARGET)) endif endif +# For all the colour targets and iriver H1x0 +ifneq (,$(strip $(foreach tgt,IPOD_VIDEO IPOD_NANO IPOD_COLOR IRIVER \ + IAUDIO_X5 GIGABEAT,$(findstring $(tgt),$(TARGET))))) + SUBDIRS += pacbox +endif + .PHONY: $(SUBDIRS) all: $(BUILDDIR)/libplugin.a $(ROCKS) $(SUBDIRS) $(DEPFILE) diff --git a/apps/plugins/pacbox/Makefile b/apps/plugins/pacbox/Makefile new file mode 100644 index 0000000000..817c6d451a --- /dev/null +++ b/apps/plugins/pacbox/Makefile @@ -0,0 +1,113 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ + -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) -I$(BUILDDIR) +CFLAGS = $(INCLUDES) $(GCCOPTS) -O2 $(TARGET) $(EXTRA_DEFINES) \ + -DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN + + +ifdef APPEXTRA + INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA))) +endif + +LINKFILE := $(OBJDIR)/link.lds +DEPFILE = $(OBJDIR)/dep-pacbox +SRC = arcade.c pacbox.c hardware.c z80.c + +SOURCES = $(SRC) +OBJS := $(SRC:%.c=$(OBJDIR)/%.o) +DIRS = . + +LDS := ../plugin.lds +OUTPUT = $(OUTDIR)/pacbox.rock + +all: $(OUTPUT) + +ifndef SIMVER +$(OBJDIR)/pacbox.elf: $(OBJS) $(LINKFILE) + @echo "LD "`basename $@` + @$(CC) $(GCCOPTS) -O -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc \ + -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/pacbox.map + +$(OUTPUT): $(OBJDIR)/pacbox.elf + @echo "OBJCOPY "`basename $@` + @$(OC) -O binary $< $@ +else + +ifeq ($(SIMVER), x11) +################################################### +# This is the X11 simulator version + +$(OUTPUT): $(OBJS) + @echo "LD $<" + @$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@ +ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) +# 'x' must be kept or you'll have "Win32 error 5" +# $ fgrep 5 /usr/include/w32api/winerror.h | head -1 +# #define ERROR_ACCESS_DENIED 5L +else + @chmod -x $@ +endif + +else # end of x11-simulator +ifeq ($(SIMVER), sdl) +################################################### +# This is the SDL simulator version + +$(OUTPUT): $(OBJS) + @echo "LD $<" + @$(CC) $(CFLAGS) -shared $(OBJS) -L$(BUILDDIR) -lplugin -o $@ +ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) +# 'x' must be kept or you'll have "Win32 error 5" +# $ fgrep 5 /usr/include/w32api/winerror.h | head -1 +# #define ERROR_ACCESS_DENIED 5L +else + @chmod -x $@ +endif + +else # end of sdl-simulator +################################################### +# This is the win32 simulator version +DLLTOOLFLAGS = --export-all +DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin + +$(OUTPUT): $(OBJS) + @echo "DLL "`basename $@` + @$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS) + @$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \ + $(BUILDDIR)/libplugin.a -o $@ +ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) +# 'x' must be kept or you'll have "Win32 error 5" +# $ fgrep 5 /usr/include/w32api/winerror.h | head -1 +# #define ERROR_ACCESS_DENIED 5L +else + @chmod -x $@ +endif +endif # end of win32-simulator +endif +endif # end of simulator section + + +include $(TOOLSDIR)/make.inc + +# MEMORYSIZE should be passed on to this makefile with the chosen memory size +# given in number of MB +$(LINKFILE): $(LDS) + @echo "build "`basename $@` + @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) \ + $(DEFINES) -E -P - >$@ + +clean: + @echo "cleaning pacbox" + @rm -rf $(OBJDIR)/pacbox + @rm -f $(OBJDIR)/pacbox.* $(DEPFILE) + +-include $(DEPFILE) + diff --git a/apps/plugins/pacbox/arcade.c b/apps/plugins/pacbox/arcade.c new file mode 100644 index 0000000000..e7bf124700 --- /dev/null +++ b/apps/plugins/pacbox/arcade.c @@ -0,0 +1,577 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "arcade.h" +#include "hardware.h" +#include +#include "plugin.h" + +extern struct plugin_api* rb; + +#ifndef HAVE_LCD_COLOR +/* Convert RGB888 to 2-bit greyscale - logic taken from bmp2rb.c */ +static fb_data rgb_to_gray(unsigned int r, unsigned int g, unsigned int b) +{ + int brightness = ((3*r + 6*g + b) / 10); + return ((brightness & 0xc0) >> 6); +} +#endif + +unsigned char color_data_[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x01, 0x0c, 0x0f, + 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x0c, 0x0b, 0x0e, + 0x00, 0x0c, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x0f, 0x00, 0x07, 0x0c, 0x02, + 0x00, 0x09, 0x06, 0x0f, 0x00, 0x0d, 0x0c, 0x0f, + 0x00, 0x05, 0x03, 0x09, 0x00, 0x0f, 0x0b, 0x00, + 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x01, + 0x00, 0x0f, 0x0b, 0x0e, 0x00, 0x0e, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char palette_data_[0x20] = { + 0x00, 0x07, 0x66, 0xef, 0x00, 0xf8, 0xea, 0x6f, + 0x00, 0x3f, 0x00, 0xc9, 0x38, 0xaa, 0xaf, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +enum { + Normal = 0x00, + FlipY = 0x01, + FlipX = 0x02, + FlipXY = 0x03 +}; + +fb_data palette[256]; /* Color palette */ +int vchar_to_x_[1024]; +int vchar_to_y_[1024]; + +void init_PacmanMachine(int dip) +{ + int i; + + /* Initialize the CPU and the RAM */ + z80_reset(); + rb->memset( &ram_[0x4000], 0xFF, 0x1000 ); + + /* Initialize parameters */ + port1_ = 0xFF; + port2_ = 0xFF; + coin_counter_ = 0; + + /* Reset the machine */ + reset_PacmanMachine(); + + /* Set the DIP switches to a default configuration */ + setDipSwitches( dip ); + + /* Initialize the video character translation tables: video memory has a + very peculiar arrangement in Pacman so we precompute a few tables to + move around faster */ + + for( i=0x000; i<0x400; i++ ) { + int x, y; + + if( i < 0x040 ) { + x = 29 - (i & 0x1F); + y = 34 + (i >> 5); + } + else if( i >= 0x3C0 ) { + x = 29 - (i & 0x1F); + y = ((i-0x3C0) >> 5); + } + else { + x = 27 - ((i-0x40) >> 5); + y = 2 + ((i-0x40) & 0x1F); + } + vchar_to_x_[i] = x; + vchar_to_y_[i] = y; + if( (y >= 0) && (y < 36) && (x >= 0) && (x < 28) ) + vchar_to_i_[i] = y*28 + x; + else + vchar_to_i_[i] = 0x3FF; + } +} + +void reset_PacmanMachine(void) +{ + int i; + + z80_reset(); + output_devices_ = 0; + interrupt_vector_ = 0; + + rb->memset( ram_+0x4000, 0, 0x1000 ); + rb->memset( color_mem_, 0, sizeof(color_mem_) ); + rb->memset( video_mem_, 0, sizeof(video_mem_) ); + rb->memset( dirty_, 0, sizeof(dirty_) ); + + for( i=0; i<8; i++ ) { + sprites_[i].color = 0; + sprites_[i].x = ScreenWidth; + } +} + +/* + Run the machine for one frame. +*/ +int run(void) +{ + /* Run until the CPU has executed the number of cycles per frame + (the function returns the number of "extra" cycles spent by the + last instruction but that is not really important here) */ + + unsigned extraCycles = z80_run( CpuCyclesPerFrame ); + + /* Reset the CPU cycle counter to make sure it doesn't overflow, + also take into account the extra cycles from the previous run */ + + setCycles( extraCycles ); + + /* If interrupts are enabled, force a CPU interrupt with the vector + set by the program */ + + if( output_devices_ & InterruptEnabled ) { + z80_interrupt( interrupt_vector_ ); + } + + return 0; +} + +/** Returns the status of the coin lockout door. */ +unsigned char getCoinLockout(void) { + return output_devices_ & CoinLockout ? 1 : 0; +} + +static void decodeCharByte( unsigned char b, unsigned char * charbuf, int charx, int chary, int charwidth ) +{ + int i; + + for( i=3; i>=0; i-- ) { + charbuf[charx+(chary+i)*charwidth] = (b & 1) | ((b >> 3) & 2); + b >>= 1; + } +} + +static void decodeCharLine( unsigned char * src, unsigned char * charbuf, int charx, int chary, int charwidth ) +{ + int x; + + for( x=7; x>=0; x-- ) { + decodeCharByte( *src++, charbuf, x+charx, chary, charwidth ); + } +} + +static void decodeCharSet( unsigned char * mem, unsigned char * charset ) +{ + int i; + + for( i=0; i<256; i++ ) { + unsigned char * src = mem + 16*i; + unsigned char * dst = charset + 64*i; + + decodeCharLine( src, dst, 0, 4, 8 ); + decodeCharLine( src+8, dst, 0, 0, 8 ); + } +} + +static void decodeSprites( unsigned char * mem, unsigned char * sprite_data ) +{ + int i; + + for( i=0; i<64; i++ ) { + unsigned char * src = mem + i*64; + unsigned char * dst = sprite_data + 256*i; + + decodeCharLine( src , dst, 8, 12, 16 ); + decodeCharLine( src+ 8, dst, 8, 0, 16 ); + decodeCharLine( src+16, dst, 8, 4, 16 ); + decodeCharLine( src+24, dst, 8, 8, 16 ); + decodeCharLine( src+32, dst, 0, 12, 16 ); + decodeCharLine( src+40, dst, 0, 0, 16 ); + decodeCharLine( src+48, dst, 0, 4, 16 ); + decodeCharLine( src+56, dst, 0, 8, 16 ); + } +} + +/* + Decode one byte from the encoded color palette. + + An encoded palette byte contains RGB information bit-packed as follows: + + bit: 7 6 5 4 3 2 1 0 + color: b b g g g r r r +*/ +static unsigned decodePaletteByte( unsigned char value ) +{ + unsigned bit0, bit1, bit2; + unsigned red, green, blue; + + bit0 = (value >> 0) & 0x01; + bit1 = (value >> 1) & 0x01; + bit2 = (value >> 2) & 0x01; + red = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = (value >> 3) & 0x01; + bit1 = (value >> 4) & 0x01; + bit2 = (value >> 5) & 0x01; + green = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + bit0 = 0; + bit1 = (value >> 6) & 0x01; + bit2 = (value >> 7) & 0x01; + blue = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; + + return (blue << 16 ) | (green << 8) | red; +} + +void decodeROMs(void) +{ + unsigned decoded_palette[0x20]; + unsigned c; + + int i; + + decodeCharSet( charset_rom_, charmap_ ); + decodeSprites( spriteset_rom_, spritemap_ ); + + for( i=0x00; i<0x20; i++ ) { + decoded_palette[i] = decodePaletteByte( palette_data_[i] ); + } + for( i=0; i<256; i++ ) { + c = decoded_palette[ color_data_[i] & 0x0F ]; +#ifdef HAVE_LCD_COLOR + palette[i] = LCD_RGBPACK((unsigned char) (c), + (unsigned char) (c >> 8), + (unsigned char) (c >> 16)); +#else + palette[i] = rgb_to_gray(c, c >> 8, c >> 16); +#endif + } +} + +void getDeviceInfo( enum InputDevice device, unsigned char * mask, unsigned char ** port ) +{ + static unsigned char MaskInfo[] = { + 0x01 , // Joy1_Up + 0x02 , // Joy1_Left + 0x04 , // Joy1_Right + 0x08 , // Joy1_Down + 0x10 , // Switch_RackAdvance + 0x20 , // CoinSlot_1 + 0x40 , // CoinSlot_2 + 0x80 , // Switch_AddCredit + 0x01 , // Joy2_Up + 0x02 , // Joy2_Left + 0x04 , // Joy2_Right + 0x08 , // Joy2_Down + 0x10 , // Switch_Test + 0x20 , // Key_OnePlayer + 0x40 , // Key_TwoPlayers + 0x80 // Switch_CocktailMode + }; + + *mask = MaskInfo[device]; + + switch( device ) { + case Joy1_Up: + case Joy1_Left: + case Joy1_Right: + case Joy1_Down: + case Switch_RackAdvance: + case CoinSlot_1: + case CoinSlot_2: + case Switch_AddCredit: + *port = &port1_; + break; + case Joy2_Up: + case Joy2_Left: + case Joy2_Right: + case Joy2_Down: + case Switch_Test: + case Key_OnePlayer: + case Key_TwoPlayers: + case Switch_CocktailMode: + *port = &port2_; + break; + default: + *port = 0; + break; + } +} + +enum InputDeviceMode getDeviceMode( enum InputDevice device ) +{ + unsigned char mask; + unsigned char * port; + + getDeviceInfo( device, &mask, &port ); + + return (*port & mask) == 0 ? DeviceOn : DeviceOff; +} + +/* + Fire an input event, telling the emulator for example + that the joystick has been released from the down position. +*/ +void setDeviceMode( enum InputDevice device, enum InputDeviceMode mode ) +{ + if( (getCoinLockout() == 0) && ((device == CoinSlot_1)||(device == CoinSlot_2)||(device == Switch_AddCredit)) ) { + // Coin slots are locked, ignore command and exit + return; + } + + unsigned char mask; + unsigned char * port; + + getDeviceInfo( device, &mask, &port ); + + if( mode == DeviceOn ) + *port &= ~mask; + else if( mode == DeviceOff ) + *port |= mask; + else if( mode == DeviceToggle ) + *port ^= mask; +} + +void setDipSwitches( unsigned value ) { + dip_switches_ = (unsigned char) value; + + setDeviceMode( Switch_RackAdvance, value & DipRackAdvance_Auto ? DeviceOn : DeviceOff ); + setDeviceMode( Switch_Test, value & DipMode_Test ? DeviceOn : DeviceOff ); + setDeviceMode( Switch_CocktailMode, value & DipCabinet_Cocktail ? DeviceOn : DeviceOff ); +} + +unsigned getDipSwitches(void) { + unsigned result = dip_switches_; + + if( getDeviceMode(Switch_RackAdvance) == DeviceOn ) result |= DipRackAdvance_Auto; + if( getDeviceMode(Switch_Test) == DeviceOn ) result |= DipMode_Test; + if( getDeviceMode(Switch_CocktailMode) == DeviceOn ) result |= DipCabinet_Cocktail; + + return result; +} + +static inline void drawChar( unsigned char * buffer, int index, int ox, int oy, int color ) +{ + buffer += ox + oy*224; // Make the buffer point to the character position + index *= 64; // Make the index point to the character offset into the character table + color = (color & 0x3F)*4; + int x,y; + + if( output_devices_ & FlipScreen ) { + // Flip character + buffer += 7*ScreenWidth; + for( y=0; y<8; y++ ) { + for( x=7; x>=0; x-- ) { + buffer[x] = charmap_[ index++ ] + color; + } + buffer -= ScreenWidth; // Go to the next line + } + } + else { + for( y=0; y<8; y++ ) { + for( x=0; x<=7; x++ ) { + buffer[x] = charmap_[ index++ ] + color; + } + buffer += ScreenWidth; // Go to the next line + } + } +} + +inline void drawSprite( unsigned char * buffer, int index ) +{ + struct PacmanSprite ps = sprites_[index]; + int x,y; + + // Exit now if sprite not visible at all + if( (ps.color == 0) || (ps.x >= ScreenWidth) || (ps.y < 16) || (ps.y >= (ScreenHeight-32)) ) { + return; + } + + // Clip the sprite coordinates to cut the parts that fall off the screen + int start_x = (ps.x < 0) ? 0 : ps.x; + int end_x = (ps.x < (ScreenWidth-16)) ? ps.x+16 : ScreenWidth; + + // Prepare variables for drawing + int color = (ps.color & 0x3F)*4; + unsigned char * spritemap_base = spritemap_ + ((ps.n & 0x3F)*256); + + buffer += ScreenWidth*ps.y; + + // Draw the 16x16 sprite + if( ps.mode == 0 ) { // Normal + // Draw the 16x16 sprite + for( y=0; y<16; y++ ) { + char* s = &spritemap_base[start_x-ps.x+y*16]; + for( x=start_x; x=0; y-=CharHeight ) { + for( x=ScreenWidth-CharWidth; x>=0; x-=CharWidth ) { + if (*dirty) { + drawChar( buffer, *video++, x, y, *color++ ); + *(dirty++)=0; + changed=true; + } else { + dirty++; + video++; + color++; + } + } + } + } + else { + for( y=0; y=0; i-- ) { + drawSprite( buffer, i ); + } +} + +/* Enables/disables the speed hack. */ +int setSpeedHack( int enabled ) +{ + int result = 0; + + if( enabled ) { + if( (ram_[0x180B] == 0xBE) && (ram_[0x1FFD] == 0x00) ) { + // Patch the ROM to activate the speed hack + ram_[0x180B] = 0x01; // Activate speed hack + ram_[0x1FFD] = 0xBD; // Fix ROM checksum + + result = 1; + } + } + else { + if( (ram_[0x180B] == 0x01) && (ram_[0x1FFD] == 0xBD) ) { + // Restore the patched ROM locations + ram_[0x180B] = 0xBE; + ram_[0x1FFD] = 0x00; + + result = 1; + } + } + + return result; +} diff --git a/apps/plugins/pacbox/arcade.h b/apps/plugins/pacbox/arcade.h new file mode 100644 index 0000000000..5de2517e80 --- /dev/null +++ b/apps/plugins/pacbox/arcade.h @@ -0,0 +1,199 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef ARCADE_H_ +#define ARCADE_H_ + +#include "plugin.h" +#include "z80.h" +#include "hardware.h" + +extern fb_data palette[256]; /* Color palette in native Rockbox format */ + +/** + Pacman sprite properties. + + This information is only needed by applications that want to do their own + sprite rendering, as the renderVideo() function already draws the sprites. + + @see PacmanMachine::renderVideo +*/ + +/** Machine hardware data */ +enum { + ScreenWidth = 224, + ScreenHeight = 288, + ScreenWidthChars = 28, + ScreenHeightChars = 36, + CharWidth = 8, + CharHeight = 8, + VideoFrequency = 60, + CpuClock = 3072000, + SoundClock = 96000, // CPU clock divided by 32 + CpuCyclesPerFrame = CpuClock / VideoFrequency +}; + +/** Input devices and switches */ +enum InputDevice { + Joy1_Up = 0, + Joy1_Left, + Joy1_Right, + Joy1_Down, + Switch_RackAdvance, + CoinSlot_1, + CoinSlot_2, + Switch_AddCredit, + Joy2_Up, + Joy2_Left, + Joy2_Right, + Joy2_Down, + Switch_Test, + Key_OnePlayer, + Key_TwoPlayers, + Switch_CocktailMode +}; + +/** Input device mode */ +enum InputDeviceMode { + DeviceOn, + DevicePushed = DeviceOn, + DeviceOff, + DeviceReleased = DeviceOff, + DeviceToggle +}; + +/** DIP switches */ +enum { + DipPlay_Free = 0x00, // Coins per play + DipPlay_OneCoinOneGame = 0x01, + DipPlay_OneCoinTwoGames = 0x02, + DipPlay_TwoCoinsOneGame = 0x03, + DipPlay_Mask = 0x03, + DipLives_1 = 0x00, // Lives per game + DipLives_2 = 0x04, + DipLives_3 = 0x08, + DipLives_5 = 0x0C, + DipLives_Mask = 0x0C, + DipBonus_10000 = 0x00, // Bonus life + DipBonus_15000 = 0x10, + DipBonus_20000 = 0x20, + DipBonus_None = 0x30, + DipBonus_Mask = 0x30, + DipDifficulty_Normal = 0x40, // Difficulty + DipDifficulty_Hard = 0x00, + DipDifficulty_Mask = 0x40, + DipGhostNames_Normal = 0x80, // Ghost names + DipGhostNames_Alternate = 0x00, + DipGhostNames_Mask = 0x80, + DipMode_Play = 0x0000, // Play/test mode + DipMode_Test = 0x0100, + DipMode_Mask = 0x0100, + DipCabinet_Upright = 0x0000, // Cabinet upright/cocktail + DipCabinet_Cocktail = 0x0200, + DipCabinet_Mask = 0x0200, + DipRackAdvance_Off = 0x0000, // Automatic level advance + DipRackAdvance_Auto = 0x0400, + DipRackAdvance_Mask = 0x0400 +}; + +void init_PacmanMachine(int dip); +int run(void); +void reset_PacmanMachine(void); +void decodeROMs(void); + +/** + Tells the emulator that the status of an input device has changed. +*/ +void setDeviceMode( enum InputDevice device, enum InputDeviceMode mode ); + +/** + Returns the value of the DIP switches. +*/ +unsigned getDipSwitches(void); + +/** + Sets the value of the DIP switches that control several game settings + (see the Dip... constants above). + + Most of the DIP switches are read at program startup and take effect + only after a machine reset. +*/ +void setDipSwitches( unsigned value ); + +/** + Draws the current video into the specified buffer. + + The buffer must be at least 224*288 bytes long. Pixels are stored in + left-to-right/top-to-bottom order starting from the upper left corner. + There is one byte per pixel, containing an index into the color palette + returned by getPalette(). + + It's up to the application to display the buffer to the user. The + code might look like this: +
+
+    @@    unsigned char video_buffer[ PacmanMachine::ScreenWidth * PacmanMachine::ScreenHeight ];
+    @@    unsigned char * vbuf = video_buffer;
+    @@    const unsigned * palette = arcade.getPalette();
+    @@
+    @@    arcade.renderVideo( vbuf );
+    @@
+    @@    for( int y=0; y> 8) & 0xFF;
+    @@            unsigned char blue = (color >> 16) & 0xFF;
+    @@
+    @@            setPixel( x, y, red, green, blue );
+    @@        }
+    @@    }
+    
+
+ +*/ +bool renderBackground( unsigned char * buffer ); +void renderSprites( unsigned char * buffer ); + +/** + Enables/disables a common speed hack that allows Pacman to + move four times faster than the ghosts. + + @param enabled true to enabled the hack, false to disable + + @return 0 if successful, otherwise the patch could not be applied + (probably because the loaded ROM set does not support it) +*/ +int setSpeedHack( int enabled ); + +/* Implementation of the Z80 Environment interface */ +unsigned char readByteHigh( unsigned addr ); + +void writeByte( unsigned, unsigned char ); + +unsigned char readPort( unsigned port ); + +void writePort( unsigned, unsigned char ); + +#endif // ARCADE_H_ diff --git a/apps/plugins/pacbox/hardware.c b/apps/plugins/pacbox/hardware.c new file mode 100644 index 0000000000..3cc4858e43 --- /dev/null +++ b/apps/plugins/pacbox/hardware.c @@ -0,0 +1,197 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "hardware.h" + +extern struct plugin_api* rb; + +/* The main data for Pacman */ + +unsigned char ram_[20*1024] IBSS_ATTR; // ROM (16K) and RAM (4K) +unsigned char charset_rom_[4*1024] IBSS_ATTR; // Character set ROM (4K) +unsigned char spriteset_rom_[4*1024] IBSS_ATTR; // Sprite set ROM (4K) +unsigned char dirty_[1024] IBSS_ATTR; +unsigned char video_mem_[1024] IBSS_ATTR; // Video memory (1K) +unsigned char color_mem_[1024] IBSS_ATTR; // Color memory (1K) +unsigned char charmap_[256*8*8]; /* Character data for 256 8x8 characters */ +unsigned char spritemap_[64*16*16]; /* Sprite data for 64 16x16 sprites */ +unsigned char output_devices_ IBSS_ATTR; /* Output flip-flops set by the game program */ +unsigned char interrupt_vector_ IBSS_ATTR; +unsigned coin_counter_ IBSS_ATTR; +unsigned char port1_ IBSS_ATTR; +unsigned char port2_ IBSS_ATTR; +unsigned char dip_switches_ IBSS_ATTR; + +/* Internal tables and structures for faster access to data */ +struct PacmanSprite sprites_[8]; /* Sprites */ +short vchar_to_i_[1024]; + + +/* + For Z80 Environment: write a byte to memory. +*/ +void writeByte( unsigned addr, unsigned char b ) +{ + addr &= 0x7FFF; + + if( addr < 0x4000 ) { + // This is a ROM address, do not write into it! + } + else if( addr < 0x4400 ) { + // Video memory + if (ram_[addr] != b) { + int x = vchar_to_i_[addr-0x4000]; + ram_[addr] = b; + dirty_[x] = 1; + video_mem_[x] = b; + } + } + else if( addr < 0x4800 ) { + // Color memory + if (ram_[addr] != b) { + int x = vchar_to_i_[addr-0x4400]; + ram_[addr] = b; + dirty_[x] = 1; + color_mem_[x] = b; + } + } + else if( addr < 0x4FF0 ) { + // Standard memory + ram_[addr] = b; + } + else if( addr < 0x5000 ) { + // Sprites + ram_[addr] = b; + + unsigned idx = (addr - 0x4FF0) / 2; + + if( addr & 1 ) { + sprites_[ idx ].color = b; + } + else { + sprites_[ idx ].n = b >> 2; + sprites_[ idx ].mode = b & 0x03; + } + } + else { + // Memory mapped ports + switch( addr ) { + case 0x5000: + // Interrupt enable + setOutputFlipFlop( InterruptEnabled, b & 0x01 ); + break; + case 0x5001: + // Sound enable + setOutputFlipFlop( SoundEnabled, b & 0x01 ); + break; + case 0x5002: + // Aux board enable? + break; + case 0x5003: + // Flip screen + setOutputFlipFlop( FlipScreen, b & 0x01 ); + break; + case 0x5004: + // Player 1 start light + setOutputFlipFlop( PlayerOneLight, b & 0x01 ); + break; + case 0x5005: + // Player 2 start light + setOutputFlipFlop( PlayerTwoLight, b & 0x01 ); + break; + case 0x5006: + // Coin lockout: bit 0 is used to enable/disable the coin insert slots + // (0=disable). + // The coin slot is enabled at startup and (temporarily) disabled when + // the maximum number of credits (99) is inserted. + setOutputFlipFlop( CoinLockout, b & 0x01 ); + break; + case 0x5007: + // Coin meter (coin counter incremented on 0/1 edge) + if( (output_devices_ & CoinMeter) == 0 && (b & 0x01) != 0 ) + coin_counter_++; + setOutputFlipFlop( CoinMeter, b & 0x01 ); + break; + case 0x50c0: + // Watchdog reset + break; + default: + if( addr >= 0x5040 && addr < 0x5060 ) { + // Sound registers + //SOUND sound_chip_.setRegister( addr-0x5040, b ); + } + else if( addr >= 0x5060 && addr < 0x5070 ) { + // Sprite coordinates, x/y pairs for 8 sprites + unsigned idx = (addr-0x5060) / 2; + + if( addr & 1 ) { + sprites_[ idx ].y = 272 - b + 1; + } + else { + sprites_[ idx ].x = 240 - b - 1; + + if( idx <= 2 ) { + // In Pacman the first few sprites must be further offset + // to the left to get a correct display (is this a hack?) + sprites_[ idx ].x -= 1; + } + } + } + break; + } + } +} + +/* + For Z80 Environment: read from a port. + + Note: all ports in Pacman are memory mapped so they are read with readByte(). +*/ +unsigned char readPort( unsigned port ) +{ + (void)port; + return 0; +} + +/* + For Z80 Environment: write to a port. +*/ +void writePort( unsigned addr, unsigned char b ) +{ + if( addr == 0 ) { + // Sets the interrupt vector for the next CPU interrupt + interrupt_vector_ = b; + } +} + +void setOutputFlipFlop( unsigned char bit, unsigned char value ) +{ + if( value ) { + output_devices_ |= bit; + } + else { + output_devices_ &= ~bit; + } +} diff --git a/apps/plugins/pacbox/hardware.h b/apps/plugins/pacbox/hardware.h new file mode 100644 index 0000000000..9b225ad1a5 --- /dev/null +++ b/apps/plugins/pacbox/hardware.h @@ -0,0 +1,141 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _HARDWARE_H +#define _HARDWARE_H + +extern unsigned char ram_[20*1024]; // ROM (16K) and RAM (4K) +extern unsigned char charset_rom_[4*1024]; // Character set ROM (4K) +extern unsigned char spriteset_rom_[4*1024]; // Sprite set ROM (4K) +extern unsigned char dirty_[1024]; +extern unsigned char video_mem_[1024]; // Video memory (1K) +extern unsigned char color_mem_[1024]; // Color memory (1K) +extern unsigned char charmap_[256*8*8]; /* Character data for 256 8x8 characters */ +extern unsigned char spritemap_[64*16*16]; /* Sprite data for 64 16x16 sprites */ +extern unsigned char output_devices_; /* Output flip-flops set by the game program */ +extern unsigned char interrupt_vector_; +extern unsigned coin_counter_; +extern unsigned char port1_; +extern unsigned char port2_; +extern unsigned char dip_switches_; + +/* Output flip-flops */ +enum { + FlipScreen = 0x01, + PlayerOneLight = 0x02, + PlayerTwoLight = 0x04, + InterruptEnabled = 0x08, + SoundEnabled = 0x10, + CoinLockout = 0x20, + CoinMeter = 0x40, + AuxBoardEnabled = 0x80 +}; + +struct PacmanSprite +{ + int mode; /** Display mode (normal or flipped) */ + int x; /** X coordinate */ + int y; /** Y coordinate */ + int n; /** Shape (from 0 to 63) */ + int color; /** Base color (0=not visible) */ +}; + +/* Internal tables and structures for faster access to data */ +extern struct PacmanSprite sprites_[8]; /* Sprites */ +extern short vchar_to_i_[1024]; + +void writeByte(unsigned addr, unsigned char b); +unsigned char readPort( unsigned port ); +void writePort( unsigned addr, unsigned char b ); +void setOutputFlipFlop( unsigned char bit, unsigned char value ); + +/* + For Z80 Environment: read a byte from high memory addresses (i.e. the + memory-mapped registers) +*/ +static inline unsigned char readByte( unsigned addr ) +{ + addr &= 0xFFFF; + + if (addr < sizeof(ram_)) + return ram_[addr]; + + // Address is not in RAM, check to see if it's a memory mapped register + switch( addr & 0xFFC0 ) { + // IN0 + case 0x5000: + // bit 0 : up + // bit 1 : left + // bit 2 : right + // bit 3 : down + // bit 4 : switch: advance to next level + // bit 5 : coin 1 + // bit 6 : coin 2 + // bit 7 : credit (same as coin but coin counter is not incremented) + return port1_; + // IN1 + case 0x5040: + // bit 0 : up (2nd player) + // bit 1 : left (2nd player) + // bit 2 : right (2nd player) + // bit 3 : down (2nd player) + // bit 4 : switch: rack test -> 0x10=off, 0=on + // bit 5 : start 1 + // bit 6 : start 2 + // bit 7 : cabinet -> 0x80=upright, 0x00=table + return port2_; + // DSW1 + case 0x5080: + // bits 0,1 : coinage -> 0=free play, 1=1 coin/play, 2=1 coin/2 play, 3=2 coin/1 play + // bits 2,3 : lives -> 0x0=1, 0x4=2, 0x8=3, 0xC=5 + // bits 4,5 : bonus life -> 0=10000, 0x10=15000, 0x20=20000, 0x30=none + // bit 6 : jumper pad: difficulty -> 0x40=normal, 0=hard + // bit 7 : jumper pad: ghost name -> 0x80=normal, 0=alternate + return dip_switches_; + // Watchdog reset + case 0x50C0: + break; + } + + return 0xFF; +} + +/* Reads a 16 bit word from memory at the specified address. */ +static inline unsigned readWord( unsigned addr ) { + addr &= 0xFFFF; + + if (addr < (sizeof(ram_)-1)) { + return ram_[addr] | ((ram_[addr+1]) << 8); + } else { + return readByte(addr) | (((unsigned)readByte(addr+1)) << 8); + } +} + +/* Writes a 16 bit word to memory at the specified address. */ +static inline void writeWord( unsigned addr, unsigned value ) { + writeByte( addr, value & 0xFF ); + writeByte( addr+1, (value >> 8) & 0xFF ); +} + +#endif diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c new file mode 100644 index 0000000000..b8625eead6 --- /dev/null +++ b/apps/plugins/pacbox/pacbox.c @@ -0,0 +1,534 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "arcade.h" + +PLUGIN_HEADER + +#ifdef USE_IRAM +extern char iramcopy[]; +extern char iramstart[]; +extern char iramend[]; +extern char iedata[]; +extern char iend[]; +#endif + +/* How many video frames (out of a possible 60) we display each second */ +#define FPS 20 + +#if CONFIG_KEYPAD == IPOD_4G_PAD + +#define PACMAN_UP BUTTON_RIGHT +#define PACMAN_DOWN BUTTON_LEFT +#define PACMAN_LEFT BUTTON_MENU +#define PACMAN_RIGHT BUTTON_PLAY +#define PACMAN_1UP BUTTON_SELECT +#define PACMAN_COIN BUTTON_SELECT + +#elif CONFIG_KEYPAD == IRIVER_H100_PAD || CONFIG_KEYPAD == IRIVER_H300_PAD + +#define PACMAN_UP BUTTON_RIGHT +#define PACMAN_DOWN BUTTON_LEFT +#define PACMAN_LEFT BUTTON_UP +#define PACMAN_RIGHT BUTTON_DOWN +#define PACMAN_1UP BUTTON_SELECT +#define PACMAN_2UP BUTTON_ON +#define PACMAN_COIN BUTTON_REC +#define PACMAN_MENU BUTTON_MODE + +#elif CONFIG_KEYPAD == GIGABEAT_PAD + +#define PACMAN_UP BUTTON_UP +#define PACMAN_DOWN BUTTON_DOWN +#define PACMAN_LEFT BUTTON_LEFT +#define PACMAN_RIGHT BUTTON_RIGHT +#define PACMAN_1UP BUTTON_SELECT +#define PACMAN_2UP BUTTON_POWER +#define PACMAN_COIN BUTTON_A +#define PACMAN_MENU BUTTON_MENU + +#elif CONFIG_KEYPAD == IAUDIO_X5_PAD + +#define PACMAN_UP BUTTON_RIGHT +#define PACMAN_DOWN BUTTON_LEFT +#define PACMAN_LEFT BUTTON_UP +#define PACMAN_RIGHT BUTTON_DOWN +#define PACMAN_1UP BUTTON_SELECT +#define PACMAN_2UP BUTTON_POWER +#define PACMAN_COIN BUTTON_REC +#define PACMAN_MENU BUTTON_PLAY + +#endif + +#if (LCD_HEIGHT >= 288) +#define XOFS ((LCD_WIDTH-224)/2) +#define YOFS ((LCD_HEIGHT-288)/2) +#elif (LCD_WIDTH >= 288) +#define XOFS ((LCD_WIDTH-288)/2) +#define YOFS ((LCD_HEIGHT-224)/2) +#elif (LCD_WIDTH >= 220) +#define XOFS ((LCD_WIDTH-(288*3/4))/2) +#define YOFS ((LCD_HEIGHT-(224*3/4))/2) +#elif (LCD_WIDTH >= 144) +#define XOFS ((LCD_WIDTH-288/2)/2) +#define YOFS ((LCD_HEIGHT-224/2)/2) +#endif + +struct plugin_api* rb; + +unsigned framesPerSecond = VideoFrequency; +unsigned long frame_counter = 0; + +struct pacman_settings { + int difficulty; + int numlives; + int bonus; + int ghostnames; + int showfps; +}; + +struct pacman_settings settings; + +bool loadFile( const char * name, unsigned char * buf, int len ) +{ + char filename[MAX_PATH]; + + rb->snprintf(filename,sizeof(filename),"/.rockbox/pacman/%s",name); + + int fd = rb->open( filename, O_RDONLY); + + if( fd < 0 ) { + return false; + } + + int n = rb->read( fd, buf, len); + + rb->close( fd ); + + if( n != len ) { + return false; + } + + return true; +} + +bool loadROMS( void ) +{ + bool romsLoaded = false; + + romsLoaded = loadFile( "pacman.6e", ram_, 0x1000) && + loadFile( "pacman.6f", ram_+0x1000, 0x1000) && + loadFile( "pacman.6h", ram_+0x2000, 0x1000) && + loadFile( "pacman.6j", ram_+0x3000, 0x1000) && + loadFile( "pacman.5e", charset_rom_, 0x1000) && + loadFile( "pacman.5f", spriteset_rom_, 0x1000); + + if( romsLoaded ) { + decodeROMs(); + reset_PacmanMachine(); + } + + return romsLoaded; +} + +/* A buffer to render Pacman's 244x288 screen into */ +unsigned char background[ScreenWidth*ScreenHeight] __attribute__ ((aligned (4))); +unsigned char video_buffer[ScreenWidth*ScreenHeight] __attribute__ ((aligned (4))); + +long start_time; +long sleep_counter = 0; +long video_frames = 0; + +int dipDifficulty[] = { DipDifficulty_Normal, DipDifficulty_Hard }; +int dipLives[] = { DipLives_1, DipLives_2, DipLives_3, DipLives_5 }; +int dipBonus[] = { DipBonus_10000, DipBonus_15000, DipBonus_20000, DipBonus_None }; +int dipGhostNames[] = { DipGhostNames_Normal, DipGhostNames_Alternate }; + +int settings_to_dip(struct pacman_settings settings) +{ + return ( DipPlay_OneCoinOneGame | + DipCabinet_Upright | + DipMode_Play | + DipRackAdvance_Off | + + dipDifficulty[settings.difficulty] | + dipLives[settings.numlives] | + dipBonus[settings.bonus] | + dipGhostNames[settings.ghostnames] + ); +} + + + +int pacbox_menu_cb(int key, int m) +{ + (void)m; + switch(key) + { +#ifdef MENU_ENTER2 + case MENU_ENTER2: +#endif + case MENU_ENTER: + key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */ + break; + +#ifdef MENU_ENTER2 + case MENU_ENTER2 | BUTTON_REL: +#endif + case MENU_ENTER | BUTTON_REL: + key = MENU_ENTER; /* fake downpress, next menu doesn't like release */ + break; + } + + return key; +} + +bool pacbox_menu(void) +{ + int m; + int result; + int menu_quit=0; + int new_setting; + bool need_restart = false; + + static const struct opt_items noyes[2] = { + { "No", NULL }, + { "Yes", NULL }, + }; + + static const struct opt_items difficulty_options[2] = { + { "Normal", NULL }, + { "Harder", NULL }, + }; + + static const struct opt_items numlives_options[4] = { + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "5", NULL }, + }; + + static const struct opt_items bonus_options[4] = { + { "10000 points", NULL }, + { "15000 points", NULL }, + { "20000 points", NULL }, + { "No bonus", NULL }, + }; + + static const struct opt_items ghostname_options[2] = { + { "Normal", NULL }, + { "Alternate", NULL }, + }; + + static const struct menu_item items[] = { + { "Difficulty", NULL }, + { "Pacmen Per Game", NULL }, + { "Bonus Life", NULL }, + { "Ghost Names", NULL }, + { "Display FPS", NULL }, + { "Restart", NULL }, + { "Quit", NULL }, + }; + + m = rb->menu_init(items, sizeof(items) / sizeof(*items), + pacbox_menu_cb, NULL, NULL, NULL); + + rb->button_clear_queue(); + + while (!menu_quit) { + result=rb->menu_show(m); + + switch(result) + { + case 0: + new_setting=settings.difficulty; + rb->set_option("Difficulty", &new_setting, INT, + difficulty_options , 2, NULL); + if (new_setting != settings.difficulty) { + settings.difficulty=new_setting; + need_restart=true; + } + break; + case 1: + new_setting=settings.numlives; + rb->set_option("Pacmen Per Game", &new_setting, INT, + numlives_options , 4, NULL); + if (new_setting != settings.numlives) { + settings.numlives=new_setting; + need_restart=true; + } + break; + case 2: + new_setting=settings.bonus; + rb->set_option("Bonus Life", &new_setting, INT, + bonus_options , 4, NULL); + if (new_setting != settings.bonus) { + settings.bonus=new_setting; + need_restart=true; + } + break; + case 3: + new_setting=settings.ghostnames; + rb->set_option("Ghost Names", &new_setting, INT, + ghostname_options , 2, NULL); + if (new_setting != settings.ghostnames) { + settings.ghostnames=new_setting; + need_restart=true; + } + break; + case 4: /* Show FPS */ + rb->set_option("Display FPS",&settings.showfps,INT, noyes, 2, NULL); + break; + case 5: /* Restart */ + need_restart=true; + menu_quit=1; + break; + default: + menu_quit=1; + break; + } + } + + rb->menu_exit(m); + + if (need_restart) { + init_PacmanMachine(settings_to_dip(settings)); + } + + /* Possible results: + exit game + restart game + usb connected + */ + return (result==6); +} + + +/* + Runs the game engine for one frame. +*/ +int gameProc( void ) +{ + int x,y; + int fps; + char str[80]; + int status; + long end_time; + unsigned char* vbuf = video_buffer; + fb_data* dst; + fb_data* next_dst; + + /* Run the machine for one frame (1/60th second) */ + run(); + + frame_counter++; + + /* Check the button status */ + status = rb->button_status(); + +#ifdef PACMAN_MENU + if (status & PACMAN_MENU) { +#else + if (rb->button_hold()) { +#endif + end_time = *rb->current_tick; + x = pacbox_menu(); + rb->lcd_clear_display(); +#ifdef HAVE_REMOTE_LCD + rb->lcd_remote_clear_display(); + rb->lcd_remote_update(); +#endif + if (x == 1) { return 1; } + start_time += *rb->current_tick-end_time; + } + + setDeviceMode( Joy1_Left, (status & PACMAN_LEFT) ? DeviceOn : DeviceOff); + setDeviceMode( Joy1_Right, (status & PACMAN_RIGHT) ? DeviceOn : DeviceOff); + setDeviceMode( Joy1_Up, (status & PACMAN_UP) ? DeviceOn : DeviceOff); + setDeviceMode( Joy1_Down, (status & PACMAN_DOWN) ? DeviceOn : DeviceOff); + setDeviceMode( CoinSlot_1, (status & PACMAN_COIN) ? DeviceOn : DeviceOff); + setDeviceMode( Key_OnePlayer, (status & PACMAN_1UP) ? DeviceOn : DeviceOff); +#ifdef PACMAN_2UP + setDeviceMode( Key_TwoPlayers, (status & PACMAN_2UP) ? DeviceOn : DeviceOff); +#endif + + /* We only update the screen every third frame - Pacman's native + framerate is 60fps, so we are attempting to display 20fps */ + if( (frame_counter % (60/FPS)) == 0) { + + video_frames++; + + /* The following functions render the Pacman screen from the contents + of the video and color ram. We first update the background, and + then draw the Sprites on top. + + Note that we only redraw the parts of the background that have + changed, which is why we need to keep a copy of the background without + the sprites on top. Even with the memcpy, this is faster than redrawing + the whole background. + */ + renderBackground( background ); + rb->memcpy(video_buffer,background,sizeof(video_buffer)); + renderSprites( video_buffer ); + +#ifdef HAVE_LCD_COLOR +#if (LCD_WIDTH >= 224) && (LCD_HEIGHT >= 288) + /* Native resolution = 224x288 */ + (void)next_dst; + dst=&rb->lcd_framebuffer[YOFS*LCD_WIDTH+XOFS]; + for (y=0;y= 288) && (LCD_HEIGHT >= 224) + /* Native resolution - rotated 90 degrees = 288x224 */ + next_dst=&rb->lcd_framebuffer[YOFS*LCD_WIDTH+XOFS+ScreenHeight-1]; + for( y=ScreenHeight-1; y>=0; y-- ) { + dst = (next_dst--); + for( x=0; x= 216) && (LCD_HEIGHT >= 168) + /* 0.75 scaling - display 3 out of 4 pixels = 216x168 + Skipping pixel #2 out of 4 seems to give the most legible display + */ + next_dst=&rb->lcd_framebuffer[YOFS*LCD_WIDTH+XOFS+((ScreenHeight*3)/4)-1]; + for (y=ScreenHeight-1;y >= 0; y--) { + if ((y & 3) != 1) { + dst = (next_dst--); + for (x=0;x= 144) && (LCD_HEIGHT >= 112) + /* 0.5 scaling - display every other pixel = 144x112 */ + next_dst=&rb->lcd_framebuffer[YOFS*LCD_WIDTH+XOFS+ScreenHeight/2-1]; + for (y=(ScreenHeight/2)-1;y >= 0; y--) { + dst = (next_dst--); + for (x=0;x= 144) && (LCD_HEIGHT >= 112) +#if LCD_PIXELFORMAT == VERTICAL_PACKING + /* 0.5 scaling - display every other pixel = 144x112 */ + next_dst=&rb->lcd_framebuffer[YOFS/4*LCD_WIDTH+XOFS+ScreenHeight/2-1]; + for (y=(ScreenHeight/2)-1;y >= 0; y--) { + dst = (next_dst--); + for (x=0;x= 144x112 */ +#endif /* Not Colour */ + + if (settings.showfps) { + fps = (video_frames*HZ*100) / (*rb->current_tick-start_time); + rb->snprintf(str,sizeof(str),"%d.%02d / %d fps ",fps/100,fps%100, + FPS); + rb->lcd_putsxy(0,0,str); + } + + rb->lcd_update(); + +#ifdef SIMULATOR + /* Keep the framerate at Pacman's 60fps */ + end_time = start_time + (video_frames*HZ)/FPS; + while (TIME_BEFORE(*rb->current_tick,end_time)) { + rb->sleep(1); + } +#endif + } + + return 0; +} + +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + (void)parameter; + int status; + + rb = api; + +#ifdef USE_IRAM + rb->memcpy(iramstart, iramcopy, iramend-iramstart); + rb->memset(iedata, 0, iend - iedata); +#endif + +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(true); +#endif + + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(LCD_BLACK); + rb->lcd_clear_display(); + rb->lcd_update(); + + /* Set the default settings (we should load these from a file) */ + settings.difficulty = 0; /* Normal */ + settings.numlives = 2; /* 3 lives */ + settings.bonus = 0; /* 10000 points */ + settings.ghostnames = 0; /* Normal names */ + settings.showfps = 0; /* Do not show FPS */ + + /* Initialise the hardware */ + init_PacmanMachine(settings_to_dip(settings)); + + /* Load the romset */ + if (loadROMS()) { + start_time = *rb->current_tick-1; + do { + status = gameProc(); + } while (!status); + } else { + rb->splash(HZ*2,true,"No ROMs in /.rockbox/pacman/"); + } + +#ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(false); +#endif + + return PLUGIN_OK; +} diff --git a/apps/plugins/pacbox/readme.txt b/apps/plugins/pacbox/readme.txt new file mode 100644 index 0000000000..41fc89ea76 --- /dev/null +++ b/apps/plugins/pacbox/readme.txt @@ -0,0 +1,13 @@ +Pacbox is based on PIE - the Pacman Instructional Emulator written by +Alessandro Scotti. PIE is a Pacman arcade machine emulator licensed +under the GNU GPL and is available from http://www.ascotti.org/ + +PIE is a Windows application written in C++ - all the Windows-specific +code was stripped out and the emulator converted to C for use in +Rockbox. + +The version of PIE used as the basis of the port was v1.11 + + +Dave Chapman +March 2006 diff --git a/apps/plugins/pacbox/z80.c b/apps/plugins/pacbox/z80.c new file mode 100644 index 0000000000..b489682b3a --- /dev/null +++ b/apps/plugins/pacbox/z80.c @@ -0,0 +1,8058 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "hardware.h" +#include "z80.h" +#include "z80_internal.h" + +// Table with parity, sign and zero flags precomputed for each byte value +unsigned char PSZ_[256] = { + Zero|Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, + 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, + 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, + Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, + 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, + Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, + Parity, 0, 0, Parity, 0, Parity, Parity, 0, 0, Parity, Parity, 0, Parity, 0, 0, Parity, + 0, Parity, Parity, 0, Parity, 0, 0, Parity, Parity, 0, 0, Parity, 0, Parity, Parity, 0, + Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, + Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, + Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, + Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, + Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, + Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, + Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, + Sign|Parity, Sign, Sign, Sign|Parity, Sign, Sign|Parity, Sign|Parity, Sign, Sign, Sign|Parity, Sign|Parity, Sign, Sign|Parity, Sign, Sign, Sign|Parity +}; + +// Interrupt flags +enum { + IFF1 = 0x40, // Interrupts enabled/disabled + IFF2 = 0x20, // Copy of IFF1 (used by non-maskable interrupts) + Halted = 0x10 // Internal use: signals that the CPU is halted +}; + +// Implements an opcode +typedef void (OpcodeHandler)(void); + +typedef struct { + OpcodeHandler* handler; + unsigned cycles; +} OpcodeInfo; + +// Implements an opcode for instructions that use the form (IX/IY + b) +typedef void (OpcodeHandlerXY)( unsigned ); + +typedef struct { + OpcodeHandlerXY* handler; + unsigned cycles; +} OpcodeInfoXY; + +/** */ +void do_opcode_xy( OpcodeInfo * ); + +/** */ +unsigned do_opcode_xycb( unsigned xy ); + +unsigned iflags_; // Interrupt mode (bits 0 and 1) and flags +unsigned cycles_; // Number of CPU cycles elapsed so far + + +// Registers +unsigned char B; //@- B register +unsigned char C; //@- C register +unsigned char D; //@- D register +unsigned char E; //@- E register +unsigned char H; //@- H register +unsigned char L; //@- L register +unsigned char A; //@- A register (accumulator) +unsigned char F; //@- Flags register +unsigned char B1; //@- Alternate B register (B') +unsigned char C1; //@- Alternate C register (C') +unsigned char D1; //@- Alternate D register (D') +unsigned char E1; //@- Alternate E register (E') +unsigned char H1; //@- Alternate H register (H') +unsigned char L1; //@- Alternate L register (L') +unsigned char A1; //@- Alternate A register (A') +unsigned char F1; //@- Alternate flags register (F') +unsigned IX; //@- Index register X +unsigned IY; //@- Index register Y +unsigned PC; //@- Program counter +unsigned SP; //@- Stack pointer +unsigned char I; //@- Interrupt register +unsigned char R; //@- Refresh register + + +/** Returns the 16 bit register BC. */ +#define BC() (((unsigned)B << 8) | C) +#define DE() (((unsigned)D << 8) | E) +#define HL() (((unsigned)H << 8) | L) + +/** + Returns the number of Z80 CPU cycles elapsed so far. + + The cycle count is reset to zero when reset() is called, or + it can be set to any value with setCycles(). It is updated after + a CPU instruction is executed, for example by calling step() + or interrupt(). +*/ +unsigned getCycles(void) { + return cycles_; +} + +/** Sets the CPU cycle counter to the specified value. */ +void setCycles( unsigned value ) { + cycles_ = value; +} + +/** Returns the current interrupt mode. */ +unsigned getInterruptMode(void) { + return iflags_ & 0x03; +} + +/** Sets the interrupt mode to the specified value. */ +void setInterruptMode( unsigned mode ); + +/** Returns non-zero if the CPU is halted, otherwise zero. */ +int isHalted(void) { + return iflags_ & Halted; +} + +/* + Sets the interrupt mode to IM0, IM1 or IM2. +*/ +void setInterruptMode( unsigned mode ) +{ + if( mode <= 2 ) { + iflags_ = (iflags_ & ~0x03) | mode; + } +} + +/* + Calls a subroutine at the specified address. +*/ +void callSub( unsigned addr ) +{ + SP -= 2; + writeWord( SP, PC ); // Save current program counter in the stack + PC = addr & 0xFFFF; // Jump to the specified address +} + +/* + Decrements a byte value by one. + Note that this is different from subtracting one from the byte value, + because flags behave differently. +*/ +static inline unsigned char decByte( unsigned char b ) +{ + F = Subtraction | (F & Carry); // Preserve the carry flag + if( (b & 0x0F) == 0 ) F |= Halfcarry; + --b; + if( b == 0x7F ) F |= Overflow; + if( b & 0x80 ) F |= Sign; + if( b == 0 ) F |= Zero; + + return b; +} + +/* + Increments a byte value by one. + Note that this is different from adding one to the byte value, + because flags behave differently. +*/ +static inline unsigned char incByte( unsigned char b ) +{ + ++b; + F &= Carry; // Preserve the carry flag + if( ! (b & 0x0F) ) F |= Halfcarry; + if( b == 0x80 ) F |= Overflow; + if( b & 0x80 ) F |= Sign; + if( b == 0 ) F |= Zero; + + return b; +} + +/* + Reads one byte from port C, updating flags according to the rules of "IN r,(C)". +*/ +static inline unsigned char inpReg(void) +{ + unsigned char r = readPort( C ); + + F = (F & Carry) | PSZ_[r]; + + return r; +} + +/* + Performs a relative jump to the specified offset. +*/ +static inline void relJump( unsigned char o ) +{ + int offset = (int)((signed char)o); + + PC = (unsigned)((int)PC + offset) & 0xFFFF; + cycles_++; +} + +/* + Returns from a subroutine, popping the saved Program Counter from the stack. +*/ +static inline void retFromSub(void) +{ + PC = readWord( SP ); + SP += 2; +} + +/* + Rotates left one byte thru the carry flag. +*/ +static inline unsigned char rotateLeft( unsigned char op ) +{ + unsigned char f = F; + + F = 0; + if( op & 0x80 ) F |= Carry; + op <<= 1; + if( f & Carry ) op |= 0x01; + F |= PSZ_[op]; + + return op; +} + +/* + Rotates left one byte copying the most significant bit (bit 7) in the carry flag. +*/ +static inline unsigned char rotateLeftCarry( unsigned char op ) +{ + F = 0; + if( op & 0x80 ) F |= Carry; + op = (op << 1) | (op >> 7); + F |= PSZ_[op]; + + return op; +} + +/* + Rotates right one byte thru the carry flag. +*/ +static inline unsigned char rotateRight( unsigned char op ) +{ + unsigned char f = F; + + F = 0; + if( op & 0x01 ) F |= Carry; + op >>= 1; + if( f & Carry ) op |= 0x80; + F |= PSZ_[op]; + + return op; +} + +/* + Rotates right one byte copying the least significant bit (bit 0) in the carry flag. +*/ +static inline unsigned char rotateRightCarry( unsigned char op ) +{ + F = 0; + if( op & 0x01 ) F |= Carry; + op = (op >> 1) | (op << 7); + F |= PSZ_[op]; + + return op; +} + +/* + Shifts left one byte. +*/ +static inline unsigned char shiftLeft( unsigned char op ) +{ + F = 0; + if( op & 0x80 ) F |= Carry; + op <<= 1; + F |= PSZ_[op]; + + return op; +} + +/* + Shifts right one byte, preserving its sign (most significant bit). +*/ +static inline unsigned char shiftRightArith( unsigned char op ) +{ + F = 0; + if( op & 0x01 ) F |= Carry; + op = (op >> 1) | (op & 0x80); + + F |= PSZ_[op]; + + return op; +} + +/* + Shifts right one byte. +*/ +static inline unsigned char shiftRightLogical( unsigned char op ) +{ + F = 0; + if( op & 0x01 ) F |= Carry; + op >>= 1; + + F |= PSZ_[op]; + + return op; +} + +/* + Tests whether the specified bit of op is set. +*/ +static inline void testBit( unsigned char bit, unsigned char op ) +{ + // Flags for a bit test operation are: + // S, P: unknown + // Z: set if bit is zero, reset otherwise + // N: reset + // H: set + // C: unaffected + // However, it seems that parity is always set like Z, so we emulate that as well. + F = (F & (Carry | Sign)) | Halfcarry; + + if( (op & (1 << bit)) == 0 ) { + // Bit is not set, so set the zero flag + F |= Zero | Parity; + } +} + +/* + Adds the specified byte op to the accumulator, adding + carry. +*/ +static inline void addByte( unsigned char op, unsigned char cf ) +{ + unsigned x = A + op; + + if( cf ) x++; // Add carry + + F = 0; + if( !(x & 0xFF) ) F |= Zero; + if( x & 0x80 ) F |= Sign; + if( x >= 0x100 ) F |= Carry; + + /* + Halfcarry is set on carry from the low order four bits. + + To see how to compute it, let's take a look at the following table, which + shows the binary addition of two binary numbers: + + A B A+B + ----------- + 0 0 0 + 0 1 1 + 1 0 1 + 1 1 0 + + Note that if only the lowest bit is used, then A+B, A-B and A^B yield the same + value. If we know A, B and the sum A+B+C, then C is easily derived: + C = A+B+C - A - B, that is + C = A+B+C ^ A ^ B. + + For the halfcarry, A and B above are the fifth bit of a byte, which corresponds + to the value 0x10. So: + + Halfcarry = ((accumulator+operand+halfcarry) ^ accumulator ^ operand) & 0x10 + + Note that masking off all bits but one is important because we have worked all + the math by using one bit only. + */ + if( (A ^ op ^ x) & 0x10 ) F |= Halfcarry; + + /* + The overflow bit is set when the result is too large to fit into the destination + register, causing a change in the sign bit. + + For a sum, we can only have overflow when adding two numbers that are both positive + or both negative. For example 0x5E + 0x4B (94 + 75) yields 0xA9 (169), which fits + into an 8-bit register only if it is interpreted as an unsigned number. If we + consider the result as a signed integer, then 0xA9 corresponds to decimal -87 and + we have overflow. + Note that if we add two signed numbers of opposite sign then we cannot overflow + the destination register, because the absolute value of the result will always fit + in 7 bits, leaving the most significant bit free for use as a sign bit. + + We can code all the above concisely by noting that: + + ~(A ^ op) & 0x80 + + is true if and only if A and op have the same sign. Also: + + (x ^ op) & 0x80 + + is true if and only if the sum of A and op has taken a sign opposite to that + of its operands. + + Thus the expression: + + ~(A ^ op) & (x ^ op) & 0x80 + + reads "A has the same sign as op, and the opposite as x", where x is the sum of + A and op (and an optional carry). + */ + if( ~(A ^ op) & (x ^ op) & 0x80 ) F |= Overflow; + + A = x; +} + +/* + Subtracts the specified byte op from the accumulator, using carry as + borrow from a previous operation. +*/ +static inline unsigned char subByte( unsigned char op, unsigned char cf ) +{ + unsigned char x = A - op; + + if( cf ) x--; + + F = Subtraction; + if( x == 0 ) F |= Zero; + if( x & 0x80 ) F |= Sign; + if( (x >= A) && (op | cf)) F |= Carry; + + // See addByte() for an explanation of the halfcarry bit + if( (A ^ op ^ x) & 0x10 ) F |= Halfcarry; + + // See addByte() for an explanation of the overflow bit. The only difference here + // is that for a subtraction we must check that the two operands have different + // sign, because in fact A-B is A+(-B). Note however that since subtraction is not + // symmetric, we have to use (x ^ A) to get the correct result, whereas for the + // addition (x ^ A) is equivalent to (x ^ op) + if( (A ^ op) & (x ^ A) & 0x80 ) F |= Overflow; + + return x; +} + +static inline unsigned addDispl( unsigned addr, unsigned char displ ) { + return (unsigned)((int)addr + (int)(signed char)displ); +} + +/** Compares the accumulator and the specified operand (CP op) */ +static inline void cmpByte( unsigned char op ) { + subByte( op, 0 ); +} + +/** Fetches a byte from the program counter location */ +static inline unsigned char fetchByte(void) { + return readByte( PC++ ); +} + +/** Fetches a 16 bit word from the program counter location */ +static inline unsigned fetchWord(void) { + unsigned x = readWord( PC ); + PC += 2; + return x; +} + +/** Sets the parity, sign and zero flags from the accumulator value */ +static inline void setFlagsPSZ(void) { + F = Halfcarry | PSZ_[A]; +} + +/** Sets the parity, sign, zero, 3rd and 5th flag bits from the accumulator value */ +static inline void setFlags35PSZ(void) { + F = (F & (Carry | Halfcarry | Subtraction)) | PSZ_[A]; +} + +/** */ +static inline void setFlags35PSZ000(void) { + F = PSZ_[A]; +} + +/* Resets the CPU */ +void z80_reset() +{ + PC = 0; // Program counter is zero + I = 0; // Interrupt register cleared + R = 0; // Memory refresh register cleared + iflags_ = 0; // IFF1 and IFF2 cleared, IM0 enabled + cycles_ = 0; // Could that be 2 (according to some Zilog docs)? + + // There is no official documentation for the following! + B = B1 = 0; + C = C1 = 0; + D = D1 = 0; + E = E1 = 0; + H = H1 = 0; + L = L1 = 0; + A = A1 = 0; + F = F1 = 0; + IX = 0; + IY = 0; + SP = 0xF000; +} + +unsigned z80_getSizeOfSnapshotBuffer(void) +{ + unsigned result = + 8*2 + // 8-bit registers + 1 + // I + 1 + // R + 2 + // IX + 2 + // IY + 2 + // PC + 2 + // SP + 4 + // iflags_ + 4; // cycles_ + + return result; +} + +static unsigned saveUint16( unsigned char * buffer, unsigned u ) +{ + *buffer++ = (unsigned char) (u >> 8); + *buffer = (unsigned char) (u); + + return 2; +} + +unsigned z80_takeSnapshot( unsigned char * buffer ) +{ + unsigned char * buf = buffer; + + *buf++ = A; *buf++ = A1; + *buf++ = B; *buf++ = B1; + *buf++ = C; *buf++ = C1; + *buf++ = D; *buf++ = D1; + *buf++ = E; *buf++ = E1; + *buf++ = H; *buf++ = H1; + *buf++ = L; *buf++ = L1; + *buf++ = F; *buf++ = F1; + + *buf++ = I; + *buf++ = R; + + buf += saveUint16( buf, IX ); + buf += saveUint16( buf, IY ); + buf += saveUint16( buf, PC ); + buf += saveUint16( buf, SP ); + + buf += saveUint16( buf, iflags_ >> 16 ); + buf += saveUint16( buf, iflags_ ); + buf += saveUint16( buf, cycles_ >> 16 ); + buf += saveUint16( buf, cycles_ ); + + return buffer - buf; +} + +static unsigned loadUint16( unsigned char ** buffer ) +{ + unsigned char * buf = *buffer; + unsigned result = *buf++; + + result = (result << 8) | *buf++; + + *buffer = buf; + + return result; +} + +unsigned z80_restoreSnapshot( unsigned char * buffer ) +{ + unsigned char * buf = buffer; + + A = *buf++; A1 = *buf++; + B = *buf++; B1 = *buf++; + C = *buf++; C1 = *buf++; + D = *buf++; D1 = *buf++; + E = *buf++; E1 = *buf++; + H = *buf++; H1 = *buf++; + L = *buf++; L1 = *buf++; + F = *buf++; F1 = *buf++; + + I = *buf++; + R = *buf++; + + IX = loadUint16( &buf ); + IY = loadUint16( &buf ); + PC = loadUint16( &buf ); + SP = loadUint16( &buf ); + + iflags_ = loadUint16( &buf ); + iflags_ = (iflags_ << 16) | loadUint16(&buf); + cycles_ = loadUint16( &buf ); + cycles_ = (cycles_ << 16) | loadUint16(&buf); + + return buf - buffer; +} + +OpcodeInfo OpInfoCB_[256] = { + { &opcode_cb_00, 8 }, // RLC B + { &opcode_cb_01, 8 }, // RLC C + { &opcode_cb_02, 8 }, // RLC D + { &opcode_cb_03, 8 }, // RLC E + { &opcode_cb_04, 8 }, // RLC H + { &opcode_cb_05, 8 }, // RLC L + { &opcode_cb_06, 15 }, // RLC (HL) + { &opcode_cb_07, 8 }, // RLC A + { &opcode_cb_08, 8 }, // RRC B + { &opcode_cb_09, 8 }, // RRC C + { &opcode_cb_0a, 8 }, // RRC D + { &opcode_cb_0b, 8 }, // RRC E + { &opcode_cb_0c, 8 }, // RRC H + { &opcode_cb_0d, 8 }, // RRC L + { &opcode_cb_0e, 15 }, // RRC (HL) + { &opcode_cb_0f, 8 }, // RRC A + { &opcode_cb_10, 8 }, // RL B + { &opcode_cb_11, 8 }, // RL C + { &opcode_cb_12, 8 }, // RL D + { &opcode_cb_13, 8 }, // RL E + { &opcode_cb_14, 8 }, // RL H + { &opcode_cb_15, 8 }, // RL L + { &opcode_cb_16, 15 }, // RL (HL) + { &opcode_cb_17, 8 }, // RL A + { &opcode_cb_18, 8 }, // RR B + { &opcode_cb_19, 8 }, // RR C + { &opcode_cb_1a, 8 }, // RR D + { &opcode_cb_1b, 8 }, // RR E + { &opcode_cb_1c, 8 }, // RR H + { &opcode_cb_1d, 8 }, // RR L + { &opcode_cb_1e, 15 }, // RR (HL) + { &opcode_cb_1f, 8 }, // RR A + { &opcode_cb_20, 8 }, // SLA B + { &opcode_cb_21, 8 }, // SLA C + { &opcode_cb_22, 8 }, // SLA D + { &opcode_cb_23, 8 }, // SLA E + { &opcode_cb_24, 8 }, // SLA H + { &opcode_cb_25, 8 }, // SLA L + { &opcode_cb_26, 15 }, // SLA (HL) + { &opcode_cb_27, 8 }, // SLA A + { &opcode_cb_28, 8 }, // SRA B + { &opcode_cb_29, 8 }, // SRA C + { &opcode_cb_2a, 8 }, // SRA D + { &opcode_cb_2b, 8 }, // SRA E + { &opcode_cb_2c, 8 }, // SRA H + { &opcode_cb_2d, 8 }, // SRA L + { &opcode_cb_2e, 15 }, // SRA (HL) + { &opcode_cb_2f, 8 }, // SRA A + { &opcode_cb_30, 8 }, // SLL B + { &opcode_cb_31, 8 }, // SLL C + { &opcode_cb_32, 8 }, // SLL D + { &opcode_cb_33, 8 }, // SLL E + { &opcode_cb_34, 8 }, // SLL H + { &opcode_cb_35, 8 }, // SLL L + { &opcode_cb_36, 15 }, // SLL (HL) + { &opcode_cb_37, 8 }, // SLL A + { &opcode_cb_38, 8 }, // SRL B + { &opcode_cb_39, 8 }, // SRL C + { &opcode_cb_3a, 8 }, // SRL D + { &opcode_cb_3b, 8 }, // SRL E + { &opcode_cb_3c, 8 }, // SRL H + { &opcode_cb_3d, 8 }, // SRL L + { &opcode_cb_3e, 15 }, // SRL (HL) + { &opcode_cb_3f, 8 }, // SRL A + { &opcode_cb_40, 8 }, // BIT 0, B + { &opcode_cb_41, 8 }, // BIT 0, C + { &opcode_cb_42, 8 }, // BIT 0, D + { &opcode_cb_43, 8 }, // BIT 0, E + { &opcode_cb_44, 8 }, // BIT 0, H + { &opcode_cb_45, 8 }, // BIT 0, L + { &opcode_cb_46, 12 }, // BIT 0, (HL) + { &opcode_cb_47, 8 }, // BIT 0, A + { &opcode_cb_48, 8 }, // BIT 1, B + { &opcode_cb_49, 8 }, // BIT 1, C + { &opcode_cb_4a, 8 }, // BIT 1, D + { &opcode_cb_4b, 8 }, // BIT 1, E + { &opcode_cb_4c, 8 }, // BIT 1, H + { &opcode_cb_4d, 8 }, // BIT 1, L + { &opcode_cb_4e, 12 }, // BIT 1, (HL) + { &opcode_cb_4f, 8 }, // BIT 1, A + { &opcode_cb_50, 8 }, // BIT 2, B + { &opcode_cb_51, 8 }, // BIT 2, C + { &opcode_cb_52, 8 }, // BIT 2, D + { &opcode_cb_53, 8 }, // BIT 2, E + { &opcode_cb_54, 8 }, // BIT 2, H + { &opcode_cb_55, 8 }, // BIT 2, L + { &opcode_cb_56, 12 }, // BIT 2, (HL) + { &opcode_cb_57, 8 }, // BIT 2, A + { &opcode_cb_58, 8 }, // BIT 3, B + { &opcode_cb_59, 8 }, // BIT 3, C + { &opcode_cb_5a, 8 }, // BIT 3, D + { &opcode_cb_5b, 8 }, // BIT 3, E + { &opcode_cb_5c, 8 }, // BIT 3, H + { &opcode_cb_5d, 8 }, // BIT 3, L + { &opcode_cb_5e, 12 }, // BIT 3, (HL) + { &opcode_cb_5f, 8 }, // BIT 3, A + { &opcode_cb_60, 8 }, // BIT 4, B + { &opcode_cb_61, 8 }, // BIT 4, C + { &opcode_cb_62, 8 }, // BIT 4, D + { &opcode_cb_63, 8 }, // BIT 4, E + { &opcode_cb_64, 8 }, // BIT 4, H + { &opcode_cb_65, 8 }, // BIT 4, L + { &opcode_cb_66, 12 }, // BIT 4, (HL) + { &opcode_cb_67, 8 }, // BIT 4, A + { &opcode_cb_68, 8 }, // BIT 5, B + { &opcode_cb_69, 8 }, // BIT 5, C + { &opcode_cb_6a, 8 }, // BIT 5, D + { &opcode_cb_6b, 8 }, // BIT 5, E + { &opcode_cb_6c, 8 }, // BIT 5, H + { &opcode_cb_6d, 8 }, // BIT 5, L + { &opcode_cb_6e, 12 }, // BIT 5, (HL) + { &opcode_cb_6f, 8 }, // BIT 5, A + { &opcode_cb_70, 8 }, // BIT 6, B + { &opcode_cb_71, 8 }, // BIT 6, C + { &opcode_cb_72, 8 }, // BIT 6, D + { &opcode_cb_73, 8 }, // BIT 6, E + { &opcode_cb_74, 8 }, // BIT 6, H + { &opcode_cb_75, 8 }, // BIT 6, L + { &opcode_cb_76, 12 }, // BIT 6, (HL) + { &opcode_cb_77, 8 }, // BIT 6, A + { &opcode_cb_78, 8 }, // BIT 7, B + { &opcode_cb_79, 8 }, // BIT 7, C + { &opcode_cb_7a, 8 }, // BIT 7, D + { &opcode_cb_7b, 8 }, // BIT 7, E + { &opcode_cb_7c, 8 }, // BIT 7, H + { &opcode_cb_7d, 8 }, // BIT 7, L + { &opcode_cb_7e, 12 }, // BIT 7, (HL) + { &opcode_cb_7f, 8 }, // BIT 7, A + { &opcode_cb_80, 8 }, // RES 0, B + { &opcode_cb_81, 8 }, // RES 0, C + { &opcode_cb_82, 8 }, // RES 0, D + { &opcode_cb_83, 8 }, // RES 0, E + { &opcode_cb_84, 8 }, // RES 0, H + { &opcode_cb_85, 8 }, // RES 0, L + { &opcode_cb_86, 15 }, // RES 0, (HL) + { &opcode_cb_87, 8 }, // RES 0, A + { &opcode_cb_88, 8 }, // RES 1, B + { &opcode_cb_89, 8 }, // RES 1, C + { &opcode_cb_8a, 8 }, // RES 1, D + { &opcode_cb_8b, 8 }, // RES 1, E + { &opcode_cb_8c, 8 }, // RES 1, H + { &opcode_cb_8d, 8 }, // RES 1, L + { &opcode_cb_8e, 15 }, // RES 1, (HL) + { &opcode_cb_8f, 8 }, // RES 1, A + { &opcode_cb_90, 8 }, // RES 2, B + { &opcode_cb_91, 8 }, // RES 2, C + { &opcode_cb_92, 8 }, // RES 2, D + { &opcode_cb_93, 8 }, // RES 2, E + { &opcode_cb_94, 8 }, // RES 2, H + { &opcode_cb_95, 8 }, // RES 2, L + { &opcode_cb_96, 15 }, // RES 2, (HL) + { &opcode_cb_97, 8 }, // RES 2, A + { &opcode_cb_98, 8 }, // RES 3, B + { &opcode_cb_99, 8 }, // RES 3, C + { &opcode_cb_9a, 8 }, // RES 3, D + { &opcode_cb_9b, 8 }, // RES 3, E + { &opcode_cb_9c, 8 }, // RES 3, H + { &opcode_cb_9d, 8 }, // RES 3, L + { &opcode_cb_9e, 15 }, // RES 3, (HL) + { &opcode_cb_9f, 8 }, // RES 3, A + { &opcode_cb_a0, 8 }, // RES 4, B + { &opcode_cb_a1, 8 }, // RES 4, C + { &opcode_cb_a2, 8 }, // RES 4, D + { &opcode_cb_a3, 8 }, // RES 4, E + { &opcode_cb_a4, 8 }, // RES 4, H + { &opcode_cb_a5, 8 }, // RES 4, L + { &opcode_cb_a6, 15 }, // RES 4, (HL) + { &opcode_cb_a7, 8 }, // RES 4, A + { &opcode_cb_a8, 8 }, // RES 5, B + { &opcode_cb_a9, 8 }, // RES 5, C + { &opcode_cb_aa, 8 }, // RES 5, D + { &opcode_cb_ab, 8 }, // RES 5, E + { &opcode_cb_ac, 8 }, // RES 5, H + { &opcode_cb_ad, 8 }, // RES 5, L + { &opcode_cb_ae, 15 }, // RES 5, (HL) + { &opcode_cb_af, 8 }, // RES 5, A + { &opcode_cb_b0, 8 }, // RES 6, B + { &opcode_cb_b1, 8 }, // RES 6, C + { &opcode_cb_b2, 8 }, // RES 6, D + { &opcode_cb_b3, 8 }, // RES 6, E + { &opcode_cb_b4, 8 }, // RES 6, H + { &opcode_cb_b5, 8 }, // RES 6, L + { &opcode_cb_b6, 15 }, // RES 6, (HL) + { &opcode_cb_b7, 8 }, // RES 6, A + { &opcode_cb_b8, 8 }, // RES 7, B + { &opcode_cb_b9, 8 }, // RES 7, C + { &opcode_cb_ba, 8 }, // RES 7, D + { &opcode_cb_bb, 8 }, // RES 7, E + { &opcode_cb_bc, 8 }, // RES 7, H + { &opcode_cb_bd, 8 }, // RES 7, L + { &opcode_cb_be, 15 }, // RES 7, (HL) + { &opcode_cb_bf, 8 }, // RES 7, A + { &opcode_cb_c0, 8 }, // SET 0, B + { &opcode_cb_c1, 8 }, // SET 0, C + { &opcode_cb_c2, 8 }, // SET 0, D + { &opcode_cb_c3, 8 }, // SET 0, E + { &opcode_cb_c4, 8 }, // SET 0, H + { &opcode_cb_c5, 8 }, // SET 0, L + { &opcode_cb_c6, 15 }, // SET 0, (HL) + { &opcode_cb_c7, 8 }, // SET 0, A + { &opcode_cb_c8, 8 }, // SET 1, B + { &opcode_cb_c9, 8 }, // SET 1, C + { &opcode_cb_ca, 8 }, // SET 1, D + { &opcode_cb_cb, 8 }, // SET 1, E + { &opcode_cb_cc, 8 }, // SET 1, H + { &opcode_cb_cd, 8 }, // SET 1, L + { &opcode_cb_ce, 15 }, // SET 1, (HL) + { &opcode_cb_cf, 8 }, // SET 1, A + { &opcode_cb_d0, 8 }, // SET 2, B + { &opcode_cb_d1, 8 }, // SET 2, C + { &opcode_cb_d2, 8 }, // SET 2, D + { &opcode_cb_d3, 8 }, // SET 2, E + { &opcode_cb_d4, 8 }, // SET 2, H + { &opcode_cb_d5, 8 }, // SET 2, L + { &opcode_cb_d6, 15 }, // SET 2, (HL) + { &opcode_cb_d7, 8 }, // SET 2, A + { &opcode_cb_d8, 8 }, // SET 3, B + { &opcode_cb_d9, 8 }, // SET 3, C + { &opcode_cb_da, 8 }, // SET 3, D + { &opcode_cb_db, 8 }, // SET 3, E + { &opcode_cb_dc, 8 }, // SET 3, H + { &opcode_cb_dd, 8 }, // SET 3, L + { &opcode_cb_de, 15 }, // SET 3, (HL) + { &opcode_cb_df, 8 }, // SET 3, A + { &opcode_cb_e0, 8 }, // SET 4, B + { &opcode_cb_e1, 8 }, // SET 4, C + { &opcode_cb_e2, 8 }, // SET 4, D + { &opcode_cb_e3, 8 }, // SET 4, E + { &opcode_cb_e4, 8 }, // SET 4, H + { &opcode_cb_e5, 8 }, // SET 4, L + { &opcode_cb_e6, 15 }, // SET 4, (HL) + { &opcode_cb_e7, 8 }, // SET 4, A + { &opcode_cb_e8, 8 }, // SET 5, B + { &opcode_cb_e9, 8 }, // SET 5, C + { &opcode_cb_ea, 8 }, // SET 5, D + { &opcode_cb_eb, 8 }, // SET 5, E + { &opcode_cb_ec, 8 }, // SET 5, H + { &opcode_cb_ed, 8 }, // SET 5, L + { &opcode_cb_ee, 15 }, // SET 5, (HL) + { &opcode_cb_ef, 8 }, // SET 5, A + { &opcode_cb_f0, 8 }, // SET 6, B + { &opcode_cb_f1, 8 }, // SET 6, C + { &opcode_cb_f2, 8 }, // SET 6, D + { &opcode_cb_f3, 8 }, // SET 6, E + { &opcode_cb_f4, 8 }, // SET 6, H + { &opcode_cb_f5, 8 }, // SET 6, L + { &opcode_cb_f6, 15 }, // SET 6, (HL) + { &opcode_cb_f7, 8 }, // SET 6, A + { &opcode_cb_f8, 8 }, // SET 7, B + { &opcode_cb_f9, 8 }, // SET 7, C + { &opcode_cb_fa, 8 }, // SET 7, D + { &opcode_cb_fb, 8 }, // SET 7, E + { &opcode_cb_fc, 8 }, // SET 7, H + { &opcode_cb_fd, 8 }, // SET 7, L + { &opcode_cb_fe, 15 }, // SET 7, (HL) + { &opcode_cb_ff, 8 } // SET 7, A +}; + +void opcode_cb_00() // RLC B +{ + B = rotateLeftCarry( B ); +} + +void opcode_cb_01() // RLC C +{ + C = rotateLeftCarry( C ); +} + +void opcode_cb_02() // RLC D +{ + D = rotateLeftCarry( D ); +} + +void opcode_cb_03() // RLC E +{ + E = rotateLeftCarry( E ); +} + +void opcode_cb_04() // RLC H +{ + H = rotateLeftCarry( H ); +} + +void opcode_cb_05() // RLC L +{ + L = rotateLeftCarry( L ); +} + +void opcode_cb_06() // RLC (HL) +{ + writeByte( HL(), rotateLeftCarry( readByte( HL() ) ) ); +} + +void opcode_cb_07() // RLC A +{ + A = rotateLeftCarry( A ); +} + +void opcode_cb_08() // RRC B +{ + B = rotateRightCarry( B ); +} + +void opcode_cb_09() // RRC C +{ + C = rotateLeftCarry( C ); +} + +void opcode_cb_0a() // RRC D +{ + D = rotateLeftCarry( D ); +} + +void opcode_cb_0b() // RRC E +{ + E = rotateLeftCarry( E ); +} + +void opcode_cb_0c() // RRC H +{ + H = rotateLeftCarry( H ); +} + +void opcode_cb_0d() // RRC L +{ + L = rotateLeftCarry( L ); +} + +void opcode_cb_0e() // RRC (HL) +{ + writeByte( HL(), rotateRightCarry( readByte( HL() ) ) ); +} + +void opcode_cb_0f() // RRC A +{ + A = rotateLeftCarry( A ); +} + +void opcode_cb_10() // RL B +{ + B = rotateLeft( B ); +} + +void opcode_cb_11() // RL C +{ + C = rotateLeft( C ); +} + +void opcode_cb_12() // RL D +{ + D = rotateLeft( D ); +} + +void opcode_cb_13() // RL E +{ + E = rotateLeft( E ); +} + +void opcode_cb_14() // RL H +{ + H = rotateLeft( H ); +} + +void opcode_cb_15() // RL L +{ + L = rotateLeft( L ); +} + +void opcode_cb_16() // RL (HL) +{ + writeByte( HL(), rotateLeft( readByte( HL() ) ) ); +} + +void opcode_cb_17() // RL A +{ + A = rotateLeft( A ); +} + +void opcode_cb_18() // RR B +{ + B = rotateRight( B ); +} + +void opcode_cb_19() // RR C +{ + C = rotateRight( C ); +} + +void opcode_cb_1a() // RR D +{ + D = rotateRight( D ); +} + +void opcode_cb_1b() // RR E +{ + E = rotateRight( E ); +} + +void opcode_cb_1c() // RR H +{ + H = rotateRight( H ); +} + +void opcode_cb_1d() // RR L +{ + L = rotateRight( L ); +} + +void opcode_cb_1e() // RR (HL) +{ + writeByte( HL(), rotateRight( readByte( HL() ) ) ); +} + +void opcode_cb_1f() // RR A +{ + A = rotateRight( A ); +} + +void opcode_cb_20() // SLA B +{ + B = shiftLeft( B ); +} + +void opcode_cb_21() // SLA C +{ + C = shiftLeft( C ); +} + +void opcode_cb_22() // SLA D +{ + D = shiftLeft( D ); +} + +void opcode_cb_23() // SLA E +{ + E = shiftLeft( E ); +} + +void opcode_cb_24() // SLA H +{ + H = shiftLeft( H ); +} + +void opcode_cb_25() // SLA L +{ + L = shiftLeft( L ); +} + +void opcode_cb_26() // SLA (HL) +{ + writeByte( HL(), shiftLeft( readByte( HL() ) ) ); +} + +void opcode_cb_27() // SLA A +{ + A = shiftLeft( A ); +} + +void opcode_cb_28() // SRA B +{ + B = shiftRightArith( B ); +} + +void opcode_cb_29() // SRA C +{ + C = shiftRightArith( C ); +} + +void opcode_cb_2a() // SRA D +{ + D = shiftRightArith( D ); +} + +void opcode_cb_2b() // SRA E +{ + E = shiftRightArith( E ); +} + +void opcode_cb_2c() // SRA H +{ + H = shiftRightArith( H ); +} + +void opcode_cb_2d() // SRA L +{ + L = shiftRightArith( L ); +} + +void opcode_cb_2e() // SRA (HL) +{ + writeByte( HL(), shiftRightArith( readByte( HL() ) ) ); +} + +void opcode_cb_2f() // SRA A +{ + A = shiftRightArith( A ); +} + +void opcode_cb_30() // SLL B +{ + B = shiftLeft( B ) | 0x01; +} + +void opcode_cb_31() // SLL C +{ + C = shiftLeft( C ) | 0x01; +} + +void opcode_cb_32() // SLL D +{ + D = shiftLeft( D ) | 0x01; +} + +void opcode_cb_33() // SLL E +{ + E = shiftLeft( E ) | 0x01; +} + +void opcode_cb_34() // SLL H +{ + H = shiftLeft( H ) | 0x01; +} + +void opcode_cb_35() // SLL L +{ + L = shiftLeft( L ) | 0x01; +} + +void opcode_cb_36() // SLL (HL) +{ + writeByte( HL(), shiftLeft( readByte( HL() ) ) | 0x01 ); +} + +void opcode_cb_37() // SLL A +{ + A = shiftLeft( A ) | 0x01; +} + +void opcode_cb_38() // SRL B +{ + B = shiftRightLogical( B ); +} + +void opcode_cb_39() // SRL C +{ + C = shiftRightLogical( C ); +} + +void opcode_cb_3a() // SRL D +{ + D = shiftRightLogical( D ); +} + +void opcode_cb_3b() // SRL E +{ + E = shiftRightLogical( E ); +} + +void opcode_cb_3c() // SRL H +{ + H = shiftRightLogical( H ); +} + +void opcode_cb_3d() // SRL L +{ + L = shiftRightLogical( L ); +} + +void opcode_cb_3e() // SRL (HL) +{ + writeByte( HL(), shiftRightLogical( readByte( HL() ) ) ); +} + +void opcode_cb_3f() // SRL A +{ + A = shiftRightLogical( A ); +} + +void opcode_cb_40() // BIT 0, B +{ + testBit( 0, B ); +} + +void opcode_cb_41() // BIT 0, C +{ + testBit( 0, C ); +} + +void opcode_cb_42() // BIT 0, D +{ + testBit( 0, D ); +} + +void opcode_cb_43() // BIT 0, E +{ + testBit( 0, E ); +} + +void opcode_cb_44() // BIT 0, H +{ + testBit( 0, H ); +} + +void opcode_cb_45() // BIT 0, L +{ + testBit( 0, L ); +} + +void opcode_cb_46() // BIT 0, (HL) +{ + testBit( 0, readByte( HL() ) ); +} + +void opcode_cb_47() // BIT 0, A +{ + testBit( 0, A ); +} + +void opcode_cb_48() // BIT 1, B +{ + testBit( 1, B ); +} + +void opcode_cb_49() // BIT 1, C +{ + testBit( 1, C ); +} + +void opcode_cb_4a() // BIT 1, D +{ + testBit( 1, D ); +} + +void opcode_cb_4b() // BIT 1, E +{ + testBit( 1, E ); +} + +void opcode_cb_4c() // BIT 1, H +{ + testBit( 1, H ); +} + +void opcode_cb_4d() // BIT 1, L +{ + testBit( 1, L ); +} + +void opcode_cb_4e() // BIT 1, (HL) +{ + testBit( 1, readByte( HL() ) ); +} + +void opcode_cb_4f() // BIT 1, A +{ + testBit( 1, A ); +} + +void opcode_cb_50() // BIT 2, B +{ + testBit( 2, B ); +} + +void opcode_cb_51() // BIT 2, C +{ + testBit( 2, C ); +} + +void opcode_cb_52() // BIT 2, D +{ + testBit( 2, D ); +} + +void opcode_cb_53() // BIT 2, E +{ + testBit( 2, E ); +} + +void opcode_cb_54() // BIT 2, H +{ + testBit( 2, H ); +} + +void opcode_cb_55() // BIT 2, L +{ + testBit( 2, L ); +} + +void opcode_cb_56() // BIT 2, (HL) +{ + testBit( 2, readByte( HL() ) ); +} + +void opcode_cb_57() // BIT 2, A +{ + testBit( 2, A ); +} + +void opcode_cb_58() // BIT 3, B +{ + testBit( 3, B ); +} + +void opcode_cb_59() // BIT 3, C +{ + testBit( 3, C ); +} + +void opcode_cb_5a() // BIT 3, D +{ + testBit( 3, D ); +} + +void opcode_cb_5b() // BIT 3, E +{ + testBit( 3, E ); +} + +void opcode_cb_5c() // BIT 3, H +{ + testBit( 3, H ); +} + +void opcode_cb_5d() // BIT 3, L +{ + testBit( 3, L ); +} + +void opcode_cb_5e() // BIT 3, (HL) +{ + testBit( 3, readByte( HL() ) ); +} + +void opcode_cb_5f() // BIT 3, A +{ + testBit( 3, A ); +} + +void opcode_cb_60() // BIT 4, B +{ + testBit( 4, B ); +} + +void opcode_cb_61() // BIT 4, C +{ + testBit( 4, C ); +} + +void opcode_cb_62() // BIT 4, D +{ + testBit( 4, D ); +} + +void opcode_cb_63() // BIT 4, E +{ + testBit( 4, E ); +} + +void opcode_cb_64() // BIT 4, H +{ + testBit( 4, H ); +} + +void opcode_cb_65() // BIT 4, L +{ + testBit( 4, L ); +} + +void opcode_cb_66() // BIT 4, (HL) +{ + testBit( 4, readByte( HL() ) ); +} + +void opcode_cb_67() // BIT 4, A +{ + testBit( 4, A ); +} + +void opcode_cb_68() // BIT 5, B +{ + testBit( 5, B ); +} + +void opcode_cb_69() // BIT 5, C +{ + testBit( 5, C ); +} + +void opcode_cb_6a() // BIT 5, D +{ + testBit( 5, D ); +} + +void opcode_cb_6b() // BIT 5, E +{ + testBit( 5, E ); +} + +void opcode_cb_6c() // BIT 5, H +{ + testBit( 5, H ); +} + +void opcode_cb_6d() // BIT 5, L +{ + testBit( 5, L ); +} + +void opcode_cb_6e() // BIT 5, (HL) +{ + testBit( 5, readByte( HL() ) ); +} + +void opcode_cb_6f() // BIT 5, A +{ + testBit( 5, A ); +} + +void opcode_cb_70() // BIT 6, B +{ + testBit( 6, B ); +} + +void opcode_cb_71() // BIT 6, C +{ + testBit( 6, C ); +} + +void opcode_cb_72() // BIT 6, D +{ + testBit( 6, D ); +} + +void opcode_cb_73() // BIT 6, E +{ + testBit( 6, E ); +} + +void opcode_cb_74() // BIT 6, H +{ + testBit( 6, H ); +} + +void opcode_cb_75() // BIT 6, L +{ + testBit( 6, L ); +} + +void opcode_cb_76() // BIT 6, (HL) +{ + testBit( 6, readByte( HL() ) ); +} + +void opcode_cb_77() // BIT 6, A +{ + testBit( 6, A ); +} + +void opcode_cb_78() // BIT 7, B +{ + testBit( 7, B ); +} + +void opcode_cb_79() // BIT 7, C +{ + testBit( 7, C ); +} + +void opcode_cb_7a() // BIT 7, D +{ + testBit( 7, D ); +} + +void opcode_cb_7b() // BIT 7, E +{ + testBit( 7, E ); +} + +void opcode_cb_7c() // BIT 7, H +{ + testBit( 7, H ); +} + +void opcode_cb_7d() // BIT 7, L +{ + testBit( 7, L ); +} + +void opcode_cb_7e() // BIT 7, (HL) +{ + testBit( 7, readByte( HL() ) ); +} + +void opcode_cb_7f() // BIT 7, A +{ + testBit( 7, A ); +} + +void opcode_cb_80() // RES 0, B +{ + B &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_81() // RES 0, C +{ + C &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_82() // RES 0, D +{ + D &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_83() // RES 0, E +{ + E &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_84() // RES 0, H +{ + H &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_85() // RES 0, L +{ + L &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_86() // RES 0, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 0) ); +} + +void opcode_cb_87() // RES 0, A +{ + A &= ~(unsigned char) (1 << 0); +} + +void opcode_cb_88() // RES 1, B +{ + B &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_89() // RES 1, C +{ + C &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_8a() // RES 1, D +{ + D &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_8b() // RES 1, E +{ + E &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_8c() // RES 1, H +{ + H &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_8d() // RES 1, L +{ + L &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_8e() // RES 1, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 1) ); +} + +void opcode_cb_8f() // RES 1, A +{ + A &= ~(unsigned char) (1 << 1); +} + +void opcode_cb_90() // RES 2, B +{ + B &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_91() // RES 2, C +{ + C &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_92() // RES 2, D +{ + D &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_93() // RES 2, E +{ + E &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_94() // RES 2, H +{ + H &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_95() // RES 2, L +{ + L &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_96() // RES 2, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 2) ); +} + +void opcode_cb_97() // RES 2, A +{ + A &= ~(unsigned char) (1 << 2); +} + +void opcode_cb_98() // RES 3, B +{ + B &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_99() // RES 3, C +{ + C &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_9a() // RES 3, D +{ + D &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_9b() // RES 3, E +{ + E &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_9c() // RES 3, H +{ + H &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_9d() // RES 3, L +{ + L &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_9e() // RES 3, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 3) ); +} + +void opcode_cb_9f() // RES 3, A +{ + A &= ~(unsigned char) (1 << 3); +} + +void opcode_cb_a0() // RES 4, B +{ + B &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a1() // RES 4, C +{ + C &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a2() // RES 4, D +{ + D &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a3() // RES 4, E +{ + E &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a4() // RES 4, H +{ + H &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a5() // RES 4, L +{ + L &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a6() // RES 4, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 4) ); +} + +void opcode_cb_a7() // RES 4, A +{ + A &= ~(unsigned char) (1 << 4); +} + +void opcode_cb_a8() // RES 5, B +{ + B &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_a9() // RES 5, C +{ + C &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_aa() // RES 5, D +{ + D &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_ab() // RES 5, E +{ + E &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_ac() // RES 5, H +{ + H &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_ad() // RES 5, L +{ + L &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_ae() // RES 5, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 5) ); +} + +void opcode_cb_af() // RES 5, A +{ + A &= ~(unsigned char) (1 << 5); +} + +void opcode_cb_b0() // RES 6, B +{ + B &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b1() // RES 6, C +{ + C &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b2() // RES 6, D +{ + D &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b3() // RES 6, E +{ + E &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b4() // RES 6, H +{ + H &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b5() // RES 6, L +{ + L &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b6() // RES 6, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 6) ); +} + +void opcode_cb_b7() // RES 6, A +{ + A &= ~(unsigned char) (1 << 6); +} + +void opcode_cb_b8() // RES 7, B +{ + B &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_b9() // RES 7, C +{ + C &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_ba() // RES 7, D +{ + D &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_bb() // RES 7, E +{ + E &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_bc() // RES 7, H +{ + H &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_bd() // RES 7, L +{ + L &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_be() // RES 7, (HL) +{ + writeByte( HL(), readByte( HL() ) & (unsigned char) ~(unsigned char) (1 << 7) ); +} + +void opcode_cb_bf() // RES 7, A +{ + A &= ~(unsigned char) (1 << 7); +} + +void opcode_cb_c0() // SET 0, B +{ + B |= (unsigned char) (1 << 0); +} + +void opcode_cb_c1() // SET 0, C +{ + C |= (unsigned char) (1 << 0); +} + +void opcode_cb_c2() // SET 0, D +{ + D |= (unsigned char) (1 << 0); +} + +void opcode_cb_c3() // SET 0, E +{ + E |= (unsigned char) (1 << 0); +} + +void opcode_cb_c4() // SET 0, H +{ + H |= (unsigned char) (1 << 0); +} + +void opcode_cb_c5() // SET 0, L +{ + L |= (unsigned char) (1 << 0); +} + +void opcode_cb_c6() // SET 0, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 0) ); +} + +void opcode_cb_c7() // SET 0, A +{ + A |= (unsigned char) (1 << 0); +} + +void opcode_cb_c8() // SET 1, B +{ + B |= (unsigned char) (1 << 1); +} + +void opcode_cb_c9() // SET 1, C +{ + C |= (unsigned char) (1 << 1); +} + +void opcode_cb_ca() // SET 1, D +{ + D |= (unsigned char) (1 << 1); +} + +void opcode_cb_cb() // SET 1, E +{ + E |= (unsigned char) (1 << 1); +} + +void opcode_cb_cc() // SET 1, H +{ + H |= (unsigned char) (1 << 1); +} + +void opcode_cb_cd() // SET 1, L +{ + L |= (unsigned char) (1 << 1); +} + +void opcode_cb_ce() // SET 1, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 1) ); +} + +void opcode_cb_cf() // SET 1, A +{ + A |= (unsigned char) (1 << 1); +} + +void opcode_cb_d0() // SET 2, B +{ + B |= (unsigned char) (1 << 2); +} + +void opcode_cb_d1() // SET 2, C +{ + C |= (unsigned char) (1 << 2); +} + +void opcode_cb_d2() // SET 2, D +{ + D |= (unsigned char) (1 << 2); +} + +void opcode_cb_d3() // SET 2, E +{ + E |= (unsigned char) (1 << 2); +} + +void opcode_cb_d4() // SET 2, H +{ + H |= (unsigned char) (1 << 2); +} + +void opcode_cb_d5() // SET 2, L +{ + L |= (unsigned char) (1 << 2); +} + +void opcode_cb_d6() // SET 2, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 2) ); +} + +void opcode_cb_d7() // SET 2, A +{ + A |= (unsigned char) (1 << 2); +} + +void opcode_cb_d8() // SET 3, B +{ + B |= (unsigned char) (1 << 3); +} + +void opcode_cb_d9() // SET 3, C +{ + C |= (unsigned char) (1 << 3); +} + +void opcode_cb_da() // SET 3, D +{ + D |= (unsigned char) (1 << 3); +} + +void opcode_cb_db() // SET 3, E +{ + E |= (unsigned char) (1 << 3); +} + +void opcode_cb_dc() // SET 3, H +{ + H |= (unsigned char) (1 << 3); +} + +void opcode_cb_dd() // SET 3, L +{ + L |= (unsigned char) (1 << 3); +} + +void opcode_cb_de() // SET 3, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 3) ); +} + +void opcode_cb_df() // SET 3, A +{ + A |= (unsigned char) (1 << 3); +} + +void opcode_cb_e0() // SET 4, B +{ + B |= (unsigned char) (1 << 4); +} + +void opcode_cb_e1() // SET 4, C +{ + C |= (unsigned char) (1 << 4); +} + +void opcode_cb_e2() // SET 4, D +{ + D |= (unsigned char) (1 << 4); +} + +void opcode_cb_e3() // SET 4, E +{ + E |= (unsigned char) (1 << 4); +} + +void opcode_cb_e4() // SET 4, H +{ + H |= (unsigned char) (1 << 4); +} + +void opcode_cb_e5() // SET 4, L +{ + L |= (unsigned char) (1 << 4); +} + +void opcode_cb_e6() // SET 4, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 4) ); +} + +void opcode_cb_e7() // SET 4, A +{ + A |= (unsigned char) (1 << 4); +} + +void opcode_cb_e8() // SET 5, B +{ + B |= (unsigned char) (1 << 5); +} + +void opcode_cb_e9() // SET 5, C +{ + C |= (unsigned char) (1 << 5); +} + +void opcode_cb_ea() // SET 5, D +{ + D |= (unsigned char) (1 << 5); +} + +void opcode_cb_eb() // SET 5, E +{ + E |= (unsigned char) (1 << 5); +} + +void opcode_cb_ec() // SET 5, H +{ + H |= (unsigned char) (1 << 5); +} + +void opcode_cb_ed() // SET 5, L +{ + L |= (unsigned char) (1 << 5); +} + +void opcode_cb_ee() // SET 5, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 5) ); +} + +void opcode_cb_ef() // SET 5, A +{ + A |= (unsigned char) (1 << 5); +} + +void opcode_cb_f0() // SET 6, B +{ + B |= (unsigned char) (1 << 6); +} + +void opcode_cb_f1() // SET 6, C +{ + C |= (unsigned char) (1 << 6); +} + +void opcode_cb_f2() // SET 6, D +{ + D |= (unsigned char) (1 << 6); +} + +void opcode_cb_f3() // SET 6, E +{ + E |= (unsigned char) (1 << 6); +} + +void opcode_cb_f4() // SET 6, H +{ + H |= (unsigned char) (1 << 6); +} + +void opcode_cb_f5() // SET 6, L +{ + L |= (unsigned char) (1 << 6); +} + +void opcode_cb_f6() // SET 6, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 6) ); +} + +void opcode_cb_f7() // SET 6, A +{ + A |= (unsigned char) (1 << 6); +} + +void opcode_cb_f8() // SET 7, B +{ + B |= (unsigned char) (1 << 7); +} + +void opcode_cb_f9() // SET 7, C +{ + C |= (unsigned char) (1 << 7); +} + +void opcode_cb_fa() // SET 7, D +{ + D |= (unsigned char) (1 << 7); +} + +void opcode_cb_fb() // SET 7, E +{ + E |= (unsigned char) (1 << 7); +} + +void opcode_cb_fc() // SET 7, H +{ + H |= (unsigned char) (1 << 7); +} + +void opcode_cb_fd() // SET 7, L +{ + L |= (unsigned char) (1 << 7); +} + +void opcode_cb_fe() // SET 7, (HL) +{ + writeByte( HL(), readByte( HL() ) | (unsigned char) (1 << 7) ); +} + +void opcode_cb_ff() // SET 7, A +{ + A |= (unsigned char) (1 << 7); +} + +OpcodeInfo OpInfoDD_[256] = { + { 0, 0 }, // 0x00 + { 0, 0 }, // 0x01 + { 0, 0 }, // 0x02 + { 0, 0 }, // 0x03 + { 0, 0 }, // 0x04 + { 0, 0 }, // 0x05 + { 0, 0 }, // 0x06 + { 0, 0 }, // 0x07 + { 0, 0 }, // 0x08 + { &opcode_dd_09, 15 }, // ADD IX, BC + { 0, 0 }, // 0x0A + { 0, 0 }, // 0x0B + { 0, 0 }, // 0x0C + { 0, 0 }, // 0x0D + { 0, 0 }, // 0x0E + { 0, 0 }, // 0x0F + { 0, 0 }, // 0x10 + { 0, 0 }, // 0x11 + { 0, 0 }, // 0x12 + { 0, 0 }, // 0x13 + { 0, 0 }, // 0x14 + { 0, 0 }, // 0x15 + { 0, 0 }, // 0x16 + { 0, 0 }, // 0x17 + { 0, 0 }, // 0x18 + { &opcode_dd_19, 15 }, // ADD IX, DE + { 0, 0 }, // 0x1A + { 0, 0 }, // 0x1B + { 0, 0 }, // 0x1C + { 0, 0 }, // 0x1D + { 0, 0 }, // 0x1E + { 0, 0 }, // 0x1F + { 0, 0 }, // 0x20 + { &opcode_dd_21, 14 }, // LD IX, nn + { &opcode_dd_22, 20 }, // LD (nn), IX + { &opcode_dd_23, 10 }, // INC IX + { &opcode_dd_24, 9 }, // INC IXH + { &opcode_dd_25, 9 }, // DEC IXH + { &opcode_dd_26, 9 }, // LD IXH, n + { 0, 0 }, // 0x27 + { 0, 0 }, // 0x28 + { &opcode_dd_29, 15 }, // ADD IX, IX + { &opcode_dd_2a, 20 }, // LD IX, (nn) + { &opcode_dd_2b, 10 }, // DEC IX + { &opcode_dd_2c, 9 }, // INC IXL + { &opcode_dd_2d, 9 }, // DEC IXL + { &opcode_dd_2e, 9 }, // LD IXL, n + { 0, 0 }, // 0x2F + { 0, 0 }, // 0x30 + { 0, 0 }, // 0x31 + { 0, 0 }, // 0x32 + { 0, 0 }, // 0x33 + { &opcode_dd_34, 23 }, // INC (IX + d) + { &opcode_dd_35, 23 }, // DEC (IX + d) + { &opcode_dd_36, 19 }, // LD (IX + d), n + { 0, 0 }, // 0x37 + { 0, 0 }, // 0x38 + { &opcode_dd_39, 15 }, // ADD IX, SP + { 0, 0 }, // 0x3A + { 0, 0 }, // 0x3B + { 0, 0 }, // 0x3C + { 0, 0 }, // 0x3D + { 0, 0 }, // 0x3E + { 0, 0 }, // 0x3F + { 0, 0 }, // 0x40 + { 0, 0 }, // 0x41 + { 0, 0 }, // 0x42 + { 0, 0 }, // 0x43 + { &opcode_dd_44, 9 }, // LD B, IXH + { &opcode_dd_45, 9 }, // LD B, IXL + { &opcode_dd_46, 19 }, // LD B, (IX + d) + { 0, 0 }, // 0x47 + { 0, 0 }, // 0x48 + { 0, 0 }, // 0x49 + { 0, 0 }, // 0x4A + { 0, 0 }, // 0x4B + { &opcode_dd_4c, 9 }, // LD C, IXH + { &opcode_dd_4d, 9 }, // LD C, IXL + { &opcode_dd_4e, 19 }, // LD C, (IX + d) + { 0, 0 }, // 0x4F + { 0, 0 }, // 0x50 + { 0, 0 }, // 0x51 + { 0, 0 }, // 0x52 + { 0, 0 }, // 0x53 + { &opcode_dd_54, 9 }, // LD D, IXH + { &opcode_dd_55, 9 }, // LD D, IXL + { &opcode_dd_56, 19 }, // LD D, (IX + d) + { 0, 0 }, // 0x57 + { 0, 0 }, // 0x58 + { 0, 0 }, // 0x59 + { 0, 0 }, // 0x5A + { 0, 0 }, // 0x5B + { &opcode_dd_5c, 9 }, // LD E, IXH + { &opcode_dd_5d, 9 }, // LD E, IXL + { &opcode_dd_5e, 19 }, // LD E, (IX + d) + { 0, 0 }, // 0x5F + { &opcode_dd_60, 9 }, // LD IXH, B + { &opcode_dd_61, 9 }, // LD IXH, C + { &opcode_dd_62, 9 }, // LD IXH, D + { &opcode_dd_63, 9 }, // LD IXH, E + { &opcode_dd_64, 9 }, // LD IXH, IXH + { &opcode_dd_65, 9 }, // LD IXH, IXL + { &opcode_dd_66, 9 }, // LD H, (IX + d) + { &opcode_dd_67, 9 }, // LD IXH, A + { &opcode_dd_68, 9 }, // LD IXL, B + { &opcode_dd_69, 9 }, // LD IXL, C + { &opcode_dd_6a, 9 }, // LD IXL, D + { &opcode_dd_6b, 9 }, // LD IXL, E + { &opcode_dd_6c, 9 }, // LD IXL, IXH + { &opcode_dd_6d, 9 }, // LD IXL, IXL + { &opcode_dd_6e, 9 }, // LD L, (IX + d) + { &opcode_dd_6f, 9 }, // LD IXL, A + { &opcode_dd_70, 19 }, // LD (IX + d), B + { &opcode_dd_71, 19 }, // LD (IX + d), C + { &opcode_dd_72, 19 }, // LD (IX + d), D + { &opcode_dd_73, 19 }, // LD (IX + d), E + { &opcode_dd_74, 19 }, // LD (IX + d), H + { &opcode_dd_75, 19 }, // LD (IX + d), L + { 0,19 }, // 0x76 + { &opcode_dd_77, 19 }, // LD (IX + d), A + { 0, 0 }, // 0x78 + { 0, 0 }, // 0x79 + { 0, 0 }, // 0x7A + { 0, 0 }, // 0x7B + { &opcode_dd_7c, 9 }, // LD A, IXH + { &opcode_dd_7d, 9 }, // LD A, IXL + { &opcode_dd_7e, 19 }, // LD A, (IX + d) + { 0, 0 }, // 0x7F + { 0, 0 }, // 0x80 + { 0, 0 }, // 0x81 + { 0, 0 }, // 0x82 + { 0, 0 }, // 0x83 + { &opcode_dd_84, 9 }, // ADD A, IXH + { &opcode_dd_85, 9 }, // ADD A, IXL + { &opcode_dd_86, 19 }, // ADD A, (IX + d) + { 0, 0 }, // 0x87 + { 0, 0 }, // 0x88 + { 0, 0 }, // 0x89 + { 0, 0 }, // 0x8A + { 0, 0 }, // 0x8B + { &opcode_dd_8c, 9 }, // ADC A, IXH + { &opcode_dd_8d, 9 }, // ADC A, IXL + { &opcode_dd_8e, 19 }, // ADC A, (IX + d) + { 0, 0 }, // 0x8F + { 0, 0 }, // 0x90 + { 0, 0 }, // 0x91 + { 0, 0 }, // 0x92 + { 0, 0 }, // 0x93 + { &opcode_dd_94, 9 }, // SUB IXH + { &opcode_dd_95, 9 }, // SUB IXL + { &opcode_dd_96, 19 }, // SUB (IX + d) + { 0, 0 }, // 0x97 + { 0, 0 }, // 0x98 + { 0, 0 }, // 0x99 + { 0, 0 }, // 0x9A + { 0, 0 }, // 0x9B + { &opcode_dd_9c, 9 }, // SBC A, IXH + { &opcode_dd_9d, 9 }, // SBC A, IXL + { &opcode_dd_9e, 19 }, // SBC A, (IX + d) + { 0, 0 }, // 0x9F + { 0, 0 }, // 0xA0 + { 0, 0 }, // 0xA1 + { 0, 0 }, // 0xA2 + { 0, 0 }, // 0xA3 + { &opcode_dd_a4, 9 }, // AND IXH + { &opcode_dd_a5, 9 }, // AND IXL + { &opcode_dd_a6, 19 }, // AND (IX + d) + { 0, 0 }, // 0xA7 + { 0, 0 }, // 0xA8 + { 0, 0 }, // 0xA9 + { 0, 0 }, // 0xAA + { 0, 0 }, // 0xAB + { &opcode_dd_ac, 9 }, // XOR IXH + { &opcode_dd_ad, 9 }, // XOR IXL + { &opcode_dd_ae, 19 }, // XOR (IX + d) + { 0, 0 }, // 0xAF + { 0, 0 }, // 0xB0 + { 0, 0 }, // 0xB1 + { 0, 0 }, // 0xB2 + { 0, 0 }, // 0xB3 + { &opcode_dd_b4, 9 }, // OR IXH + { &opcode_dd_b5, 9 }, // OR IXL + { &opcode_dd_b6, 19 }, // OR (IX + d) + { 0, 0 }, // 0xB7 + { 0, 0 }, // 0xB8 + { 0, 0 }, // 0xB9 + { 0, 0 }, // 0xBA + { 0, 0 }, // 0xBB + { &opcode_dd_bc, 9 }, // CP IXH + { &opcode_dd_bd, 9 }, // CP IXL + { &opcode_dd_be, 19 }, // CP (IX + d) + { 0, 0 }, // 0xBF + { 0, 0 }, // 0xC0 + { 0, 0 }, // 0xC1 + { 0, 0 }, // 0xC2 + { 0, 0 }, // 0xC3 + { 0, 0 }, // 0xC4 + { 0, 0 }, // 0xC5 + { 0, 0 }, // 0xC6 + { 0, 0 }, // 0xC7 + { 0, 0 }, // 0xC8 + { 0, 0 }, // 0xC9 + { 0, 0 }, // 0xCA + { &opcode_dd_cb, 0 }, // + { 0, 0 }, // 0xCC + { 0, 0 }, // 0xCD + { 0, 0 }, // 0xCE + { 0, 0 }, // 0xCF + { 0, 0 }, // 0xD0 + { 0, 0 }, // 0xD1 + { 0, 0 }, // 0xD2 + { 0, 0 }, // 0xD3 + { 0, 0 }, // 0xD4 + { 0, 0 }, // 0xD5 + { 0, 0 }, // 0xD6 + { 0, 0 }, // 0xD7 + { 0, 0 }, // 0xD8 + { 0, 0 }, // 0xD9 + { 0, 0 }, // 0xDA + { 0, 0 }, // 0xDB + { 0, 0 }, // 0xDC + { 0, 0 }, // 0xDD + { 0, 0 }, // 0xDE + { 0, 0 }, // 0xDF + { 0, 0 }, // 0xE0 + { &opcode_dd_e1, 14 }, // POP IX + { 0, 0 }, // 0xE2 + { &opcode_dd_e3, 23 }, // EX (SP), IX + { 0, 0 }, // 0xE4 + { &opcode_dd_e5, 15 }, // PUSH IX + { 0, 0 }, // 0xE6 + { 0, 0 }, // 0xE7 + { 0, 0 }, // 0xE8 + { &opcode_dd_e9, 8 }, // JP (IX) + { 0, 0 }, // 0xEA + { 0, 0 }, // 0xEB + { 0, 0 }, // 0xEC + { 0, 0 }, // 0xED + { 0, 0 }, // 0xEE + { 0, 0 }, // 0xEF + { 0, 0 }, // 0xF0 + { 0, 0 }, // 0xF1 + { 0, 0 }, // 0xF2 + { 0, 0 }, // 0xF3 + { 0, 0 }, // 0xF4 + { 0, 0 }, // 0xF5 + { 0, 0 }, // 0xF6 + { 0, 0 }, // 0xF7 + { 0, 0 }, // 0xF8 + { &opcode_dd_f9, 10 }, // LD SP, IX + { 0, 0 }, // 0xFA + { 0, 0 }, // 0xFB + { 0, 0 }, // 0xFC + { 0, 0 }, // 0xFD + { 0, 0 }, // 0xFE + { 0, 0 } // 0xFF +}; + +void opcode_dd_09() // ADD IX, BC +{ + unsigned rr = BC(); + + F &= (Zero | Sign | Parity); + if( ((IX & 0xFFF)+(rr & 0xFFF)) > 0xFFF ) F |= Halfcarry; + IX += rr; + if( IX & 0x10000 ) F |= Carry; +} + +void opcode_dd_19() // ADD IX, DE +{ + unsigned rr = DE(); + + F &= (Zero | Sign | Parity); + if( ((IX & 0xFFF)+(rr & 0xFFF)) > 0xFFF ) F |= Halfcarry; + IX += rr; + if( IX & 0x10000 ) F |= Carry; +} + +void opcode_dd_21() // LD IX, nn +{ + IX = fetchWord(); +} + +void opcode_dd_22() // LD (nn), IX +{ + writeWord( fetchWord(), IX ); +} + +void opcode_dd_23() // INC IX +{ + IX++; +} + +void opcode_dd_24() // INC IXH +{ + IX = (IX & 0xFF) | ((unsigned)incByte( IX >> 8 ) << 8); +} + +void opcode_dd_25() // DEC IXH +{ + IX = (IX & 0xFF) | ((unsigned)decByte( IX >> 8 ) << 8); +} + +void opcode_dd_26() // LD IXH, n +{ + IX = (IX & 0xFF) | ((unsigned)fetchByte() << 8); +} + +void opcode_dd_29() // ADD IX, IX +{ + F &= (Zero | Sign | Parity); + if( IX & 0x800 ) F |= Halfcarry; + IX += IX; + if( IX & 0x10000 ) F |= Carry; +} + +void opcode_dd_2a() // LD IX, (nn) +{ + IX = readWord( fetchWord() ); +} + +void opcode_dd_2b() // DEC IX +{ + IX--; +} + +void opcode_dd_2c() // INC IXL +{ + IX = (IX & 0xFF00) | incByte( IX & 0xFF ); +} + +void opcode_dd_2d() // DEC IXL +{ + IX = (IX & 0xFF00) | decByte( IX & 0xFF ); +} + +void opcode_dd_2e() // LD IXL, n +{ + IX = (IX & 0xFF00) | fetchByte(); +} + +void opcode_dd_34() // INC (IX + d) +{ + unsigned addr = addDispl( IX, fetchByte() ); + + writeByte( addr, incByte( readByte( addr ) ) ); +} + +void opcode_dd_35() // DEC (IX + d) +{ + unsigned addr = addDispl( IX, fetchByte() ); + + writeByte( addr, decByte( readByte( addr ) ) ); +} + +void opcode_dd_36() // LD (IX + d), n +{ + unsigned addr = addDispl( IX, fetchByte() ); + + writeByte( addr, fetchByte() ); +} + +void opcode_dd_39() // ADD IX, SP +{ + F &= (Zero | Sign | Parity); + if( ((IX & 0xFFF)+(SP & 0xFFF)) > 0xFFF ) F |= Halfcarry; + IX += SP; + if( IX & 0x10000 ) F |= Carry; +} + +void opcode_dd_44() // LD B, IXH +{ + B = IX >> 8; +} + +void opcode_dd_45() // LD B, IXL +{ + B = IX & 0xFF; +} + +void opcode_dd_46() // LD B, (IX + d) +{ + B = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_4c() // LD C, IXH +{ + C = IX >> 8; +} + +void opcode_dd_4d() // LD C, IXL +{ + C = IX & 0xFF; +} + +void opcode_dd_4e() // LD C, (IX + d) +{ + C = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_54() // LD D, IXH +{ + D = IX >> 8; +} + +void opcode_dd_55() // LD D, IXL +{ + D = IX & 0xFF; +} + +void opcode_dd_56() // LD D, (IX + d) +{ + D = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_5c() // LD E, IXH +{ + E = IX >> 8; +} + +void opcode_dd_5d() // LD E, IXL +{ + E = IX & 0xFF; +} + +void opcode_dd_5e() // LD E, (IX + d) +{ + E = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_60() // LD IXH, B +{ + IX = (IX & 0xFF) | ((unsigned)B << 8); +} + +void opcode_dd_61() // LD IXH, C +{ + IX = (IX & 0xFF) | ((unsigned)C << 8); +} + +void opcode_dd_62() // LD IXH, D +{ + IX = (IX & 0xFF) | ((unsigned)D << 8); +} + +void opcode_dd_63() // LD IXH, E +{ + IX = (IX & 0xFF) | ((unsigned)E << 8); +} + +void opcode_dd_64() // LD IXH, IXH +{ +} + +void opcode_dd_65() // LD IXH, IXL +{ + IX = (IX & 0xFF) | ((IX << 8) & 0xFF00); +} + +void opcode_dd_66() // LD H, (IX + d) +{ + H = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_67() // LD IXH, A +{ + IX = (IX & 0xFF) | ((unsigned)A << 8); +} + +void opcode_dd_68() // LD IXL, B +{ + IX = (IX & 0xFF00) | B; +} + +void opcode_dd_69() // LD IXL, C +{ + IX = (IX & 0xFF00) | C; +} + +void opcode_dd_6a() // LD IXL, D +{ + IX = (IX & 0xFF00) | D; +} + +void opcode_dd_6b() // LD IXL, E +{ + IX = (IX & 0xFF00) | E; +} + +void opcode_dd_6c() // LD IXL, IXH +{ + IX = (IX & 0xFF00) | ((IX >> 8) & 0xFF); +} + +void opcode_dd_6d() // LD IXL, IXL +{ +} + +void opcode_dd_6e() // LD L, (IX + d) +{ + L = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_6f() // LD IXL, A +{ + IX = (IX & 0xFF00) | A; +} + +void opcode_dd_70() // LD (IX + d), B +{ + writeByte( addDispl(IX,fetchByte()), B ); +} + +void opcode_dd_71() // LD (IX + d), C +{ + writeByte( addDispl(IX,fetchByte()), C ); +} + +void opcode_dd_72() // LD (IX + d), D +{ + writeByte( addDispl(IX,fetchByte()), D ); +} + +void opcode_dd_73() // LD (IX + d), E +{ + writeByte( addDispl(IX,fetchByte()), E ); +} + +void opcode_dd_74() // LD (IX + d), H +{ + writeByte( addDispl(IX,fetchByte()), H ); +} + +void opcode_dd_75() // LD (IX + d), L +{ + writeByte( addDispl(IX,fetchByte()), L ); +} + +void opcode_dd_77() // LD (IX + d), A +{ + writeByte( addDispl(IX,fetchByte()), A ); +} + +void opcode_dd_7c() // LD A, IXH +{ + A = IX >> 8; +} + +void opcode_dd_7d() // LD A, IXL +{ + A = IX & 0xFF; +} + +void opcode_dd_7e() // LD A, (IX + d) +{ + A = readByte( addDispl(IX,fetchByte()) ); +} + +void opcode_dd_84() // ADD A, IXH +{ + addByte( IX >> 8, 0 ); +} + +void opcode_dd_85() // ADD A, IXL +{ + addByte( IX & 0xFF, 0 ); +} + +void opcode_dd_86() // ADD A, (IX + d) +{ + addByte( readByte( addDispl(IX,fetchByte()) ), 0 ); +} + +void opcode_dd_8c() // ADC A, IXH +{ + addByte( IX >> 8, F & Carry ); +} + +void opcode_dd_8d() // ADC A, IXL +{ + addByte( IX & 0xFF, F & Carry ); +} + +void opcode_dd_8e() // ADC A, (IX + d) +{ + addByte( readByte( addDispl(IX,fetchByte()) ), F & Carry ); +} + +void opcode_dd_94() // SUB IXH +{ + A = subByte( IX >> 8, 0 ); +} + +void opcode_dd_95() // SUB IXL +{ + A = subByte( IX & 0xFF, 0 ); +} + +void opcode_dd_96() // SUB (IX + d) +{ + A = subByte( readByte( addDispl(IX,fetchByte()) ), 0 ); +} + +void opcode_dd_9c() // SBC A, IXH +{ + A = subByte( IX >> 8, F & Carry ); +} + +void opcode_dd_9d() // SBC A, IXL +{ + A = subByte( IX & 0xFF, F & Carry ); +} + +void opcode_dd_9e() // SBC A, (IX + d) +{ + A = subByte( readByte( addDispl(IX,fetchByte()) ), F & Carry ); +} + +void opcode_dd_a4() // AND IXH +{ + A &= IX >> 8; + setFlags35PSZ000(); + F |= Halfcarry; +} + +void opcode_dd_a5() // AND IXL +{ + A &= IX & 0xFF; + setFlags35PSZ000(); + F |= Halfcarry; +} + +void opcode_dd_a6() // AND (IX + d) +{ + A &= readByte( addDispl(IX,fetchByte()) ); + setFlags35PSZ000(); + F |= Halfcarry; +} + +void opcode_dd_ac() // XOR IXH +{ + A ^= IX >> 8; + setFlags35PSZ000(); +} + +void opcode_dd_ad() // XOR IXL +{ + A ^= IX & 0xFF; + setFlags35PSZ000(); +} + +void opcode_dd_ae() // XOR (IX + d) +{ + A ^= readByte( addDispl(IX,fetchByte()) ); + setFlags35PSZ000(); +} + +void opcode_dd_b4() // OR IXH +{ + A |= IX >> 8; + setFlags35PSZ000(); +} + +void opcode_dd_b5() // OR IXL +{ + A |= IX & 0xFF; + setFlags35PSZ000(); +} + +void opcode_dd_b6() // OR (IX + d) +{ + A |= readByte( addDispl(IX,fetchByte()) ); + setFlags35PSZ000(); +} + +void opcode_dd_bc() // CP IXH +{ + cmpByte( IX >> 8 ); +} + +void opcode_dd_bd() // CP IXL +{ + cmpByte( IX & 0xFF ); +} + +void opcode_dd_be() // CP (IX + d) +{ + cmpByte( readByte( addDispl(IX,fetchByte()) ) ); +} + +void opcode_dd_cb() // +{ + do_opcode_xycb( IX ); +} + +void opcode_dd_e1() // POP IX +{ + IX = readWord( SP ); + SP += 2; +} + +void opcode_dd_e3() // EX (SP), IX +{ + unsigned ix = IX; + + IX = readWord( SP ); + writeWord( SP, ix ); +} + +void opcode_dd_e5() // PUSH IX +{ + SP -= 2; + writeWord( SP, IX ); +} + +void opcode_dd_e9() // JP (IX) +{ + PC = IX; +} + +void opcode_dd_f9() // LD SP, IX +{ + SP = IX; +} + +OpcodeInfo OpInfoED_[256] = { + { 0, 0 }, // 0x00 + { 0, 0 }, // 0x01 + { 0, 0 }, // 0x02 + { 0, 0 }, // 0x03 + { 0, 0 }, // 0x04 + { 0, 0 }, // 0x05 + { 0, 0 }, // 0x06 + { 0, 0 }, // 0x07 + { 0, 0 }, // 0x08 + { 0, 0 }, // 0x09 + { 0, 0 }, // 0x0A + { 0, 0 }, // 0x0B + { 0, 0 }, // 0x0C + { 0, 0 }, // 0x0D + { 0, 0 }, // 0x0E + { 0, 0 }, // 0x0F + { 0, 0 }, // 0x10 + { 0, 0 }, // 0x11 + { 0, 0 }, // 0x12 + { 0, 0 }, // 0x13 + { 0, 0 }, // 0x14 + { 0, 0 }, // 0x15 + { 0, 0 }, // 0x16 + { 0, 0 }, // 0x17 + { 0, 0 }, // 0x18 + { 0, 0 }, // 0x19 + { 0, 0 }, // 0x1A + { 0, 0 }, // 0x1B + { 0, 0 }, // 0x1C + { 0, 0 }, // 0x1D + { 0, 0 }, // 0x1E + { 0, 0 }, // 0x1F + { 0, 0 }, // 0x20 + { 0, 0 }, // 0x21 + { 0, 0 }, // 0x22 + { 0, 0 }, // 0x23 + { 0, 0 }, // 0x24 + { 0, 0 }, // 0x25 + { 0, 0 }, // 0x26 + { 0, 0 }, // 0x27 + { 0, 0 }, // 0x28 + { 0, 0 }, // 0x29 + { 0, 0 }, // 0x2A + { 0, 0 }, // 0x2B + { 0, 0 }, // 0x2C + { 0, 0 }, // 0x2D + { 0, 0 }, // 0x2E + { 0, 0 }, // 0x2F + { 0, 0 }, // 0x30 + { 0, 0 }, // 0x31 + { 0, 0 }, // 0x32 + { 0, 0 }, // 0x33 + { 0, 0 }, // 0x34 + { 0, 0 }, // 0x35 + { 0, 0 }, // 0x36 + { 0, 0 }, // 0x37 + { 0, 0 }, // 0x38 + { 0, 0 }, // 0x39 + { 0, 0 }, // 0x3A + { 0, 0 }, // 0x3B + { 0, 0 }, // 0x3C + { 0, 0 }, // 0x3D + { 0, 0 }, // 0x3E + { 0, 0 }, // 0x3F + { &opcode_ed_40, 12 }, // IN B, (C) + { &opcode_ed_41, 12 }, // OUT (C), B + { &opcode_ed_42, 15 }, // SBC HL, BC + { &opcode_ed_43, 20 }, // LD (nn), BC + { &opcode_ed_44, 8 }, // NEG + { &opcode_ed_45, 14 }, // RETN + { &opcode_ed_46, 8 }, // IM 0 + { &opcode_ed_47, 9 }, // LD I, A + { &opcode_ed_48, 12 }, // IN C, (C) + { &opcode_ed_49, 12 }, // OUT (C), C + { &opcode_ed_4a, 15 }, // ADC HL, BC + { &opcode_ed_4b, 20 }, // LD BC, (nn) + { &opcode_ed_4c, 8 }, // NEG + { &opcode_ed_4d, 14 }, // RETI + { &opcode_ed_4e, 8 }, // IM 0/1 + { &opcode_ed_4f, 9 }, // LD R, A + { &opcode_ed_50, 12 }, // IN D, (C) + { &opcode_ed_51, 12 }, // OUT (C), D + { &opcode_ed_52, 15 }, // SBC HL, DE + { &opcode_ed_53, 20 }, // LD (nn), DE + { &opcode_ed_54, 8 }, // NEG + { &opcode_ed_55, 14 }, // RETN + { &opcode_ed_56, 8 }, // IM 1 + { &opcode_ed_57, 9 }, // LD A, I + { &opcode_ed_58, 12 }, // IN E, (C) + { &opcode_ed_59, 12 }, // OUT (C), E + { &opcode_ed_5a, 15 }, // ADC HL, DE + { &opcode_ed_5b, 20 }, // LD DE, (nn) + { &opcode_ed_5c, 8 }, // NEG + { &opcode_ed_5d, 14 }, // RETN + { &opcode_ed_5e, 8 }, // IM 2 + { &opcode_ed_5f, 9 }, // LD A, R + { &opcode_ed_60, 12 }, // IN H, (C) + { &opcode_ed_61, 12 }, // OUT (C), H + { &opcode_ed_62, 15 }, // SBC HL, HL + { &opcode_ed_63, 20 }, // LD (nn), HL + { &opcode_ed_64, 8 }, // NEG + { &opcode_ed_65, 14 }, // RETN + { &opcode_ed_66, 8 }, // IM 0 + { &opcode_ed_67, 18 }, // RRD + { &opcode_ed_68, 12 }, // IN L, (C) + { &opcode_ed_69, 12 }, // OUT (C), L + { &opcode_ed_6a, 15 }, // ADC HL, HL + { &opcode_ed_6b, 20 }, // LD HL, (nn) + { &opcode_ed_6c, 8 }, // NEG + { &opcode_ed_6d, 14 }, // RETN + { &opcode_ed_6e, 8 }, // IM 0/1 + { &opcode_ed_6f, 18 }, // RLD + { &opcode_ed_70, 12 }, // IN (C) / IN F, (C) + { &opcode_ed_71, 12 }, // OUT (C), 0 + { &opcode_ed_72, 15 }, // SBC HL, SP + { &opcode_ed_73, 20 }, // LD (nn), SP + { &opcode_ed_74, 8 }, // NEG + { &opcode_ed_75, 14 }, // RETN + { &opcode_ed_76, 8 }, // IM 1 + { 0, 0 }, // 0x77 + { &opcode_ed_78, 12 }, // IN A, (C) + { &opcode_ed_79, 12 }, // OUT (C), A + { &opcode_ed_7a, 15 }, // ADC HL, SP + { &opcode_ed_7b, 20 }, // LD SP, (nn) + { &opcode_ed_7c, 8 }, // NEG + { &opcode_ed_7d, 14 }, // RETN + { &opcode_ed_7e, 8 }, // IM 2 + { 0, 0 }, // 0x7F + { 0, 0 }, // 0x80 + { 0, 0 }, // 0x81 + { 0, 0 }, // 0x82 + { 0, 0 }, // 0x83 + { 0, 0 }, // 0x84 + { 0, 0 }, // 0x85 + { 0, 0 }, // 0x86 + { 0, 0 }, // 0x87 + { 0, 0 }, // 0x88 + { 0, 0 }, // 0x89 + { 0, 0 }, // 0x8A + { 0, 0 }, // 0x8B + { 0, 0 }, // 0x8C + { 0, 0 }, // 0x8D + { 0, 0 }, // 0x8E + { 0, 0 }, // 0x8F + { 0, 0 }, // 0x90 + { 0, 0 }, // 0x91 + { 0, 0 }, // 0x92 + { 0, 0 }, // 0x93 + { 0, 0 }, // 0x94 + { 0, 0 }, // 0x95 + { 0, 0 }, // 0x96 + { 0, 0 }, // 0x97 + { 0, 0 }, // 0x98 + { 0, 0 }, // 0x99 + { 0, 0 }, // 0x9A + { 0, 0 }, // 0x9B + { 0, 0 }, // 0x9C + { 0, 0 }, // 0x9D + { 0, 0 }, // 0x9E + { 0, 0 }, // 0x9F + { &opcode_ed_a0, 16 }, // LDI + { &opcode_ed_a1, 16 }, // CPI + { &opcode_ed_a2, 16 }, // INI + { &opcode_ed_a3, 16 }, // OUTI + { 0, 0 }, // 0xA4 + { 0, 0 }, // 0xA5 + { 0, 0 }, // 0xA6 + { 0, 0 }, // 0xA7 + { &opcode_ed_a8, 16 }, // LDD + { &opcode_ed_a9, 16 }, // CPD + { &opcode_ed_aa, 16 }, // IND + { &opcode_ed_ab, 16 }, // OUTD + { 0, 0 }, // 0xAC + { 0, 0 }, // 0xAD + { 0, 0 }, // 0xAE + { 0, 0 }, // 0xAF + { &opcode_ed_b0, 0 }, // LDIR + { &opcode_ed_b1, 0 }, // CPIR + { &opcode_ed_b2, 0 }, // INIR + { &opcode_ed_b3, 0 }, // OTIR + { 0, 0 }, // 0xB4 + { 0, 0 }, // 0xB5 + { 0, 0 }, // 0xB6 + { 0, 0 }, // 0xB7 + { &opcode_ed_b8, 0 }, // LDDR + { &opcode_ed_b9, 0 }, // CPDR + { &opcode_ed_ba, 0 }, // INDR + { &opcode_ed_bb, 0 }, // OTDR + { 0, 0 }, // 0xBC + { 0, 0 }, // 0xBD + { 0, 0 }, // 0xBE + { 0, 0 }, // 0xBF + { 0, 0 }, // 0xC0 + { 0, 0 }, // 0xC1 + { 0, 0 }, // 0xC2 + { 0, 0 }, // 0xC3 + { 0, 0 }, // 0xC4 + { 0, 0 }, // 0xC5 + { 0, 0 }, // 0xC6 + { 0, 0 }, // 0xC7 + { 0, 0 }, // 0xC8 + { 0, 0 }, // 0xC9 + { 0, 0 }, // 0xCA + { 0, 0 }, // 0xCB + { 0, 0 }, // 0xCC + { 0, 0 }, // 0xCD + { 0, 0 }, // 0xCE + { 0, 0 }, // 0xCF + { 0, 0 }, // 0xD0 + { 0, 0 }, // 0xD1 + { 0, 0 }, // 0xD2 + { 0, 0 }, // 0xD3 + { 0, 0 }, // 0xD4 + { 0, 0 }, // 0xD5 + { 0, 0 }, // 0xD6 + { 0, 0 }, // 0xD7 + { 0, 0 }, // 0xD8 + { 0, 0 }, // 0xD9 + { 0, 0 }, // 0xDA + { 0, 0 }, // 0xDB + { 0, 0 }, // 0xDC + { 0, 0 }, // 0xDD + { 0, 0 }, // 0xDE + { 0, 0 }, // 0xDF + { 0, 0 }, // 0xE0 + { 0, 0 }, // 0xE1 + { 0, 0 }, // 0xE2 + { 0, 0 }, // 0xE3 + { 0, 0 }, // 0xE4 + { 0, 0 }, // 0xE5 + { 0, 0 }, // 0xE6 + { 0, 0 }, // 0xE7 + { 0, 0 }, // 0xE8 + { 0, 0 }, // 0xE9 + { 0, 0 }, // 0xEA + { 0, 0 }, // 0xEB + { 0, 0 }, // 0xEC + { 0, 0 }, // 0xED + { 0, 0 }, // 0xEE + { 0, 0 }, // 0xEF + { 0, 0 }, // 0xF0 + { 0, 0 }, // 0xF1 + { 0, 0 }, // 0xF2 + { 0, 0 }, // 0xF3 + { 0, 0 }, // 0xF4 + { 0, 0 }, // 0xF5 + { 0, 0 }, // 0xF6 + { 0, 0 }, // 0xF7 + { 0, 0 }, // 0xF8 + { 0, 0 }, // 0xF9 + { 0, 0 }, // 0xFA + { 0, 0 }, // 0xFB + { 0, 0 }, // 0xFC + { 0, 0 }, // 0xFD + { 0, 0 }, // 0xFE + { 0, 0 } // 0xFF +}; + +void opcode_ed_40() // IN B, (C) +{ + B = inpReg(); +} + +void opcode_ed_41() // OUT (C), B +{ + writePort( C, B ); +} + +void opcode_ed_42() // SBC HL, BC +{ + unsigned char a; + + a = A; + A = L; L = subByte( C, F & Carry ); + A = H; H = subByte( B, F & Carry ); + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_43() // LD (nn), BC +{ + unsigned addr = fetchWord(); + + writeByte( addr, C ); + writeByte( addr+1, B ); +} + +void opcode_ed_44() // NEG +{ + unsigned char a = A; + + A = 0; + A = subByte( a, 0 ); +} + +void opcode_ed_45() // RETN +{ + retFromSub(); + iflags_ &= ~IFF1; + if( iflags_ & IFF2 ) iflags_ |= IFF1; +} + +void opcode_ed_46() // IM 0 +{ + setInterruptMode( 0 ); +} + +void opcode_ed_47() // LD I, A +{ + I = A; +} + +void opcode_ed_48() // IN C, (C) +{ + C = inpReg(); +} + +void opcode_ed_49() // OUT (C), C +{ + writePort( C, C ); +} + +void opcode_ed_4a() // ADC HL, BC +{ + unsigned char a; + + a = A; + A = L; addByte( C, F & Carry ); L = A; + A = H; addByte( B, F & Carry ); H = A; + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_4b() // LD BC, (nn) +{ + unsigned addr = fetchWord(); + + C = readByte( addr ); + B = readByte( addr+1 ); +} + +void opcode_ed_4c() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_4d() // RETI +{ + retFromSub(); + //onReturnFromInterrupt(); +} + +void opcode_ed_4e() // IM 0/1 +{ + setInterruptMode( 0 ); +} + +void opcode_ed_4f() // LD R, A +{ + R = A; +} + +void opcode_ed_50() // IN D, (C) +{ + D = inpReg(); +} + +void opcode_ed_51() // OUT (C), D +{ + writePort( C, D ); +} + +void opcode_ed_52() // SBC HL, DE +{ + unsigned char a; + + a = A; + A = L; L = subByte( E, F & Carry ); + A = H; H = subByte( D, F & Carry ); + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_53() // LD (nn), DE +{ + unsigned addr = fetchWord(); + + writeByte( addr, E ); + writeByte( addr+1, D ); +} + +void opcode_ed_54() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_55() // RETN +{ + opcode_ed_45(); +} + +void opcode_ed_56() // IM 1 +{ + setInterruptMode( 1 ); +} + +void opcode_ed_57() // LD A, I +{ + A = I; + setFlags35PSZ(); + F &= ~(Halfcarry | Parity | AddSub); + if( iflags_ & IFF2 ) F |= Parity; +} + +void opcode_ed_58() // IN E, (C) +{ + E = inpReg(); +} + +void opcode_ed_59() // OUT (C), E +{ + writePort( C, E ); +} + +void opcode_ed_5a() // ADC HL, DE +{ + unsigned char a; + + a = A; + A = L; addByte( E, F & Carry ); L = A; + A = H; addByte( D, F & Carry ); H = A; + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_5b() // LD DE, (nn) +{ + unsigned addr = fetchWord(); + + E = readByte( addr ); + D = readByte( addr+1 ); +} + +void opcode_ed_5c() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_5d() // RETN +{ + opcode_ed_45(); +} + +void opcode_ed_5e() // IM 2 +{ + setInterruptMode( 2 ); +} + +void opcode_ed_5f() // LD A, R +{ + A = R; + setFlags35PSZ(); + F &= ~(Halfcarry | Parity | AddSub); + if( iflags_ & IFF2 ) F |= Parity; +} + +void opcode_ed_60() // IN H, (C) +{ + H = inpReg(); +} + +void opcode_ed_61() // OUT (C), H +{ + writePort( C, H ); +} + +void opcode_ed_62() // SBC HL, HL +{ + unsigned char a; + + a = A; + A = L; L = subByte( L, F & Carry ); + A = H; H = subByte( H, F & Carry ); + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_63() // LD (nn), HL +{ + unsigned addr = fetchWord(); + + writeByte( addr, L ); + writeByte( addr+1, H ); +} + +void opcode_ed_64() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_65() // RETN +{ + opcode_ed_45(); +} + +void opcode_ed_66() // IM 0 +{ + setInterruptMode( 0 ); +} + +void opcode_ed_67() // RRD +{ + unsigned char x = readByte( HL() ); + + writeByte( HL(), (A << 4) | (x >> 4) ); + A = (A & 0xF0) | (x & 0x0F); + setFlags35PSZ(); + F &= ~(Halfcarry | AddSub); +} + +void opcode_ed_68() // IN L, (C) +{ + L = inpReg(); +} + +void opcode_ed_69() // OUT (C), L +{ + writePort( C, L ); +} + +void opcode_ed_6a() // ADC HL, HL +{ + unsigned char a; + + a = A; + A = L; addByte( L, F & Carry ); L = A; + A = H; addByte( H, F & Carry ); H = A; + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_6b() // LD HL, (nn) +{ + unsigned addr = fetchWord(); + + L = readByte( addr ); + H = readByte( addr+1 ); +} + +void opcode_ed_6c() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_6d() // RETN +{ + opcode_ed_45(); +} + +void opcode_ed_6e() // IM 0/1 +{ + setInterruptMode( 0 ); +} + +void opcode_ed_6f() // RLD +{ + unsigned char x = readByte( HL() ); + + writeByte( HL(), (x << 4) | (A & 0x0F) ); + A = (A & 0xF0) | (x >> 4); + setFlags35PSZ(); + F &= ~(Halfcarry | AddSub); +} + +void opcode_ed_70() // IN (C) / IN F, (C) +{ + inpReg(); +} + +void opcode_ed_71() // OUT (C), 0 +{ + writePort( C, 0 ); +} + +void opcode_ed_72() // SBC HL, SP +{ + unsigned char a; + + a = A; + A = L; L = subByte( SP & 0xFF, F & Carry ); + A = H; H = subByte( (SP >> 8) & 0xFF, F & Carry ); + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_73() // LD (nn), SP +{ + writeWord( fetchWord(), SP ); +} + +void opcode_ed_74() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_75() // RETN +{ + opcode_ed_45(); +} + +void opcode_ed_76() // IM 1 +{ + setInterruptMode( 1 ); +} + +void opcode_ed_78() // IN A, (C) +{ + A = inpReg(); +} + +void opcode_ed_79() // OUT (C), A +{ + writePort( C, A ); +} + +void opcode_ed_7a() // ADC HL, SP +{ + unsigned char a; + + a = A; + A = L; addByte( SP & 0xFF, F & Carry ); L = A; + A = H; addByte( (SP >> 8) & 0xFF, F & Carry ); H = A; + A = a; + if( HL() == 0 ) F |= Zero; else F &= ~Zero; +} + +void opcode_ed_7b() // LD SP, (nn) +{ + SP = readWord( fetchWord() ); +} + +void opcode_ed_7c() // NEG +{ + opcode_ed_44(); +} + +void opcode_ed_7d() // RETN +{ + opcode_ed_45(); +} + +void opcode_ed_7e() // IM 2 +{ + setInterruptMode( 2 ); +} + +void opcode_ed_a0() // LDI +{ + writeByte( DE(), readByte( HL() ) ); + if( ++L == 0 ) ++H; // HL++ + if( ++E == 0 ) ++D; // DE++ + if( C-- == 0 ) --B; // BC-- + F &= ~(Halfcarry | Subtraction | Parity); + if( BC() ) F |= Parity; +} + +void opcode_ed_a1() // CPI +{ + unsigned char f = F; + + cmpByte( readByte( HL() ) ); + if( ++L == 0 ) ++H; // HL++ + if( C-- == 0 ) --B; // BC-- + F = (F & ~(Carry | Parity)) | (f & Carry); + if( BC() ) F |= Parity; +} + +void opcode_ed_a2() // INI +{ + writeByte( HL(), readPort( C ) ); + if( ++L == 0 ) ++H; // HL++ + B = decByte( B ); +} + +void opcode_ed_a3() // OUTI +{ + writePort( C, readByte( HL() ) ); + if( ++L == 0 ) ++H; // HL++ + B = decByte( B ); +} + +void opcode_ed_a8() // LDD +{ + writeByte( DE(), readByte( HL() ) ); + if( L-- == 0 ) --H; // HL-- + if( E-- == 0 ) --D; // DE-- + if( C-- == 0 ) --B; // BC-- + F &= ~(Halfcarry | Subtraction | Parity); + if( BC() ) F |= Parity; +} + +void opcode_ed_a9() // CPD +{ + unsigned char f = F; + + cmpByte( readByte( HL() ) ); + if( L-- == 0 ) --H; // HL-- + if( C-- == 0 ) --B; // BC-- + F = (F & ~(Carry | Parity)) | (f & Carry); + if( BC() ) F |= Parity; +} + +void opcode_ed_aa() // IND +{ + writeByte( HL(), readPort( C ) ); + if( L-- == 0 ) --H; // HL-- + B = decByte( B ); +} + +void opcode_ed_ab() // OUTD +{ + writePort( C, readByte( HL() ) ); + if( L-- == 0 ) --H; // HL-- + B = decByte( B ); +} + +void opcode_ed_b0() // LDIR +{ + opcode_ed_a0(); // LDI + if( F & Parity ) { // After LDI, the Parity flag will be zero when BC=0 + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_b1() // CPIR +{ + opcode_ed_a1(); // CPI + if( (F & Parity) && !(F & Zero) ) { // Parity clear when BC=0, Zero set when A=(HL) + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_b2() // INIR +{ + opcode_ed_a2(); // INI + if( B != 0 ) { + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_b3() // OTIR +{ + opcode_ed_a3(); // OUTI + if( B != 0 ) { + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_b8() // LDDR +{ + opcode_ed_a8(); // LDD + if( F & Parity ) { // After LDD, the Parity flag will be zero when BC=0 + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_b9() // CPDR +{ + opcode_ed_a9(); // CPD + if( (F & Parity) && !(F & Zero) ) { // Parity clear when BC=0, Zero set when A=(HL) + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_ba() // INDR +{ + opcode_ed_aa(); // IND + if( B != 0 ) { + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +void opcode_ed_bb() // OTDR +{ + opcode_ed_ab(); // OUTD + if( B != 0 ) { + cycles_ += 5; + PC -= 2; // Decrement PC so that instruction is re-executed at next step (this allows interrupts to occur) + } +} + +OpcodeInfo OpInfoFD_[256] = { + { 0, 0 }, // 0x00 + { 0, 0 }, // 0x01 + { 0, 0 }, // 0x02 + { 0, 0 }, // 0x03 + { 0, 0 }, // 0x04 + { 0, 0 }, // 0x05 + { 0, 0 }, // 0x06 + { 0, 0 }, // 0x07 + { 0, 0 }, // 0x08 + { &opcode_fd_09, 15 }, // ADD IY, BC + { 0, 0 }, // 0x0A + { 0, 0 }, // 0x0B + { 0, 0 }, // 0x0C + { 0, 0 }, // 0x0D + { 0, 0 }, // 0x0E + { 0, 0 }, // 0x0F + { 0, 0 }, // 0x10 + { 0, 0 }, // 0x11 + { 0, 0 }, // 0x12 + { 0, 0 }, // 0x13 + { 0, 0 }, // 0x14 + { 0, 0 }, // 0x15 + { 0, 0 }, // 0x16 + { 0, 0 }, // 0x17 + { 0, 0 }, // 0x18 + { &opcode_fd_19, 15 }, // ADD IY, DE + { 0, 0 }, // 0x1A + { 0, 0 }, // 0x1B + { 0, 0 }, // 0x1C + { 0, 0 }, // 0x1D + { 0, 0 }, // 0x1E + { 0, 0 }, // 0x1F + { 0, 0 }, // 0x20 + { &opcode_fd_21, 14 }, // LD IY, nn + { &opcode_fd_22, 20 }, // LD (nn), IY + { &opcode_fd_23, 10 }, // INC IY + { &opcode_fd_24, 9 }, // INC IYH + { &opcode_fd_25, 9 }, // DEC IYH + { &opcode_fd_26, 9 }, // LD IYH, n + { 0, 0 }, // 0x27 + { 0, 0 }, // 0x28 + { &opcode_fd_29, 15 }, // ADD IY, IY + { &opcode_fd_2a, 20 }, // LD IY, (nn) + { &opcode_fd_2b, 10 }, // DEC IY + { &opcode_fd_2c, 9 }, // INC IYL + { &opcode_fd_2d, 9 }, // DEC IYL + { &opcode_fd_2e, 9 }, // LD IYL, n + { 0, 0 }, // 0x2F + { 0, 0 }, // 0x30 + { 0, 0 }, // 0x31 + { 0, 0 }, // 0x32 + { 0, 0 }, // 0x33 + { &opcode_fd_34, 23 }, // INC (IY + d) + { &opcode_fd_35, 23 }, // DEC (IY + d) + { &opcode_fd_36, 19 }, // LD (IY + d), n + { 0, 0 }, // 0x37 + { 0, 0 }, // 0x38 + { &opcode_fd_39, 15 }, // ADD IY, SP + { 0, 0 }, // 0x3A + { 0, 0 }, // 0x3B + { 0, 0 }, // 0x3C + { 0, 0 }, // 0x3D + { 0, 0 }, // 0x3E + { 0, 0 }, // 0x3F + { 0, 0 }, // 0x40 + { 0, 0 }, // 0x41 + { 0, 0 }, // 0x42 + { 0, 0 }, // 0x43 + { &opcode_fd_44, 9 }, // LD B, IYH + { &opcode_fd_45, 9 }, // LD B, IYL + { &opcode_fd_46, 19 }, // LD B, (IY + d) + { 0, 0 }, // 0x47 + { 0, 0 }, // 0x48 + { 0, 0 }, // 0x49 + { 0, 0 }, // 0x4A + { 0, 0 }, // 0x4B + { &opcode_fd_4c, 9 }, // LD C, IYH + { &opcode_fd_4d, 9 }, // LD C, IYL + { &opcode_fd_4e, 19 }, // LD C, (IY + d) + { 0, 0 }, // 0x4F + { 0, 0 }, // 0x50 + { 0, 0 }, // 0x51 + { 0, 0 }, // 0x52 + { 0, 0 }, // 0x53 + { &opcode_fd_54, 9 }, // LD D, IYH + { &opcode_fd_55, 9 }, // LD D, IYL + { &opcode_fd_56, 19 }, // LD D, (IY + d) + { 0, 0 }, // 0x57 + { 0, 0 }, // 0x58 + { 0, 0 }, // 0x59 + { 0, 0 }, // 0x5A + { 0, 0 }, // 0x5B + { &opcode_fd_5c, 9 }, // LD E, IYH + { &opcode_fd_5d, 9 }, // LD E, IYL + { &opcode_fd_5e, 19 }, // LD E, (IY + d) + { 0, 0 }, // 0x5F + { &opcode_fd_60, 9 }, // LD IYH, B + { &opcode_fd_61, 9 }, // LD IYH, C + { &opcode_fd_62, 9 }, // LD IYH, D + { &opcode_fd_63, 9 }, // LD IYH, E + { &opcode_fd_64, 9 }, // LD IYH, IYH + { &opcode_fd_65, 9 }, // LD IYH, IYL + { &opcode_fd_66, 9 }, // LD H, (IY + d) + { &opcode_fd_67, 9 }, // LD IYH, A + { &opcode_fd_68, 9 }, // LD IYL, B + { &opcode_fd_69, 9 }, // LD IYL, C + { &opcode_fd_6a, 9 }, // LD IYL, D + { &opcode_fd_6b, 9 }, // LD IYL, E + { &opcode_fd_6c, 9 }, // LD IYL, IYH + { &opcode_fd_6d, 9 }, // LD IYL, IYL + { &opcode_fd_6e, 9 }, // LD L, (IY + d) + { &opcode_fd_6f, 9 }, // LD IYL, A + { &opcode_fd_70, 19 }, // LD (IY + d), B + { &opcode_fd_71, 19 }, // LD (IY + d), C + { &opcode_fd_72, 19 }, // LD (IY + d), D + { &opcode_fd_73, 19 }, // LD (IY + d), E + { &opcode_fd_74, 19 }, // LD (IY + d), H + { &opcode_fd_75, 19 }, // LD (IY + d), L + { 0,19 }, // 0x76 + { &opcode_fd_77, 19 }, // LD (IY + d), A + { 0, 0 }, // 0x78 + { 0, 0 }, // 0x79 + { 0, 0 }, // 0x7A + { 0, 0 }, // 0x7B + { &opcode_fd_7c, 9 }, // LD A, IYH + { &opcode_fd_7d, 9 }, // LD A, IYL + { &opcode_fd_7e, 19 }, // LD A, (IY + d) + { 0, 0 }, // 0x7F + { 0, 0 }, // 0x80 + { 0, 0 }, // 0x81 + { 0, 0 }, // 0x82 + { 0, 0 }, // 0x83 + { &opcode_fd_84, 9 }, // ADD A, IYH + { &opcode_fd_85, 9 }, // ADD A, IYL + { &opcode_fd_86, 19 }, // ADD A, (IY + d) + { 0, 0 }, // 0x87 + { 0, 0 }, // 0x88 + { 0, 0 }, // 0x89 + { 0, 0 }, // 0x8A + { 0, 0 }, // 0x8B + { &opcode_fd_8c, 9 }, // ADC A, IYH + { &opcode_fd_8d, 9 }, // ADC A, IYL + { &opcode_fd_8e, 19 }, // ADC A, (IY + d) + { 0, 0 }, // 0x8F + { 0, 0 }, // 0x90 + { 0, 0 }, // 0x91 + { 0, 0 }, // 0x92 + { 0, 0 }, // 0x93 + { &opcode_fd_94, 9 }, // SUB IYH + { &opcode_fd_95, 9 }, // SUB IYL + { &opcode_fd_96, 19 }, // SUB (IY + d) + { 0, 0 }, // 0x97 + { 0, 0 }, // 0x98 + { 0, 0 }, // 0x99 + { 0, 0 }, // 0x9A + { 0, 0 }, // 0x9B + { &opcode_fd_9c, 9 }, // SBC A, IYH + { &opcode_fd_9d, 9 }, // SBC A, IYL + { &opcode_fd_9e, 19 }, // SBC A, (IY + d) + { 0, 0 }, // 0x9F + { 0, 0 }, // 0xA0 + { 0, 0 }, // 0xA1 + { 0, 0 }, // 0xA2 + { 0, 0 }, // 0xA3 + { &opcode_fd_a4, 9 }, // AND IYH + { &opcode_fd_a5, 9 }, // AND IYL + { &opcode_fd_a6, 19 }, // AND (IY + d) + { 0, 0 }, // 0xA7 + { 0, 0 }, // 0xA8 + { 0, 0 }, // 0xA9 + { 0, 0 }, // 0xAA + { 0, 0 }, // 0xAB + { &opcode_fd_ac, 9 }, // XOR IYH + { &opcode_fd_ad, 9 }, // XOR IYL + { &opcode_fd_ae, 19 }, // XOR (IY + d) + { 0, 0 }, // 0xAF + { 0, 0 }, // 0xB0 + { 0, 0 }, // 0xB1 + { 0, 0 }, // 0xB2 + { 0, 0 }, // 0xB3 + { &opcode_fd_b4, 9 }, // OR IYH + { &opcode_fd_b5, 9 }, // OR IYL + { &opcode_fd_b6, 19 }, // OR (IY + d) + { 0, 0 }, // 0xB7 + { 0, 0 }, // 0xB8 + { 0, 0 }, // 0xB9 + { 0, 0 }, // 0xBA + { 0, 0 }, // 0xBB + { &opcode_fd_bc, 9 }, // CP IYH + { &opcode_fd_bd, 9 }, // CP IYL + { &opcode_fd_be, 19 }, // CP (IY + d) + { 0, 0 }, // 0xBF + { 0, 0 }, // 0xC0 + { 0, 0 }, // 0xC1 + { 0, 0 }, // 0xC2 + { 0, 0 }, // 0xC3 + { 0, 0 }, // 0xC4 + { 0, 0 }, // 0xC5 + { 0, 0 }, // 0xC6 + { 0, 0 }, // 0xC7 + { 0, 0 }, // 0xC8 + { 0, 0 }, // 0xC9 + { 0, 0 }, // 0xCA + { &opcode_fd_cb, 0 }, // + { 0, 0 }, // 0xCC + { 0, 0 }, // 0xCD + { 0, 0 }, // 0xCE + { 0, 0 }, // 0xCF + { 0, 0 }, // 0xD0 + { 0, 0 }, // 0xD1 + { 0, 0 }, // 0xD2 + { 0, 0 }, // 0xD3 + { 0, 0 }, // 0xD4 + { 0, 0 }, // 0xD5 + { 0, 0 }, // 0xD6 + { 0, 0 }, // 0xD7 + { 0, 0 }, // 0xD8 + { 0, 0 }, // 0xD9 + { 0, 0 }, // 0xDA + { 0, 0 }, // 0xDB + { 0, 0 }, // 0xDC + { 0, 0 }, // 0xDD + { 0, 0 }, // 0xDE + { 0, 0 }, // 0xDF + { 0, 0 }, // 0xE0 + { &opcode_fd_e1, 14 }, // POP IY + { 0, 0 }, // 0xE2 + { &opcode_fd_e3, 23 }, // EX (SP), IY + { 0, 0 }, // 0xE4 + { &opcode_fd_e5, 15 }, // PUSH IY + { 0, 0 }, // 0xE6 + { 0, 0 }, // 0xE7 + { 0, 0 }, // 0xE8 + { &opcode_fd_e9, 8 }, // JP (IY) + { 0, 0 }, // 0xEA + { 0, 0 }, // 0xEB + { 0, 0 }, // 0xEC + { 0, 0 }, // 0xED + { 0, 0 }, // 0xEE + { 0, 0 }, // 0xEF + { 0, 0 }, // 0xF0 + { 0, 0 }, // 0xF1 + { 0, 0 }, // 0xF2 + { 0, 0 }, // 0xF3 + { 0, 0 }, // 0xF4 + { 0, 0 }, // 0xF5 + { 0, 0 }, // 0xF6 + { 0, 0 }, // 0xF7 + { 0, 0 }, // 0xF8 + { &opcode_fd_f9, 10 }, // LD SP, IY + { 0, 0 }, // 0xFA + { 0, 0 }, // 0xFB + { 0, 0 }, // 0xFC + { 0, 0 }, // 0xFD + { 0, 0 }, // 0xFE + { 0, 0 } // 0xFF +}; + +void opcode_fd_09() // ADD IY, BC +{ + unsigned rr = BC(); + + F &= (Zero | Sign | Parity); + if( ((IY & 0xFFF)+(rr & 0xFFF)) > 0xFFF ) F |= Halfcarry; + IY += rr; + if( IY & 0x10000 ) F |= Carry; +} + +void opcode_fd_19() // ADD IY, DE +{ + unsigned rr = DE(); + + F &= (Zero | Sign | Parity); + if( ((IY & 0xFFF)+(rr & 0xFFF)) > 0xFFF ) F |= Halfcarry; + IY += rr; + if( IY & 0x10000 ) F |= Carry; +} + +void opcode_fd_21() // LD IY, nn +{ + IY = fetchWord(); +} + +void opcode_fd_22() // LD (nn), IY +{ + writeWord( fetchWord(), IY ); +} + +void opcode_fd_23() // INC IY +{ + IY++; +} + +void opcode_fd_24() // INC IYH +{ + IY = (IY & 0xFF) | ((unsigned)incByte( IY >> 8 ) << 8); +} + +void opcode_fd_25() // DEC IYH +{ + IY = (IY & 0xFF) | ((unsigned)decByte( IY >> 8 ) << 8); +} + +void opcode_fd_26() // LD IYH, n +{ + IY = (IY & 0xFF) | ((unsigned)fetchByte() << 8); +} + +void opcode_fd_29() // ADD IY, IY +{ + F &= (Zero | Sign | Parity); + if( IY & 0x800 ) F |= Halfcarry; + IY += IY; + if( IY & 0x10000 ) F |= Carry; +} + +void opcode_fd_2a() // LD IY, (nn) +{ + IY = readWord( fetchWord() ); +} + +void opcode_fd_2b() // DEC IY +{ + IY--; +} + +void opcode_fd_2c() // INC IYL +{ + IY = (IY & 0xFF00) | incByte( IY & 0xFF ); +} + +void opcode_fd_2d() // DEC IYL +{ + IY = (IY & 0xFF00) | decByte( IY & 0xFF ); +} + +void opcode_fd_2e() // LD IYL, n +{ + IY = (IY & 0xFF00) | fetchByte(); +} + +void opcode_fd_34() // INC (IY + d) +{ + unsigned addr = addDispl( IY, fetchByte() ); + + writeByte( addr, incByte( readByte( addr ) ) ); +} + +void opcode_fd_35() // DEC (IY + d) +{ + unsigned addr = addDispl( IY, fetchByte() ); + + writeByte( addr, decByte( readByte( addr ) ) ); +} + +void opcode_fd_36() // LD (IY + d), n +{ + unsigned addr = addDispl( IY, fetchByte() ); + + writeByte( addr, fetchByte() ); +} + +void opcode_fd_39() // ADD IY, SP +{ + F &= (Zero | Sign | Parity); + if( ((IY & 0xFFF)+(SP & 0xFFF)) > 0xFFF ) F |= Halfcarry; + IY += SP; + if( IY & 0x10000 ) F |= Carry; +} + +void opcode_fd_44() // LD B, IYH +{ + B = IY >> 8; +} + +void opcode_fd_45() // LD B, IYL +{ + B = IY & 0xFF; +} + +void opcode_fd_46() // LD B, (IY + d) +{ + B = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_4c() // LD C, IYH +{ + C = IY >> 8; +} + +void opcode_fd_4d() // LD C, IYL +{ + C = IY & 0xFF; +} + +void opcode_fd_4e() // LD C, (IY + d) +{ + C = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_54() // LD D, IYH +{ + D = IY >> 8; +} + +void opcode_fd_55() // LD D, IYL +{ + D = IY & 0xFF; +} + +void opcode_fd_56() // LD D, (IY + d) +{ + D = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_5c() // LD E, IYH +{ + E = IY >> 8; +} + +void opcode_fd_5d() // LD E, IYL +{ + E = IY & 0xFF; +} + +void opcode_fd_5e() // LD E, (IY + d) +{ + E = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_60() // LD IYH, B +{ + IY = (IY & 0xFF) | ((unsigned)B << 8); +} + +void opcode_fd_61() // LD IYH, C +{ + IY = (IY & 0xFF) | ((unsigned)C << 8); +} + +void opcode_fd_62() // LD IYH, D +{ + IY = (IY & 0xFF) | ((unsigned)D << 8); +} + +void opcode_fd_63() // LD IYH, E +{ + IY = (IY & 0xFF) | ((unsigned)E << 8); +} + +void opcode_fd_64() // LD IYH, IYH +{ +} + +void opcode_fd_65() // LD IYH, IYL +{ + IY = (IY & 0xFF) | ((IY << 8) & 0xFF00); +} + +void opcode_fd_66() // LD H, (IY + d) +{ + H = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_67() // LD IYH, A +{ + IY = (IY & 0xFF) | ((unsigned)A << 8); +} + +void opcode_fd_68() // LD IYL, B +{ + IY = (IY & 0xFF00) | B; +} + +void opcode_fd_69() // LD IYL, C +{ + IY = (IY & 0xFF00) | C; +} + +void opcode_fd_6a() // LD IYL, D +{ + IY = (IY & 0xFF00) | D; +} + +void opcode_fd_6b() // LD IYL, E +{ + IY = (IY & 0xFF00) | E; +} + +void opcode_fd_6c() // LD IYL, IYH +{ + IY = (IY & 0xFF00) | ((IY >> 8) & 0xFF); +} + +void opcode_fd_6d() // LD IYL, IYL +{ +} + +void opcode_fd_6e() // LD L, (IY + d) +{ + L = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_6f() // LD IYL, A +{ + IY = (IY & 0xFF00) | A; +} + +void opcode_fd_70() // LD (IY + d), B +{ + writeByte( addDispl(IY,fetchByte()), B ); +} + +void opcode_fd_71() // LD (IY + d), C +{ + writeByte( addDispl(IY,fetchByte()), C ); +} + +void opcode_fd_72() // LD (IY + d), D +{ + writeByte( addDispl(IY,fetchByte()), D ); +} + +void opcode_fd_73() // LD (IY + d), E +{ + writeByte( addDispl(IY,fetchByte()), E ); +} + +void opcode_fd_74() // LD (IY + d), H +{ + writeByte( addDispl(IY,fetchByte()), H ); +} + +void opcode_fd_75() // LD (IY + d), L +{ + writeByte( addDispl(IY,fetchByte()), L ); +} + +void opcode_fd_77() // LD (IY + d), A +{ + writeByte( addDispl(IY,fetchByte()), A ); +} + +void opcode_fd_7c() // LD A, IYH +{ + A = IY >> 8; +} + +void opcode_fd_7d() // LD A, IYL +{ + A = IY & 0xFF; +} + +void opcode_fd_7e() // LD A, (IY + d) +{ + A = readByte( addDispl(IY,fetchByte()) ); +} + +void opcode_fd_84() // ADD A, IYH +{ + addByte( IY >> 8, 0 ); +} + +void opcode_fd_85() // ADD A, IYL +{ + addByte( IY & 0xFF, 0 ); +} + +void opcode_fd_86() // ADD A, (IY + d) +{ + addByte( readByte( addDispl(IY,fetchByte()) ), 0 ); +} + +void opcode_fd_8c() // ADC A, IYH +{ + addByte( IY >> 8, F & Carry ); +} + +void opcode_fd_8d() // ADC A, IYL +{ + addByte( IY & 0xFF, F & Carry ); +} + +void opcode_fd_8e() // ADC A, (IY + d) +{ + addByte( readByte( addDispl(IY,fetchByte()) ), F & Carry ); +} + +void opcode_fd_94() // SUB IYH +{ + A = subByte( IY >> 8, 0 ); +} + +void opcode_fd_95() // SUB IYL +{ + A = subByte( IY & 0xFF, 0 ); +} + +void opcode_fd_96() // SUB (IY + d) +{ + A = subByte( readByte( addDispl(IY,fetchByte()) ), 0 ); +} + +void opcode_fd_9c() // SBC A, IYH +{ + A = subByte( IY >> 8, F & Carry ); +} + +void opcode_fd_9d() // SBC A, IYL +{ + A = subByte( IY & 0xFF, F & Carry ); +} + +void opcode_fd_9e() // SBC A, (IY + d) +{ + A = subByte( readByte( addDispl(IY,fetchByte()) ), F & Carry ); +} + +void opcode_fd_a4() // AND IYH +{ + A &= IY >> 8; + setFlags35PSZ000(); + F |= Halfcarry; +} + +void opcode_fd_a5() // AND IYL +{ + A &= IY & 0xFF; + setFlags35PSZ000(); + F |= Halfcarry; +} + +void opcode_fd_a6() // AND (IY + d) +{ + A &= readByte( addDispl(IY,fetchByte()) ); + setFlags35PSZ000(); + F |= Halfcarry; +} + +void opcode_fd_ac() // XOR IYH +{ + A ^= IY >> 8; + setFlags35PSZ000(); +} + +void opcode_fd_ad() // XOR IYL +{ + A ^= IY & 0xFF; + setFlags35PSZ000(); +} + +void opcode_fd_ae() // XOR (IY + d) +{ + A ^= readByte( addDispl(IY,fetchByte()) ); + setFlags35PSZ000(); +} + +void opcode_fd_b4() // OR IYH +{ + A |= IY >> 8; + setFlags35PSZ000(); +} + +void opcode_fd_b5() // OR IYL +{ + A |= IY & 0xFF; + setFlags35PSZ000(); +} + +void opcode_fd_b6() // OR (IY + d) +{ + A |= readByte( addDispl(IY,fetchByte()) ); + setFlags35PSZ000(); +} + +void opcode_fd_bc() // CP IYH +{ + cmpByte( IY >> 8 ); +} + +void opcode_fd_bd() // CP IYL +{ + cmpByte( IY & 0xFF ); +} + +void opcode_fd_be() // CP (IY + d) +{ + cmpByte( readByte( addDispl(IY,fetchByte()) ) ); +} + +void opcode_fd_cb() // +{ + do_opcode_xycb( IY ); +} + +void opcode_fd_e1() // POP IY +{ + IY = readWord( SP ); + SP += 2; +} + +void opcode_fd_e3() // EX (SP), IY +{ + unsigned iy = IY; + + IY = readWord( SP ); + writeWord( SP, iy ); +} + +void opcode_fd_e5() // PUSH IY +{ + SP -= 2; + writeWord( SP, IY ); +} + +void opcode_fd_e9() // JP (IY) +{ + PC = IY; +} + +void opcode_fd_f9() // LD SP, IY +{ + SP = IY; +} + +OpcodeInfoXY OpInfoXYCB_[256] = { + { &opcode_xycb_00, 20 }, // LD B, RLC (IX + d) + { &opcode_xycb_01, 20 }, // LD C, RLC (IX + d) + { &opcode_xycb_02, 20 }, // LD D, RLC (IX + d) + { &opcode_xycb_03, 20 }, // LD E, RLC (IX + d) + { &opcode_xycb_04, 20 }, // LD H, RLC (IX + d) + { &opcode_xycb_05, 20 }, // LD L, RLC (IX + d) + { &opcode_xycb_06, 20 }, // RLC (IX + d) + { &opcode_xycb_07, 20 }, // LD A, RLC (IX + d) + { &opcode_xycb_08, 20 }, // LD B, RRC (IX + d) + { &opcode_xycb_09, 20 }, // LD C, RRC (IX + d) + { &opcode_xycb_0a, 20 }, // LD D, RRC (IX + d) + { &opcode_xycb_0b, 20 }, // LD E, RRC (IX + d) + { &opcode_xycb_0c, 20 }, // LD H, RRC (IX + d) + { &opcode_xycb_0d, 20 }, // LD L, RRC (IX + d) + { &opcode_xycb_0e, 20 }, // RRC (IX + d) + { &opcode_xycb_0f, 20 }, // LD A, RRC (IX + d) + { &opcode_xycb_10, 20 }, // LD B, RL (IX + d) + { &opcode_xycb_11, 20 }, // LD C, RL (IX + d) + { &opcode_xycb_12, 20 }, // LD D, RL (IX + d) + { &opcode_xycb_13, 20 }, // LD E, RL (IX + d) + { &opcode_xycb_14, 20 }, // LD H, RL (IX + d) + { &opcode_xycb_15, 20 }, // LD L, RL (IX + d) + { &opcode_xycb_16, 20 }, // RL (IX + d) + { &opcode_xycb_17, 20 }, // LD A, RL (IX + d) + { &opcode_xycb_18, 20 }, // LD B, RR (IX + d) + { &opcode_xycb_19, 20 }, // LD C, RR (IX + d) + { &opcode_xycb_1a, 20 }, // LD D, RR (IX + d) + { &opcode_xycb_1b, 20 }, // LD E, RR (IX + d) + { &opcode_xycb_1c, 20 }, // LD H, RR (IX + d) + { &opcode_xycb_1d, 20 }, // LD L, RR (IX + d) + { &opcode_xycb_1e, 20 }, // RR (IX + d) + { &opcode_xycb_1f, 20 }, // LD A, RR (IX + d) + { &opcode_xycb_20, 20 }, // LD B, SLA (IX + d) + { &opcode_xycb_21, 20 }, // LD C, SLA (IX + d) + { &opcode_xycb_22, 20 }, // LD D, SLA (IX + d) + { &opcode_xycb_23, 20 }, // LD E, SLA (IX + d) + { &opcode_xycb_24, 20 }, // LD H, SLA (IX + d) + { &opcode_xycb_25, 20 }, // LD L, SLA (IX + d) + { &opcode_xycb_26, 20 }, // SLA (IX + d) + { &opcode_xycb_27, 20 }, // LD A, SLA (IX + d) + { &opcode_xycb_28, 20 }, // LD B, SRA (IX + d) + { &opcode_xycb_29, 20 }, // LD C, SRA (IX + d) + { &opcode_xycb_2a, 20 }, // LD D, SRA (IX + d) + { &opcode_xycb_2b, 20 }, // LD E, SRA (IX + d) + { &opcode_xycb_2c, 20 }, // LD H, SRA (IX + d) + { &opcode_xycb_2d, 20 }, // LD L, SRA (IX + d) + { &opcode_xycb_2e, 20 }, // SRA (IX + d) + { &opcode_xycb_2f, 20 }, // LD A, SRA (IX + d) + { &opcode_xycb_30, 20 }, // LD B, SLL (IX + d) + { &opcode_xycb_31, 20 }, // LD C, SLL (IX + d) + { &opcode_xycb_32, 20 }, // LD D, SLL (IX + d) + { &opcode_xycb_33, 20 }, // LD E, SLL (IX + d) + { &opcode_xycb_34, 20 }, // LD H, SLL (IX + d) + { &opcode_xycb_35, 20 }, // LD L, SLL (IX + d) + { &opcode_xycb_36, 20 }, // SLL (IX + d) + { &opcode_xycb_37, 20 }, // LD A, SLL (IX + d) + { &opcode_xycb_38, 20 }, // LD B, SRL (IX + d) + { &opcode_xycb_39, 20 }, // LD C, SRL (IX + d) + { &opcode_xycb_3a, 20 }, // LD D, SRL (IX + d) + { &opcode_xycb_3b, 20 }, // LD E, SRL (IX + d) + { &opcode_xycb_3c, 20 }, // LD H, SRL (IX + d) + { &opcode_xycb_3d, 20 }, // LD L, SRL (IX + d) + { &opcode_xycb_3e, 20 }, // SRL (IX + d) + { &opcode_xycb_3f, 20 }, // LD A, SRL (IX + d) + { &opcode_xycb_40, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_41, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_42, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_43, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_44, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_45, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_46, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_47, 20 }, // BIT 0, (IX + d) + { &opcode_xycb_48, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_49, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_4a, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_4b, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_4c, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_4d, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_4e, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_4f, 20 }, // BIT 1, (IX + d) + { &opcode_xycb_50, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_51, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_52, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_53, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_54, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_55, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_56, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_57, 20 }, // BIT 2, (IX + d) + { &opcode_xycb_58, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_59, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_5a, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_5b, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_5c, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_5d, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_5e, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_5f, 20 }, // BIT 3, (IX + d) + { &opcode_xycb_60, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_61, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_62, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_63, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_64, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_65, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_66, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_67, 20 }, // BIT 4, (IX + d) + { &opcode_xycb_68, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_69, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_6a, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_6b, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_6c, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_6d, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_6e, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_6f, 20 }, // BIT 5, (IX + d) + { &opcode_xycb_70, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_71, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_72, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_73, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_74, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_75, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_76, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_77, 20 }, // BIT 6, (IX + d) + { &opcode_xycb_78, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_79, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_7a, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_7b, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_7c, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_7d, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_7e, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_7f, 20 }, // BIT 7, (IX + d) + { &opcode_xycb_80, 20 }, // LD B, RES 0, (IX + d) + { &opcode_xycb_81, 20 }, // LD C, RES 0, (IX + d) + { &opcode_xycb_82, 20 }, // LD D, RES 0, (IX + d) + { &opcode_xycb_83, 20 }, // LD E, RES 0, (IX + d) + { &opcode_xycb_84, 20 }, // LD H, RES 0, (IX + d) + { &opcode_xycb_85, 20 }, // LD L, RES 0, (IX + d) + { &opcode_xycb_86, 20 }, // RES 0, (IX + d) + { &opcode_xycb_87, 20 }, // LD A, RES 0, (IX + d) + { &opcode_xycb_88, 20 }, // LD B, RES 1, (IX + d) + { &opcode_xycb_89, 20 }, // LD C, RES 1, (IX + d) + { &opcode_xycb_8a, 20 }, // LD D, RES 1, (IX + d) + { &opcode_xycb_8b, 20 }, // LD E, RES 1, (IX + d) + { &opcode_xycb_8c, 20 }, // LD H, RES 1, (IX + d) + { &opcode_xycb_8d, 20 }, // LD L, RES 1, (IX + d) + { &opcode_xycb_8e, 20 }, // RES 1, (IX + d) + { &opcode_xycb_8f, 20 }, // LD A, RES 1, (IX + d) + { &opcode_xycb_90, 20 }, // LD B, RES 2, (IX + d) + { &opcode_xycb_91, 20 }, // LD C, RES 2, (IX + d) + { &opcode_xycb_92, 20 }, // LD D, RES 2, (IX + d) + { &opcode_xycb_93, 20 }, // LD E, RES 2, (IX + d) + { &opcode_xycb_94, 20 }, // LD H, RES 2, (IX + d) + { &opcode_xycb_95, 20 }, // LD L, RES 2, (IX + d) + { &opcode_xycb_96, 20 }, // RES 2, (IX + d) + { &opcode_xycb_97, 20 }, // LD A, RES 2, (IX + d) + { &opcode_xycb_98, 20 }, // LD B, RES 3, (IX + d) + { &opcode_xycb_99, 20 }, // LD C, RES 3, (IX + d) + { &opcode_xycb_9a, 20 }, // LD D, RES 3, (IX + d) + { &opcode_xycb_9b, 20 }, // LD E, RES 3, (IX + d) + { &opcode_xycb_9c, 20 }, // LD H, RES 3, (IX + d) + { &opcode_xycb_9d, 20 }, // LD L, RES 3, (IX + d) + { &opcode_xycb_9e, 20 }, // RES 3, (IX + d) + { &opcode_xycb_9f, 20 }, // LD A, RES 3, (IX + d) + { &opcode_xycb_a0, 20 }, // LD B, RES 4, (IX + d) + { &opcode_xycb_a1, 20 }, // LD C, RES 4, (IX + d) + { &opcode_xycb_a2, 20 }, // LD D, RES 4, (IX + d) + { &opcode_xycb_a3, 20 }, // LD E, RES 4, (IX + d) + { &opcode_xycb_a4, 20 }, // LD H, RES 4, (IX + d) + { &opcode_xycb_a5, 20 }, // LD L, RES 4, (IX + d) + { &opcode_xycb_a6, 20 }, // RES 4, (IX + d) + { &opcode_xycb_a7, 20 }, // LD A, RES 4, (IX + d) + { &opcode_xycb_a8, 20 }, // LD B, RES 5, (IX + d) + { &opcode_xycb_a9, 20 }, // LD C, RES 5, (IX + d) + { &opcode_xycb_aa, 20 }, // LD D, RES 5, (IX + d) + { &opcode_xycb_ab, 20 }, // LD E, RES 5, (IX + d) + { &opcode_xycb_ac, 20 }, // LD H, RES 5, (IX + d) + { &opcode_xycb_ad, 20 }, // LD L, RES 5, (IX + d) + { &opcode_xycb_ae, 20 }, // RES 5, (IX + d) + { &opcode_xycb_af, 20 }, // LD A, RES 5, (IX + d) + { &opcode_xycb_b0, 20 }, // LD B, RES 6, (IX + d) + { &opcode_xycb_b1, 20 }, // LD C, RES 6, (IX + d) + { &opcode_xycb_b2, 20 }, // LD D, RES 6, (IX + d) + { &opcode_xycb_b3, 20 }, // LD E, RES 6, (IX + d) + { &opcode_xycb_b4, 20 }, // LD H, RES 6, (IX + d) + { &opcode_xycb_b5, 20 }, // LD L, RES 6, (IX + d) + { &opcode_xycb_b6, 20 }, // RES 6, (IX + d) + { &opcode_xycb_b7, 20 }, // LD A, RES 6, (IX + d) + { &opcode_xycb_b8, 20 }, // LD B, RES 7, (IX + d) + { &opcode_xycb_b9, 20 }, // LD C, RES 7, (IX + d) + { &opcode_xycb_ba, 20 }, // LD D, RES 7, (IX + d) + { &opcode_xycb_bb, 20 }, // LD E, RES 7, (IX + d) + { &opcode_xycb_bc, 20 }, // LD H, RES 7, (IX + d) + { &opcode_xycb_bd, 20 }, // LD L, RES 7, (IX + d) + { &opcode_xycb_be, 20 }, // RES 7, (IX + d) + { &opcode_xycb_bf, 20 }, // LD A, RES 7, (IX + d) + { &opcode_xycb_c0, 20 }, // LD B, SET 0, (IX + d) + { &opcode_xycb_c1, 20 }, // LD C, SET 0, (IX + d) + { &opcode_xycb_c2, 20 }, // LD D, SET 0, (IX + d) + { &opcode_xycb_c3, 20 }, // LD E, SET 0, (IX + d) + { &opcode_xycb_c4, 20 }, // LD H, SET 0, (IX + d) + { &opcode_xycb_c5, 20 }, // LD L, SET 0, (IX + d) + { &opcode_xycb_c6, 20 }, // SET 0, (IX + d) + { &opcode_xycb_c7, 20 }, // LD A, SET 0, (IX + d) + { &opcode_xycb_c8, 20 }, // LD B, SET 1, (IX + d) + { &opcode_xycb_c9, 20 }, // LD C, SET 1, (IX + d) + { &opcode_xycb_ca, 20 }, // LD D, SET 1, (IX + d) + { &opcode_xycb_cb, 20 }, // LD E, SET 1, (IX + d) + { &opcode_xycb_cc, 20 }, // LD H, SET 1, (IX + d) + { &opcode_xycb_cd, 20 }, // LD L, SET 1, (IX + d) + { &opcode_xycb_ce, 20 }, // SET 1, (IX + d) + { &opcode_xycb_cf, 20 }, // LD A, SET 1, (IX + d) + { &opcode_xycb_d0, 20 }, // LD B, SET 2, (IX + d) + { &opcode_xycb_d1, 20 }, // LD C, SET 2, (IX + d) + { &opcode_xycb_d2, 20 }, // LD D, SET 2, (IX + d) + { &opcode_xycb_d3, 20 }, // LD E, SET 2, (IX + d) + { &opcode_xycb_d4, 20 }, // LD H, SET 2, (IX + d) + { &opcode_xycb_d5, 20 }, // LD L, SET 2, (IX + d) + { &opcode_xycb_d6, 20 }, // SET 2, (IX + d) + { &opcode_xycb_d7, 20 }, // LD A, SET 2, (IX + d) + { &opcode_xycb_d8, 20 }, // LD B, SET 3, (IX + d) + { &opcode_xycb_d9, 20 }, // LD C, SET 3, (IX + d) + { &opcode_xycb_da, 20 }, // LD D, SET 3, (IX + d) + { &opcode_xycb_db, 20 }, // LD E, SET 3, (IX + d) + { &opcode_xycb_dc, 20 }, // LD H, SET 3, (IX + d) + { &opcode_xycb_dd, 20 }, // LD L, SET 3, (IX + d) + { &opcode_xycb_de, 20 }, // SET 3, (IX + d) + { &opcode_xycb_df, 20 }, // LD A, SET 3, (IX + d) + { &opcode_xycb_e0, 20 }, // LD B, SET 4, (IX + d) + { &opcode_xycb_e1, 20 }, // LD C, SET 4, (IX + d) + { &opcode_xycb_e2, 20 }, // LD D, SET 4, (IX + d) + { &opcode_xycb_e3, 20 }, // LD E, SET 4, (IX + d) + { &opcode_xycb_e4, 20 }, // LD H, SET 4, (IX + d) + { &opcode_xycb_e5, 20 }, // LD L, SET 4, (IX + d) + { &opcode_xycb_e6, 20 }, // SET 4, (IX + d) + { &opcode_xycb_e7, 20 }, // LD A, SET 4, (IX + d) + { &opcode_xycb_e8, 20 }, // LD B, SET 5, (IX + d) + { &opcode_xycb_e9, 20 }, // LD C, SET 5, (IX + d) + { &opcode_xycb_ea, 20 }, // LD D, SET 5, (IX + d) + { &opcode_xycb_eb, 20 }, // LD E, SET 5, (IX + d) + { &opcode_xycb_ec, 20 }, // LD H, SET 5, (IX + d) + { &opcode_xycb_ed, 20 }, // LD L, SET 5, (IX + d) + { &opcode_xycb_ee, 20 }, // SET 5, (IX + d) + { &opcode_xycb_ef, 20 }, // LD A, SET 5, (IX + d) + { &opcode_xycb_f0, 20 }, // LD B, SET 6, (IX + d) + { &opcode_xycb_f1, 20 }, // LD C, SET 6, (IX + d) + { &opcode_xycb_f2, 20 }, // LD D, SET 6, (IX + d) + { &opcode_xycb_f3, 20 }, // LD E, SET 6, (IX + d) + { &opcode_xycb_f4, 20 }, // LD H, SET 6, (IX + d) + { &opcode_xycb_f5, 20 }, // LD L, SET 6, (IX + d) + { &opcode_xycb_f6, 20 }, // SET 6, (IX + d) + { &opcode_xycb_f7, 20 }, // LD A, SET 6, (IX + d) + { &opcode_xycb_f8, 20 }, // LD B, SET 7, (IX + d) + { &opcode_xycb_f9, 20 }, // LD C, SET 7, (IX + d) + { &opcode_xycb_fa, 20 }, // LD D, SET 7, (IX + d) + { &opcode_xycb_fb, 20 }, // LD E, SET 7, (IX + d) + { &opcode_xycb_fc, 20 }, // LD H, SET 7, (IX + d) + { &opcode_xycb_fd, 20 }, // LD L, SET 7, (IX + d) + { &opcode_xycb_fe, 20 }, // SET 7, (IX + d) + { &opcode_xycb_ff, 20 } // LD A, SET 7, (IX + d) +}; + +unsigned do_opcode_xycb( unsigned xy ) +{ + xy = addDispl( xy, fetchByte() ); + + unsigned op = fetchByte(); + + cycles_ += OpInfoXYCB_[ op ].cycles; + + OpInfoXYCB_[ op ].handler( xy ); + + return xy; +} + +void opcode_xycb_00( unsigned xy ) // LD B, RLC (IX + d) +{ + B = rotateLeftCarry( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_01( unsigned xy ) // LD C, RLC (IX + d) +{ + C = rotateLeftCarry( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_02( unsigned xy ) // LD D, RLC (IX + d) +{ + D = rotateLeftCarry( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_03( unsigned xy ) // LD E, RLC (IX + d) +{ + E = rotateLeftCarry( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_04( unsigned xy ) // LD H, RLC (IX + d) +{ + H = rotateLeftCarry( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_05( unsigned xy ) // LD L, RLC (IX + d) +{ + L = rotateLeftCarry( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_06( unsigned xy ) // RLC (IX + d) +{ + writeByte( xy, rotateLeftCarry( readByte(xy) ) ); +} + +void opcode_xycb_07( unsigned xy ) // LD A, RLC (IX + d) +{ + A = rotateLeftCarry( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_08( unsigned xy ) // LD B, RRC (IX + d) +{ + B = rotateRightCarry( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_09( unsigned xy ) // LD C, RRC (IX + d) +{ + C = rotateRightCarry( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_0a( unsigned xy ) // LD D, RRC (IX + d) +{ + D = rotateRightCarry( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_0b( unsigned xy ) // LD E, RRC (IX + d) +{ + E = rotateRightCarry( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_0c( unsigned xy ) // LD H, RRC (IX + d) +{ + H = rotateRightCarry( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_0d( unsigned xy ) // LD L, RRC (IX + d) +{ + L = rotateRightCarry( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_0e( unsigned xy ) // RRC (IX + d) +{ + writeByte( xy, rotateRightCarry( readByte(xy) ) ); +} + +void opcode_xycb_0f( unsigned xy ) // LD A, RRC (IX + d) +{ + A = rotateRightCarry( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_10( unsigned xy ) // LD B, RL (IX + d) +{ + B = rotateLeft( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_11( unsigned xy ) // LD C, RL (IX + d) +{ + C = rotateLeft( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_12( unsigned xy ) // LD D, RL (IX + d) +{ + D = rotateLeft( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_13( unsigned xy ) // LD E, RL (IX + d) +{ + E = rotateLeft( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_14( unsigned xy ) // LD H, RL (IX + d) +{ + H = rotateLeft( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_15( unsigned xy ) // LD L, RL (IX + d) +{ + L = rotateLeft( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_16( unsigned xy ) // RL (IX + d) +{ + writeByte( xy, rotateLeft( readByte(xy) ) ); +} + +void opcode_xycb_17( unsigned xy ) // LD A, RL (IX + d) +{ + A = rotateLeft( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_18( unsigned xy ) // LD B, RR (IX + d) +{ + B = rotateRight( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_19( unsigned xy ) // LD C, RR (IX + d) +{ + C = rotateRight( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_1a( unsigned xy ) // LD D, RR (IX + d) +{ + D = rotateRight( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_1b( unsigned xy ) // LD E, RR (IX + d) +{ + E = rotateRight( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_1c( unsigned xy ) // LD H, RR (IX + d) +{ + H = rotateRight( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_1d( unsigned xy ) // LD L, RR (IX + d) +{ + L = rotateRight( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_1e( unsigned xy ) // RR (IX + d) +{ + writeByte( xy, rotateRight( readByte(xy) ) ); +} + +void opcode_xycb_1f( unsigned xy ) // LD A, RR (IX + d) +{ + A = rotateRight( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_20( unsigned xy ) // LD B, SLA (IX + d) +{ + B = shiftLeft( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_21( unsigned xy ) // LD C, SLA (IX + d) +{ + C = shiftLeft( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_22( unsigned xy ) // LD D, SLA (IX + d) +{ + D = shiftLeft( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_23( unsigned xy ) // LD E, SLA (IX + d) +{ + E = shiftLeft( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_24( unsigned xy ) // LD H, SLA (IX + d) +{ + H = shiftLeft( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_25( unsigned xy ) // LD L, SLA (IX + d) +{ + L = shiftLeft( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_26( unsigned xy ) // SLA (IX + d) +{ + writeByte( xy, shiftLeft( readByte(xy) ) ); +} + +void opcode_xycb_27( unsigned xy ) // LD A, SLA (IX + d) +{ + A = shiftLeft( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_28( unsigned xy ) // LD B, SRA (IX + d) +{ + B = shiftRightArith( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_29( unsigned xy ) // LD C, SRA (IX + d) +{ + C = shiftRightArith( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_2a( unsigned xy ) // LD D, SRA (IX + d) +{ + D = shiftRightArith( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_2b( unsigned xy ) // LD E, SRA (IX + d) +{ + E = shiftRightArith( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_2c( unsigned xy ) // LD H, SRA (IX + d) +{ + H = shiftRightArith( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_2d( unsigned xy ) // LD L, SRA (IX + d) +{ + L = shiftRightArith( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_2e( unsigned xy ) // SRA (IX + d) +{ + writeByte( xy, shiftRightArith( readByte(xy) ) ); +} + +void opcode_xycb_2f( unsigned xy ) // LD A, SRA (IX + d) +{ + A = shiftRightArith( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_30( unsigned xy ) // LD B, SLL (IX + d) +{ + B = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, B ); +} + +void opcode_xycb_31( unsigned xy ) // LD C, SLL (IX + d) +{ + C = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, C ); +} + +void opcode_xycb_32( unsigned xy ) // LD D, SLL (IX + d) +{ + D = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, D ); +} + +void opcode_xycb_33( unsigned xy ) // LD E, SLL (IX + d) +{ + E = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, E ); +} + +void opcode_xycb_34( unsigned xy ) // LD H, SLL (IX + d) +{ + H = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, H ); +} + +void opcode_xycb_35( unsigned xy ) // LD L, SLL (IX + d) +{ + L = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, L ); +} + +void opcode_xycb_36( unsigned xy ) // SLL (IX + d) +{ + writeByte( xy, shiftLeft( readByte(xy) ) | 0x01 ); +} + +void opcode_xycb_37( unsigned xy ) // LD A, SLL (IX + d) +{ + A = shiftLeft( readByte(xy) ) | 0x01; + writeByte( xy, A ); +} + +void opcode_xycb_38( unsigned xy ) // LD B, SRL (IX + d) +{ + B = shiftRightLogical( readByte(xy) ); + writeByte( xy, B ); +} + +void opcode_xycb_39( unsigned xy ) // LD C, SRL (IX + d) +{ + C = shiftRightLogical( readByte(xy) ); + writeByte( xy, C ); +} + +void opcode_xycb_3a( unsigned xy ) // LD D, SRL (IX + d) +{ + D = shiftRightLogical( readByte(xy) ); + writeByte( xy, D ); +} + +void opcode_xycb_3b( unsigned xy ) // LD E, SRL (IX + d) +{ + E = shiftRightLogical( readByte(xy) ); + writeByte( xy, E ); +} + +void opcode_xycb_3c( unsigned xy ) // LD H, SRL (IX + d) +{ + H = shiftRightLogical( readByte(xy) ); + writeByte( xy, H ); +} + +void opcode_xycb_3d( unsigned xy ) // LD L, SRL (IX + d) +{ + L = shiftRightLogical( readByte(xy) ); + writeByte( xy, L ); +} + +void opcode_xycb_3e( unsigned xy ) // SRL (IX + d) +{ + writeByte( xy, shiftRightLogical( readByte(xy) ) ); +} + +void opcode_xycb_3f( unsigned xy ) // LD A, SRL (IX + d) +{ + A = shiftRightLogical( readByte(xy) ); + writeByte( xy, A ); +} + +void opcode_xycb_40( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_41( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_42( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_43( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_44( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_45( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_46( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_47( unsigned xy ) // BIT 0, (IX + d) +{ + testBit( 0, readByte( xy ) ); +} + +void opcode_xycb_48( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_49( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_4a( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_4b( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_4c( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_4d( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_4e( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_4f( unsigned xy ) // BIT 1, (IX + d) +{ + testBit( 1, readByte( xy ) ); +} + +void opcode_xycb_50( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_51( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_52( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_53( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_54( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_55( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_56( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_57( unsigned xy ) // BIT 2, (IX + d) +{ + testBit( 2, readByte( xy ) ); +} + +void opcode_xycb_58( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_59( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_5a( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_5b( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_5c( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_5d( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_5e( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_5f( unsigned xy ) // BIT 3, (IX + d) +{ + testBit( 3, readByte( xy ) ); +} + +void opcode_xycb_60( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_61( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_62( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_63( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_64( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_65( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_66( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_67( unsigned xy ) // BIT 4, (IX + d) +{ + testBit( 4, readByte( xy ) ); +} + +void opcode_xycb_68( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_69( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_6a( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_6b( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_6c( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_6d( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_6e( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_6f( unsigned xy ) // BIT 5, (IX + d) +{ + testBit( 5, readByte( xy ) ); +} + +void opcode_xycb_70( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_71( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_72( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_73( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_74( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_75( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_76( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_77( unsigned xy ) // BIT 6, (IX + d) +{ + testBit( 6, readByte( xy ) ); +} + +void opcode_xycb_78( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_79( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_7a( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_7b( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_7c( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_7d( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_7e( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_7f( unsigned xy ) // BIT 7, (IX + d) +{ + testBit( 7, readByte( xy ) ); +} + +void opcode_xycb_80( unsigned xy ) // LD B, RES 0, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, B ); +} + +void opcode_xycb_81( unsigned xy ) // LD C, RES 0, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, C ); +} + +void opcode_xycb_82( unsigned xy ) // LD D, RES 0, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, D ); +} + +void opcode_xycb_83( unsigned xy ) // LD E, RES 0, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, E ); +} + +void opcode_xycb_84( unsigned xy ) // LD H, RES 0, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, H ); +} + +void opcode_xycb_85( unsigned xy ) // LD L, RES 0, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, L ); +} + +void opcode_xycb_86( unsigned xy ) // RES 0, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 0) ); +} + +void opcode_xycb_87( unsigned xy ) // LD A, RES 0, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 0); + writeByte( xy, A ); +} + +void opcode_xycb_88( unsigned xy ) // LD B, RES 1, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, B ); +} + +void opcode_xycb_89( unsigned xy ) // LD C, RES 1, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, C ); +} + +void opcode_xycb_8a( unsigned xy ) // LD D, RES 1, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, D ); +} + +void opcode_xycb_8b( unsigned xy ) // LD E, RES 1, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, E ); +} + +void opcode_xycb_8c( unsigned xy ) // LD H, RES 1, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, H ); +} + +void opcode_xycb_8d( unsigned xy ) // LD L, RES 1, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, L ); +} + +void opcode_xycb_8e( unsigned xy ) // RES 1, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 1) ); +} + +void opcode_xycb_8f( unsigned xy ) // LD A, RES 1, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 1); + writeByte( xy, A ); +} + +void opcode_xycb_90( unsigned xy ) // LD B, RES 2, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, B ); +} + +void opcode_xycb_91( unsigned xy ) // LD C, RES 2, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, C ); +} + +void opcode_xycb_92( unsigned xy ) // LD D, RES 2, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, D ); +} + +void opcode_xycb_93( unsigned xy ) // LD E, RES 2, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, E ); +} + +void opcode_xycb_94( unsigned xy ) // LD H, RES 2, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, H ); +} + +void opcode_xycb_95( unsigned xy ) // LD L, RES 2, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, L ); +} + +void opcode_xycb_96( unsigned xy ) // RES 2, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 2) ); +} + +void opcode_xycb_97( unsigned xy ) // LD A, RES 2, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 2); + writeByte( xy, A ); +} + +void opcode_xycb_98( unsigned xy ) // LD B, RES 3, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, B ); +} + +void opcode_xycb_99( unsigned xy ) // LD C, RES 3, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, C ); +} + +void opcode_xycb_9a( unsigned xy ) // LD D, RES 3, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, D ); +} + +void opcode_xycb_9b( unsigned xy ) // LD E, RES 3, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, E ); +} + +void opcode_xycb_9c( unsigned xy ) // LD H, RES 3, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, H ); +} + +void opcode_xycb_9d( unsigned xy ) // LD L, RES 3, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, L ); +} + +void opcode_xycb_9e( unsigned xy ) // RES 3, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 3) ); +} + +void opcode_xycb_9f( unsigned xy ) // LD A, RES 3, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 3); + writeByte( xy, A ); +} + +void opcode_xycb_a0( unsigned xy ) // LD B, RES 4, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, B ); +} + +void opcode_xycb_a1( unsigned xy ) // LD C, RES 4, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, C ); +} + +void opcode_xycb_a2( unsigned xy ) // LD D, RES 4, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, D ); +} + +void opcode_xycb_a3( unsigned xy ) // LD E, RES 4, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, E ); +} + +void opcode_xycb_a4( unsigned xy ) // LD H, RES 4, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, H ); +} + +void opcode_xycb_a5( unsigned xy ) // LD L, RES 4, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, L ); +} + +void opcode_xycb_a6( unsigned xy ) // RES 4, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 4) ); +} + +void opcode_xycb_a7( unsigned xy ) // LD A, RES 4, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 4); + writeByte( xy, A ); +} + +void opcode_xycb_a8( unsigned xy ) // LD B, RES 5, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, B ); +} + +void opcode_xycb_a9( unsigned xy ) // LD C, RES 5, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, C ); +} + +void opcode_xycb_aa( unsigned xy ) // LD D, RES 5, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, D ); +} + +void opcode_xycb_ab( unsigned xy ) // LD E, RES 5, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, E ); +} + +void opcode_xycb_ac( unsigned xy ) // LD H, RES 5, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, H ); +} + +void opcode_xycb_ad( unsigned xy ) // LD L, RES 5, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, L ); +} + +void opcode_xycb_ae( unsigned xy ) // RES 5, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 5) ); +} + +void opcode_xycb_af( unsigned xy ) // LD A, RES 5, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 5); + writeByte( xy, A ); +} + +void opcode_xycb_b0( unsigned xy ) // LD B, RES 6, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, B ); +} + +void opcode_xycb_b1( unsigned xy ) // LD C, RES 6, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, C ); +} + +void opcode_xycb_b2( unsigned xy ) // LD D, RES 6, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, D ); +} + +void opcode_xycb_b3( unsigned xy ) // LD E, RES 6, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, E ); +} + +void opcode_xycb_b4( unsigned xy ) // LD H, RES 6, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, H ); +} + +void opcode_xycb_b5( unsigned xy ) // LD L, RES 6, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, L ); +} + +void opcode_xycb_b6( unsigned xy ) // RES 6, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 6) ); +} + +void opcode_xycb_b7( unsigned xy ) // LD A, RES 6, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 6); + writeByte( xy, A ); +} + +void opcode_xycb_b8( unsigned xy ) // LD B, RES 7, (IX + d) +{ + B = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, B ); +} + +void opcode_xycb_b9( unsigned xy ) // LD C, RES 7, (IX + d) +{ + C = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, C ); +} + +void opcode_xycb_ba( unsigned xy ) // LD D, RES 7, (IX + d) +{ + D = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, D ); +} + +void opcode_xycb_bb( unsigned xy ) // LD E, RES 7, (IX + d) +{ + E = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, E ); +} + +void opcode_xycb_bc( unsigned xy ) // LD H, RES 7, (IX + d) +{ + H = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, H ); +} + +void opcode_xycb_bd( unsigned xy ) // LD L, RES 7, (IX + d) +{ + L = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, L ); +} + +void opcode_xycb_be( unsigned xy ) // RES 7, (IX + d) +{ + writeByte( xy, readByte(xy) & (unsigned char) ~(1 << 7) ); +} + +void opcode_xycb_bf( unsigned xy ) // LD A, RES 7, (IX + d) +{ + A = readByte(xy) & (unsigned char) ~(1 << 7); + writeByte( xy, A ); +} + +void opcode_xycb_c0( unsigned xy ) // LD B, SET 0, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, B ); +} + +void opcode_xycb_c1( unsigned xy ) // LD C, SET 0, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, C ); +} + +void opcode_xycb_c2( unsigned xy ) // LD D, SET 0, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, D ); +} + +void opcode_xycb_c3( unsigned xy ) // LD E, SET 0, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, E ); +} + +void opcode_xycb_c4( unsigned xy ) // LD H, SET 0, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, H ); +} + +void opcode_xycb_c5( unsigned xy ) // LD L, SET 0, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, L ); +} + +void opcode_xycb_c6( unsigned xy ) // SET 0, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 0) ); +} + +void opcode_xycb_c7( unsigned xy ) // LD A, SET 0, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 0); + writeByte( xy, A ); +} + +void opcode_xycb_c8( unsigned xy ) // LD B, SET 1, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, B ); +} + +void opcode_xycb_c9( unsigned xy ) // LD C, SET 1, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, C ); +} + +void opcode_xycb_ca( unsigned xy ) // LD D, SET 1, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, D ); +} + +void opcode_xycb_cb( unsigned xy ) // LD E, SET 1, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, E ); +} + +void opcode_xycb_cc( unsigned xy ) // LD H, SET 1, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, H ); +} + +void opcode_xycb_cd( unsigned xy ) // LD L, SET 1, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, L ); +} + +void opcode_xycb_ce( unsigned xy ) // SET 1, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 1) ); +} + +void opcode_xycb_cf( unsigned xy ) // LD A, SET 1, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 1); + writeByte( xy, A ); +} + +void opcode_xycb_d0( unsigned xy ) // LD B, SET 2, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, B ); +} + +void opcode_xycb_d1( unsigned xy ) // LD C, SET 2, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, C ); +} + +void opcode_xycb_d2( unsigned xy ) // LD D, SET 2, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, D ); +} + +void opcode_xycb_d3( unsigned xy ) // LD E, SET 2, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, E ); +} + +void opcode_xycb_d4( unsigned xy ) // LD H, SET 2, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, H ); +} + +void opcode_xycb_d5( unsigned xy ) // LD L, SET 2, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, L ); +} + +void opcode_xycb_d6( unsigned xy ) // SET 2, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 2) ); +} + +void opcode_xycb_d7( unsigned xy ) // LD A, SET 2, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 2); + writeByte( xy, A ); +} + +void opcode_xycb_d8( unsigned xy ) // LD B, SET 3, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, B ); +} + +void opcode_xycb_d9( unsigned xy ) // LD C, SET 3, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, C ); +} + +void opcode_xycb_da( unsigned xy ) // LD D, SET 3, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, D ); +} + +void opcode_xycb_db( unsigned xy ) // LD E, SET 3, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, E ); +} + +void opcode_xycb_dc( unsigned xy ) // LD H, SET 3, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, H ); +} + +void opcode_xycb_dd( unsigned xy ) // LD L, SET 3, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, L ); +} + +void opcode_xycb_de( unsigned xy ) // SET 3, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 3) ); +} + +void opcode_xycb_df( unsigned xy ) // LD A, SET 3, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 3); + writeByte( xy, A ); +} + +void opcode_xycb_e0( unsigned xy ) // LD B, SET 4, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, B ); +} + +void opcode_xycb_e1( unsigned xy ) // LD C, SET 4, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, C ); +} + +void opcode_xycb_e2( unsigned xy ) // LD D, SET 4, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, D ); +} + +void opcode_xycb_e3( unsigned xy ) // LD E, SET 4, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, E ); +} + +void opcode_xycb_e4( unsigned xy ) // LD H, SET 4, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, H ); +} + +void opcode_xycb_e5( unsigned xy ) // LD L, SET 4, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, L ); +} + +void opcode_xycb_e6( unsigned xy ) // SET 4, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 4) ); +} + +void opcode_xycb_e7( unsigned xy ) // LD A, SET 4, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 4); + writeByte( xy, A ); +} + +void opcode_xycb_e8( unsigned xy ) // LD B, SET 5, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, B ); +} + +void opcode_xycb_e9( unsigned xy ) // LD C, SET 5, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, C ); +} + +void opcode_xycb_ea( unsigned xy ) // LD D, SET 5, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, D ); +} + +void opcode_xycb_eb( unsigned xy ) // LD E, SET 5, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, E ); +} + +void opcode_xycb_ec( unsigned xy ) // LD H, SET 5, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, H ); +} + +void opcode_xycb_ed( unsigned xy ) // LD L, SET 5, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, L ); +} + +void opcode_xycb_ee( unsigned xy ) // SET 5, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 5) ); +} + +void opcode_xycb_ef( unsigned xy ) // LD A, SET 5, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 5); + writeByte( xy, A ); +} + +void opcode_xycb_f0( unsigned xy ) // LD B, SET 6, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, B ); +} + +void opcode_xycb_f1( unsigned xy ) // LD C, SET 6, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, C ); +} + +void opcode_xycb_f2( unsigned xy ) // LD D, SET 6, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, D ); +} + +void opcode_xycb_f3( unsigned xy ) // LD E, SET 6, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, E ); +} + +void opcode_xycb_f4( unsigned xy ) // LD H, SET 6, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, H ); +} + +void opcode_xycb_f5( unsigned xy ) // LD L, SET 6, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, L ); +} + +void opcode_xycb_f6( unsigned xy ) // SET 6, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 6) ); +} + +void opcode_xycb_f7( unsigned xy ) // LD A, SET 6, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 6); + writeByte( xy, A ); +} + +void opcode_xycb_f8( unsigned xy ) // LD B, SET 7, (IX + d) +{ + B = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, B ); +} + +void opcode_xycb_f9( unsigned xy ) // LD C, SET 7, (IX + d) +{ + C = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, C ); +} + +void opcode_xycb_fa( unsigned xy ) // LD D, SET 7, (IX + d) +{ + D = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, D ); +} + +void opcode_xycb_fb( unsigned xy ) // LD E, SET 7, (IX + d) +{ + E = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, E ); +} + +void opcode_xycb_fc( unsigned xy ) // LD H, SET 7, (IX + d) +{ + H = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, H ); +} + +void opcode_xycb_fd( unsigned xy ) // LD L, SET 7, (IX + d) +{ + L = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, L ); +} + +void opcode_xycb_fe( unsigned xy ) // SET 7, (IX + d) +{ + writeByte( xy, readByte(xy) | (unsigned char) (1 << 7) ); +} + +void opcode_xycb_ff( unsigned xy ) // LD A, SET 7, (IX + d) +{ + A = readByte(xy) | (unsigned char) (1 << 7); + writeByte( xy, A ); +} + +OpcodeInfo OpInfo_[256] = { + { &opcode_00, 4 }, // NOP + { &opcode_01, 10 }, // LD BC,nn + { &opcode_02, 7 }, // LD (BC),A + { &opcode_03, 6 }, // INC BC + { &opcode_04, 4 }, // INC B + { &opcode_05, 4 }, // DEC B + { &opcode_06, 7 }, // LD B,n + { &opcode_07, 4 }, // RLCA + { &opcode_08, 4 }, // EX AF,AF' + { &opcode_09, 11 }, // ADD HL,BC + { &opcode_0a, 7 }, // LD A,(BC) + { &opcode_0b, 6 }, // DEC BC + { &opcode_0c, 4 }, // INC C + { &opcode_0d, 4 }, // DEC C + { &opcode_0e, 7 }, // LD C,n + { &opcode_0f, 4 }, // RRCA + { &opcode_10, 8 }, // DJNZ d + { &opcode_11, 10 }, // LD DE,nn + { &opcode_12, 7 }, // LD (DE),A + { &opcode_13, 6 }, // INC DE + { &opcode_14, 4 }, // INC D + { &opcode_15, 4 }, // DEC D + { &opcode_16, 7 }, // LD D,n + { &opcode_17, 4 }, // RLA + { &opcode_18, 12 }, // JR d + { &opcode_19, 11 }, // ADD HL,DE + { &opcode_1a, 7 }, // LD A,(DE) + { &opcode_1b, 6 }, // DEC DE + { &opcode_1c, 4 }, // INC E + { &opcode_1d, 4 }, // DEC E + { &opcode_1e, 7 }, // LD E,n + { &opcode_1f, 4 }, // RRA + { &opcode_20, 7 }, // JR NZ,d + { &opcode_21, 10 }, // LD HL,nn + { &opcode_22, 16 }, // LD (nn),HL + { &opcode_23, 6 }, // INC HL + { &opcode_24, 4 }, // INC H + { &opcode_25, 4 }, // DEC H + { &opcode_26, 7 }, // LD H,n + { &opcode_27, 4 }, // DAA + { &opcode_28, 7 }, // JR Z,d + { &opcode_29, 11 }, // ADD HL,HL + { &opcode_2a, 16 }, // LD HL,(nn) + { &opcode_2b, 6 }, // DEC HL + { &opcode_2c, 4 }, // INC L + { &opcode_2d, 4 }, // DEC L + { &opcode_2e, 7 }, // LD L,n + { &opcode_2f, 4 }, // CPL + { &opcode_30, 7 }, // JR NC,d + { &opcode_31, 10 }, // LD SP,nn + { &opcode_32, 13 }, // LD (nn),A + { &opcode_33, 6 }, // INC SP + { &opcode_34, 11 }, // INC (HL) + { &opcode_35, 11 }, // DEC (HL) + { &opcode_36, 10 }, // LD (HL),n + { &opcode_37, 4 }, // SCF + { &opcode_38, 7 }, // JR C,d + { &opcode_39, 11 }, // ADD HL,SP + { &opcode_3a, 13 }, // LD A,(nn) + { &opcode_3b, 6 }, // DEC SP + { &opcode_3c, 4 }, // INC A + { &opcode_3d, 4 }, // DEC A + { &opcode_3e, 7 }, // LD A,n + { &opcode_3f, 4 }, // CCF + { &opcode_40, 4 }, // LD B,B + { &opcode_41, 4 }, // LD B,C + { &opcode_42, 4 }, // LD B,D + { &opcode_43, 4 }, // LD B,E + { &opcode_44, 4 }, // LD B,H + { &opcode_45, 4 }, // LD B,L + { &opcode_46, 7 }, // LD B,(HL) + { &opcode_47, 4 }, // LD B,A + { &opcode_48, 4 }, // LD C,B + { &opcode_49, 4 }, // LD C,C + { &opcode_4a, 4 }, // LD C,D + { &opcode_4b, 4 }, // LD C,E + { &opcode_4c, 4 }, // LD C,H + { &opcode_4d, 4 }, // LD C,L + { &opcode_4e, 7 }, // LD C,(HL) + { &opcode_4f, 4 }, // LD C,A + { &opcode_50, 4 }, // LD D,B + { &opcode_51, 4 }, // LD D,C + { &opcode_52, 4 }, // LD D,D + { &opcode_53, 4 }, // LD D,E + { &opcode_54, 4 }, // LD D,H + { &opcode_55, 4 }, // LD D,L + { &opcode_56, 7 }, // LD D,(HL) + { &opcode_57, 4 }, // LD D,A + { &opcode_58, 4 }, // LD E,B + { &opcode_59, 4 }, // LD E,C + { &opcode_5a, 4 }, // LD E,D + { &opcode_5b, 4 }, // LD E,E + { &opcode_5c, 4 }, // LD E,H + { &opcode_5d, 4 }, // LD E,L + { &opcode_5e, 7 }, // LD E,(HL) + { &opcode_5f, 4 }, // LD E,A + { &opcode_60, 4 }, // LD H,B + { &opcode_61, 4 }, // LD H,C + { &opcode_62, 4 }, // LD H,D + { &opcode_63, 4 }, // LD H,E + { &opcode_64, 4 }, // LD H,H + { &opcode_65, 4 }, // LD H,L + { &opcode_66, 7 }, // LD H,(HL) + { &opcode_67, 4 }, // LD H,A + { &opcode_68, 4 }, // LD L,B + { &opcode_69, 4 }, // LD L,C + { &opcode_6a, 4 }, // LD L,D + { &opcode_6b, 4 }, // LD L,E + { &opcode_6c, 4 }, // LD L,H + { &opcode_6d, 4 }, // LD L,L + { &opcode_6e, 7 }, // LD L,(HL) + { &opcode_6f, 4 }, // LD L,A + { &opcode_70, 7 }, // LD (HL),B + { &opcode_71, 7 }, // LD (HL),C + { &opcode_72, 7 }, // LD (HL),D + { &opcode_73, 7 }, // LD (HL),E + { &opcode_74, 7 }, // LD (HL),H + { &opcode_75, 7 }, // LD (HL),L + { &opcode_76, 4 }, // HALT + { &opcode_77, 7 }, // LD (HL),A + { &opcode_78, 4 }, // LD A,B + { &opcode_79, 4 }, // LD A,C + { &opcode_7a, 4 }, // LD A,D + { &opcode_7b, 4 }, // LD A,E + { &opcode_7c, 4 }, // LD A,H + { &opcode_7d, 4 }, // LD A,L + { &opcode_7e, 7 }, // LD A,(HL) + { &opcode_7f, 4 }, // LD A,A + { &opcode_80, 4 }, // ADD A,B + { &opcode_81, 4 }, // ADD A,C + { &opcode_82, 4 }, // ADD A,D + { &opcode_83, 4 }, // ADD A,E + { &opcode_84, 4 }, // ADD A,H + { &opcode_85, 4 }, // ADD A,L + { &opcode_86, 7 }, // ADD A,(HL) + { &opcode_87, 4 }, // ADD A,A + { &opcode_88, 4 }, // ADC A,B + { &opcode_89, 4 }, // ADC A,C + { &opcode_8a, 4 }, // ADC A,D + { &opcode_8b, 4 }, // ADC A,E + { &opcode_8c, 4 }, // ADC A,H + { &opcode_8d, 4 }, // ADC A,L + { &opcode_8e, 7 }, // ADC A,(HL) + { &opcode_8f, 4 }, // ADC A,A + { &opcode_90, 4 }, // SUB B + { &opcode_91, 4 }, // SUB C + { &opcode_92, 4 }, // SUB D + { &opcode_93, 4 }, // SUB E + { &opcode_94, 4 }, // SUB H + { &opcode_95, 4 }, // SUB L + { &opcode_96, 7 }, // SUB (HL) + { &opcode_97, 4 }, // SUB A + { &opcode_98, 4 }, // SBC A,B + { &opcode_99, 4 }, // SBC A,C + { &opcode_9a, 4 }, // SBC A,D + { &opcode_9b, 4 }, // SBC A,E + { &opcode_9c, 4 }, // SBC A,H + { &opcode_9d, 4 }, // SBC A,L + { &opcode_9e, 7 }, // SBC A,(HL) + { &opcode_9f, 4 }, // SBC A,A + { &opcode_a0, 4 }, // AND B + { &opcode_a1, 4 }, // AND C + { &opcode_a2, 4 }, // AND D + { &opcode_a3, 4 }, // AND E + { &opcode_a4, 4 }, // AND H + { &opcode_a5, 4 }, // AND L + { &opcode_a6, 7 }, // AND (HL) + { &opcode_a7, 4 }, // AND A + { &opcode_a8, 4 }, // XOR B + { &opcode_a9, 4 }, // XOR C + { &opcode_aa, 4 }, // XOR D + { &opcode_ab, 4 }, // XOR E + { &opcode_ac, 4 }, // XOR H + { &opcode_ad, 4 }, // XOR L + { &opcode_ae, 7 }, // XOR (HL) + { &opcode_af, 4 }, // XOR A + { &opcode_b0, 4 }, // OR B + { &opcode_b1, 4 }, // OR C + { &opcode_b2, 4 }, // OR D + { &opcode_b3, 4 }, // OR E + { &opcode_b4, 4 }, // OR H + { &opcode_b5, 4 }, // OR L + { &opcode_b6, 7 }, // OR (HL) + { &opcode_b7, 4 }, // OR A + { &opcode_b8, 4 }, // CP B + { &opcode_b9, 4 }, // CP C + { &opcode_ba, 4 }, // CP D + { &opcode_bb, 4 }, // CP E + { &opcode_bc, 4 }, // CP H + { &opcode_bd, 4 }, // CP L + { &opcode_be, 7 }, // CP (HL) + { &opcode_bf, 4 }, // CP A + { &opcode_c0, 5 }, // RET NZ + { &opcode_c1, 10 }, // POP BC + { &opcode_c2, 10 }, // JP NZ,nn + { &opcode_c3, 10 }, // JP nn + { &opcode_c4, 10 }, // CALL NZ,nn + { &opcode_c5, 11 }, // PUSH BC + { &opcode_c6, 7 }, // ADD A,n + { &opcode_c7, 11 }, // RST 0 + { &opcode_c8, 5 }, // RET Z + { &opcode_c9, 10 }, // RET + { &opcode_ca, 10 }, // JP Z,nn + { &opcode_cb, 0 }, // [Prefix] + { &opcode_cc, 10 }, // CALL Z,nn + { &opcode_cd, 17 }, // CALL nn + { &opcode_ce, 7 }, // ADC A,n + { &opcode_cf, 11 }, // RST 8 + { &opcode_d0, 5 }, // RET NC + { &opcode_d1, 10 }, // POP DE + { &opcode_d2, 10 }, // JP NC,nn + { &opcode_d3, 11 }, // OUT (n),A + { &opcode_d4, 10 }, // CALL NC,nn + { &opcode_d5, 11 }, // PUSH DE + { &opcode_d6, 7 }, // SUB n + { &opcode_d7, 11 }, // RST 10H + { &opcode_d8, 5 }, // RET C + { &opcode_d9, 4 }, // EXX + { &opcode_da, 10 }, // JP C,nn + { &opcode_db, 11 }, // IN A,(n) + { &opcode_dc, 10 }, // CALL C,nn + { &opcode_dd, 0 }, // [IX Prefix] + { &opcode_de, 7 }, // SBC A,n + { &opcode_df, 11 }, // RST 18H + { &opcode_e0, 5 }, // RET PO + { &opcode_e1, 10 }, // POP HL + { &opcode_e2, 10 }, // JP PO,nn + { &opcode_e3, 19 }, // EX (SP),HL + { &opcode_e4, 10 }, // CALL PO,nn + { &opcode_e5, 11 }, // PUSH HL + { &opcode_e6, 7 }, // AND n + { &opcode_e7, 11 }, // RST 20H + { &opcode_e8, 5 }, // RET PE + { &opcode_e9, 4 }, // JP (HL) + { &opcode_ea, 10 }, // JP PE,nn + { &opcode_eb, 4 }, // EX DE,HL + { &opcode_ec, 10 }, // CALL PE,nn + { &opcode_ed, 0 }, // [Prefix] + { &opcode_ee, 7 }, // XOR n + { &opcode_ef, 11 }, // RST 28H + { &opcode_f0, 5 }, // RET P + { &opcode_f1, 10 }, // POP AF + { &opcode_f2, 10 }, // JP P,nn + { &opcode_f3, 4 }, // DI + { &opcode_f4, 10 }, // CALL P,nn + { &opcode_f5, 11 }, // PUSH AF + { &opcode_f6, 7 }, // OR n + { &opcode_f7, 11 }, // RST 30H + { &opcode_f8, 5 }, // RET M + { &opcode_f9, 6 }, // LD SP,HL + { &opcode_fa, 10 }, // JP M,nn + { &opcode_fb, 4 }, // EI + { &opcode_fc, 10 }, // CALL M,nn + { &opcode_fd, 0 }, // [IY Prefix] + { &opcode_fe, 7 }, // CP n + { &opcode_ff, 11 } // RST 38H +}; + +void opcode_00() // NOP +{ +} + +void opcode_01() // LD BC,nn +{ + C = fetchByte(); + B = fetchByte(); +} + +void opcode_02() // LD (BC),A +{ + writeByte( BC(), A ); +} + +void opcode_03() // INC BC +{ + if( ++C == 0 ) ++B; +} + +void opcode_04() // INC B +{ + B = incByte( B ); +} + +void opcode_05() // DEC B +{ + B = decByte( B ); +} + +void opcode_06() // LD B,n +{ + B = fetchByte(); +} + +void opcode_07() // RLCA +{ + A = (A << 1) | (A >> 7); + F = F & ~(AddSub | Halfcarry | Carry); + if( A & 0x01 ) F |= Carry; +} + +void opcode_08() // EX AF,AF' +{ + unsigned char x; + + x = A; A = A1; A1 = x; + x = F; F = F1; F1 = x; +} + +void opcode_09() // ADD HL,BC +{ + unsigned hl = HL(); + unsigned rp = BC(); + unsigned x = hl + rp; + + F &= Sign | Zero | Parity; + if( x > 0xFFFF ) F |= Carry; + if( ((hl & 0xFFF) + (rp & 0xFFF)) > 0xFFF ) F |= Halfcarry; + + L = x & 0xFF; + H = (x >> 8) & 0xFF; +} + +void opcode_0a() // LD A,(BC) +{ + A = readByte( BC() ); +} + +void opcode_0b() // DEC BC +{ + if( C-- == 0 ) --B; +} + +void opcode_0c() // INC C +{ + C = incByte( C ); +} + +void opcode_0d() // DEC C +{ + C = decByte( C ); +} + +void opcode_0e() // LD C,n +{ + C = fetchByte(); +} + +void opcode_0f() // RRCA +{ + A = (A >> 1) | (A << 7); + F = F & ~(AddSub | Halfcarry | Carry); + if( A & 0x80 ) F |= Carry; +} + +void opcode_10() // DJNZ d +{ + unsigned char o = fetchByte(); + + if( --B != 0 ) relJump( o ); +} + +void opcode_11() // LD DE,nn +{ + E = fetchByte(); + D = fetchByte(); +} + +void opcode_12() // LD (DE),A +{ + writeByte( DE(), A ); +} + +void opcode_13() // INC DE +{ + if( ++E == 0 ) ++D; +} + +void opcode_14() // INC D +{ + D = incByte( D ); +} + +void opcode_15() // DEC D +{ + D = decByte( D ); +} + +void opcode_16() // LD D,n +{ + D = fetchByte(); +} + +void opcode_17() // RLA +{ + unsigned char a = A; + + A <<= 1; + if( F & Carry ) A |= 0x01; + F = F & ~(AddSub | Halfcarry | Carry); + if( a & 0x80 ) F |= Carry; +} + +void opcode_18() // JR d +{ + relJump( fetchByte() ); +} + +void opcode_19() // ADD HL,DE +{ + unsigned hl = HL(); + unsigned rp = DE(); + unsigned x = hl + rp; + + F &= Sign | Zero | Parity; + if( x > 0xFFFF ) F |= Carry; + if( ((hl & 0xFFF) + (rp & 0xFFF)) > 0xFFF ) F |= Halfcarry; + + L = x & 0xFF; + H = (x >> 8) & 0xFF; +} + +void opcode_1a() // LD A,(DE) +{ + A = readByte( DE() ); +} + +void opcode_1b() // DEC DE +{ + if( E-- == 0 ) --D; +} + +void opcode_1c() // INC E +{ + E = incByte( E ); +} + +void opcode_1d() // DEC E +{ + E = decByte( E ); +} + +void opcode_1e() // LD E,n +{ + E = fetchByte(); +} + +void opcode_1f() // RRA +{ + unsigned char a = A; + + A >>= 1; + if( F & Carry ) A |= 0x80; + F = F & ~(AddSub | Halfcarry | Carry); + if( a & 0x01 ) F |= Carry; +} + +void opcode_20() // JR NZ,d +{ + unsigned char o = fetchByte(); + + if( ! (F & Zero) ) relJump( o ); +} + +void opcode_21() // LD HL,nn +{ + L = fetchByte(); + H = fetchByte(); +} + +void opcode_22() // LD (nn),HL +{ + unsigned x = fetchWord(); + + writeByte( x , L ); + writeByte( x+1, H ); +} + +void opcode_23() // INC HL +{ + if( ++L == 0 ) ++H; +} + +void opcode_24() // INC H +{ + H = incByte( H ); +} + +void opcode_25() // DEC H +{ + H = decByte( H ); +} + +void opcode_26() // LD H,n +{ + H = fetchByte(); +} + +/* + DAA is computed using the following table to get a diff value + that is added to or subtracted (according to the N flag) from A: + + C Upper H Lower Diff + -+-----+-+-----+---- + 1 * 0 0-9 60 + 1 * 1 0-9 66 + 1 * * A-F 66 + 0 0-9 0 0-9 00 + 0 0-9 1 0-9 06 + 0 0-8 * A-F 06 + 0 A-F 0 0-9 60 + 0 9-F * A-F 66 + 0 A-F 1 0-9 66 + + The carry and halfcarry flags are then updated using similar tables. + + These tables were found by Stefano Donati of Ramsoft and are + published in the "Undocumented Z80 Documented" paper by Sean Young, + the following is an algorithmical implementation with no lookups. +*/ +void opcode_27() // DAA +{ + unsigned char diff; + unsigned char hf = F & Halfcarry; + unsigned char cf = F & Carry; + unsigned char lower = A & 0x0F; + + if( cf ) { + diff = (lower >= 0x0A) || hf ? 0x66 : 0x60; + } + else { + diff = (A >= 0x9A) ? 0x60 : 0x00; + + if( hf || (lower >= 0x0A) ) diff += 0x06; + } + + if( A >= 0x9A ) cf = Carry; + + if( F & Subtraction ) { + A -= diff; + F = PSZ_[A] | Subtraction | cf; + if( hf && (lower <= 0x05) ) F |= Halfcarry; + } + else { + A += diff; + F = PSZ_[A] | cf; + if( lower >= 0x0A ) F |= Halfcarry; + } +} + +void opcode_28() // JR Z,d +{ + unsigned char o = fetchByte(); + + if( F & Zero ) relJump( o ); +} + +void opcode_29() // ADD HL,HL +{ + unsigned hl = HL(); + unsigned rp = hl; + unsigned x = hl + rp; + + F &= Sign | Zero | Parity; + if( x > 0xFFFF ) F |= Carry; + if( ((hl & 0xFFF) + (rp & 0xFFF)) > 0xFFF ) F |= Halfcarry; + + L = x & 0xFF; + H = (x >> 8) & 0xFF; +} + +void opcode_2a() // LD HL,(nn) +{ + unsigned x = fetchWord(); + + L = readByte( x ); + H = readByte( x+1 ); +} + +void opcode_2b() // DEC HL +{ + if( L-- == 0 ) --H; +} + +void opcode_2c() // INC L +{ + L = incByte( L ); +} + +void opcode_2d() // DEC L +{ + L = decByte( L ); +} + +void opcode_2e() // LD L,n +{ + L = fetchByte(); +} + +void opcode_2f() // CPL +{ + A ^= 0xFF; + F |= AddSub | Halfcarry; +} + +void opcode_30() // JR NC,d +{ + unsigned char o = fetchByte(); + + if( ! (F & Carry) ) relJump( o ); +} + +void opcode_31() // LD SP,nn +{ + SP = fetchWord(); +} + +void opcode_32() // LD (nn),A +{ + writeByte( fetchWord(), A ); +} + +void opcode_33() // INC SP +{ + SP = (SP + 1) & 0xFFFF; +} + +void opcode_34() // INC (HL) +{ + writeByte( HL(), incByte( readByte( HL() ) ) ); +} + +void opcode_35() // DEC (HL) +{ + writeByte( HL(), decByte( readByte( HL() ) ) ); +} + +void opcode_36() // LD (HL),n +{ + writeByte( HL(), fetchByte() ); +} + +void opcode_37() // SCF +{ + F = (F & (Parity | Sign | Zero)) | Carry; +} + +void opcode_38() // JR C,d +{ + unsigned char o = fetchByte(); + + if( F & Carry ) relJump( o ); +} + +void opcode_39() // ADD HL,SP +{ + unsigned hl = HL(); + unsigned rp = SP; + unsigned x = hl + rp; + + F &= Sign | Zero | Parity; + if( x > 0xFFFF ) F |= Carry; + if( ((hl & 0xFFF) + (rp & 0xFFF)) > 0xFFF ) F |= Halfcarry; + + L = x & 0xFF; + H = (x >> 8) & 0xFF; +} + +void opcode_3a() // LD A,(nn) +{ + A = readByte( fetchWord() ); +} + +void opcode_3b() // DEC SP +{ + SP = (SP - 1) & 0xFFFF; +} + +void opcode_3c() // INC A +{ + A = incByte( A ); +} + +void opcode_3d() // DEC A +{ + A = decByte( A ); +} + +void opcode_3e() // LD A,n +{ + A = fetchByte(); +} + +void opcode_3f() // CCF +{ + if( F & Carry ) { + F = (F & (Parity | Sign | Zero)) | Halfcarry; // Halfcarry holds previous carry + } + else { + F = (F & (Parity | Sign | Zero)) | Carry; + } +} + +void opcode_40() // LD B,B +{ +} + +void opcode_41() // LD B,C +{ + B = C; +} + +void opcode_42() // LD B,D +{ + B = D; +} + +void opcode_43() // LD B,E +{ + B = E; +} + +void opcode_44() // LD B,H +{ + B = H; +} + +void opcode_45() // LD B,L +{ + B = L; +} + +void opcode_46() // LD B,(HL) +{ + B = readByte( HL() ); +} + +void opcode_47() // LD B,A +{ + B = A; +} + +void opcode_48() // LD C,B +{ + C = B; +} + +void opcode_49() // LD C,C +{ +} + +void opcode_4a() // LD C,D +{ + C = D; +} + +void opcode_4b() // LD C,E +{ + C = E; +} + +void opcode_4c() // LD C,H +{ + C = H; +} + +void opcode_4d() // LD C,L +{ + C = L; +} + +void opcode_4e() // LD C,(HL) +{ + C = readByte( HL() ); +} + +void opcode_4f() // LD C,A +{ + C = A; +} + +void opcode_50() // LD D,B +{ + D = B; +} + +void opcode_51() // LD D,C +{ + D = C; +} + +void opcode_52() // LD D,D +{ +} + +void opcode_53() // LD D,E +{ + D = E; +} + +void opcode_54() // LD D,H +{ + D = H; +} + +void opcode_55() // LD D,L +{ + D = L; +} + +void opcode_56() // LD D,(HL) +{ + D = readByte( HL() ); +} + +void opcode_57() // LD D,A +{ + D = A; +} + +void opcode_58() // LD E,B +{ + E = B; +} + +void opcode_59() // LD E,C +{ + E = C; +} + +void opcode_5a() // LD E,D +{ + E = D; +} + +void opcode_5b() // LD E,E +{ +} + +void opcode_5c() // LD E,H +{ + E = H; +} + +void opcode_5d() // LD E,L +{ + E = L; +} + +void opcode_5e() // LD E,(HL) +{ + E = readByte( HL() ); +} + +void opcode_5f() // LD E,A +{ + E = A; +} + +void opcode_60() // LD H,B +{ + H = B; +} + +void opcode_61() // LD H,C +{ + H = C; +} + +void opcode_62() // LD H,D +{ + H = D; +} + +void opcode_63() // LD H,E +{ + H = E; +} + +void opcode_64() // LD H,H +{ +} + +void opcode_65() // LD H,L +{ + H = L; +} + +void opcode_66() // LD H,(HL) +{ + H = readByte( HL() ); +} + +void opcode_67() // LD H,A +{ + H = A; +} + +void opcode_68() // LD L,B +{ + L = B; +} + +void opcode_69() // LD L,C +{ + L = C; +} + +void opcode_6a() // LD L,D +{ + L = D; +} + +void opcode_6b() // LD L,E +{ + L = E; +} + +void opcode_6c() // LD L,H +{ + L = H; +} + +void opcode_6d() // LD L,L +{ +} + +void opcode_6e() // LD L,(HL) +{ + L = readByte( HL() ); +} + +void opcode_6f() // LD L,A +{ + L = A; +} + +void opcode_70() // LD (HL),B +{ + writeByte( HL(), B ); +} + +void opcode_71() // LD (HL),C +{ + writeByte( HL(), C ); +} + +void opcode_72() // LD (HL),D +{ + writeByte( HL(), D ); +} + +void opcode_73() // LD (HL),E +{ + writeByte( HL(), E ); +} + +void opcode_74() // LD (HL),H +{ + writeByte( HL(), H ); +} + +void opcode_75() // LD (HL),L +{ + writeByte( HL(), L ); +} + +void opcode_76() // HALT +{ + iflags_ |= Halted; +} + +void opcode_77() // LD (HL),A +{ + writeByte( HL(), A ); +} + +void opcode_78() // LD A,B +{ + A = B; +} + +void opcode_79() // LD A,C +{ + A = C; +} + +void opcode_7a() // LD A,D +{ + A = D; +} + +void opcode_7b() // LD A,E +{ + A = E; +} + +void opcode_7c() // LD A,H +{ + A = H; +} + +void opcode_7d() // LD A,L +{ + A = L; +} + +void opcode_7e() // LD A,(HL) +{ + A = readByte( HL() ); +} + +void opcode_7f() // LD A,A +{ +} + +void opcode_80() // ADD A,B +{ + addByte( B, 0 ); +} + +void opcode_81() // ADD A,C +{ + addByte( C, 0 ); +} + +void opcode_82() // ADD A,D +{ + addByte( D, 0 ); +} + +void opcode_83() // ADD A,E +{ + addByte( E, 0 ); +} + +void opcode_84() // ADD A,H +{ + addByte( H, 0 ); +} + +void opcode_85() // ADD A,L +{ + addByte( L, 0 ); +} + +void opcode_86() // ADD A,(HL) +{ + addByte( readByte( HL() ), 0 ); +} + +void opcode_87() // ADD A,A +{ + addByte( A, 0 ); +} + +void opcode_88() // ADC A,B +{ + addByte( B, F & Carry ); +} + +void opcode_89() // ADC A,C +{ + addByte( C, F & Carry ); +} + +void opcode_8a() // ADC A,D +{ + addByte( D, F & Carry ); +} + +void opcode_8b() // ADC A,E +{ + addByte( E, F & Carry ); +} + +void opcode_8c() // ADC A,H +{ + addByte( H, F & Carry ); +} + +void opcode_8d() // ADC A,L +{ + addByte( L, F & Carry ); +} + +void opcode_8e() // ADC A,(HL) +{ + addByte( readByte( HL() ), F & Carry ); +} + +void opcode_8f() // ADC A,A +{ + addByte( A, F & Carry ); +} + +void opcode_90() // SUB B +{ + A = subByte( B, 0 ); +} + +void opcode_91() // SUB C +{ + A = subByte( C, 0 ); +} + +void opcode_92() // SUB D +{ + A = subByte( D, 0 ); +} + +void opcode_93() // SUB E +{ + A = subByte( E, 0 ); +} + +void opcode_94() // SUB H +{ + A = subByte( H, 0 ); +} + +void opcode_95() // SUB L +{ + A = subByte( L, 0 ); +} + +void opcode_96() // SUB (HL) +{ + A = subByte( readByte( HL() ), 0 ); +} + +void opcode_97() // SUB A +{ + A = subByte( A, 0 ); +} + +void opcode_98() // SBC A,B +{ + A = subByte( B, F & Carry ); +} + +void opcode_99() // SBC A,C +{ + A = subByte( C, F & Carry ); +} + +void opcode_9a() // SBC A,D +{ + A = subByte( D, F & Carry ); +} + +void opcode_9b() // SBC A,E +{ + A = subByte( E, F & Carry ); +} + +void opcode_9c() // SBC A,H +{ + A = subByte( H, F & Carry ); +} + +void opcode_9d() // SBC A,L +{ + A = subByte( L, F & Carry ); +} + +void opcode_9e() // SBC A,(HL) +{ + A = subByte( readByte( HL() ), F & Carry ); +} + +void opcode_9f() // SBC A,A +{ + A = subByte( A, F & Carry ); +} + +void opcode_a0() // AND B +{ + A &= B; + setFlagsPSZ(); +} + +void opcode_a1() // AND C +{ + A &= C; + setFlagsPSZ(); +} + +void opcode_a2() // AND D +{ + A &= D; + setFlagsPSZ(); +} + +void opcode_a3() // AND E +{ + A &= E; + setFlagsPSZ(); +} + +void opcode_a4() // AND H +{ + A &= H; + setFlagsPSZ(); +} + +void opcode_a5() // AND L +{ + A &= L; + setFlagsPSZ(); +} + +void opcode_a6() // AND (HL) +{ + A &= readByte( HL() ); + setFlagsPSZ(); +} + +void opcode_a7() // AND A +{ + setFlagsPSZ(); +} + +void opcode_a8() // XOR B +{ + A ^= B; + setFlags35PSZ000(); +} + +void opcode_a9() // XOR C +{ + A ^= C; + setFlags35PSZ000(); +} + +void opcode_aa() // XOR D +{ + A ^= D; + setFlags35PSZ000(); +} + +void opcode_ab() // XOR E +{ + A ^= E; + setFlags35PSZ000(); +} + +void opcode_ac() // XOR H +{ + A ^= H; + setFlags35PSZ000(); +} + +void opcode_ad() // XOR L +{ + A ^= L; + setFlags35PSZ000(); +} + +void opcode_ae() // XOR (HL) +{ + A ^= readByte( HL() ); + setFlags35PSZ000(); +} + +void opcode_af() // XOR A +{ + A = 0; + setFlags35PSZ000(); +} + +void opcode_b0() // OR B +{ + A |= B; + setFlags35PSZ000(); +} + +void opcode_b1() // OR C +{ + A |= C; + setFlags35PSZ000(); +} + +void opcode_b2() // OR D +{ + A |= D; + setFlags35PSZ000(); +} + +void opcode_b3() // OR E +{ + A |= E; + setFlags35PSZ000(); +} + +void opcode_b4() // OR H +{ + A |= H; + setFlags35PSZ000(); +} + +void opcode_b5() // OR L +{ + A |= L; + setFlags35PSZ000(); +} + +void opcode_b6() // OR (HL) +{ + A |= readByte( HL() ); + setFlags35PSZ000(); +} + +void opcode_b7() // OR A +{ + setFlags35PSZ000(); +} + +void opcode_b8() // CP B +{ + cmpByte( B ); +} + +void opcode_b9() // CP C +{ + cmpByte( C ); +} + +void opcode_ba() // CP D +{ + cmpByte( D ); +} + +void opcode_bb() // CP E +{ + cmpByte( E ); +} + +void opcode_bc() // CP H +{ + cmpByte( H ); +} + +void opcode_bd() // CP L +{ + cmpByte( L ); +} + +void opcode_be() // CP (HL) +{ + cmpByte( readByte( HL() ) ); +} + +void opcode_bf() // CP A +{ + cmpByte( A ); +} + +void opcode_c0() // RET NZ +{ + if( ! (F & Zero) ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_c1() // POP BC +{ + C = readByte( SP++ ); + B = readByte( SP++ ); +} + +void opcode_c2() // JP NZ,nn +{ + if( ! (F & Zero) ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_c3() // JP nn +{ + PC = readWord( PC ); +} + +void opcode_c4() // CALL NZ,nn +{ + if( ! (F & Zero) ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_c5() // PUSH BC +{ + writeByte( --SP, B ); + writeByte( --SP, C ); +} + +void opcode_c6() // ADD A,n +{ + addByte( fetchByte(), 0 ); +} + +void opcode_c7() // RST 0 +{ + callSub( 0x00 ); +} + +void opcode_c8() // RET Z +{ + if( F & Zero ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_c9() // RET +{ + retFromSub(); +} + +void opcode_ca() // JP Z,nn +{ + if( F & Zero ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_cb() // [Prefix] +{ + unsigned op = fetchByte(); + + cycles_ += OpInfoCB_[ op ].cycles; + OpInfoCB_[ op ].handler(); +} + +void opcode_cc() // CALL Z,nn +{ + if( F & Zero ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_cd() // CALL nn +{ + callSub( fetchWord() ); +} + +void opcode_ce() // ADC A,n +{ + addByte( fetchByte(), F & Carry ); +} + +void opcode_cf() // RST 8 +{ + callSub( 0x08 ); +} + +void opcode_d0() // RET NC +{ + if( ! (F & Carry) ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_d1() // POP DE +{ + E = readByte( SP++ ); + D = readByte( SP++ ); +} + +void opcode_d2() // JP NC,nn +{ + if( ! (F & Carry) ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_d3() // OUT (n),A +{ + writePort( fetchByte(), A ); +} + +void opcode_d4() // CALL NC,nn +{ + if( ! (F & Carry) ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_d5() // PUSH DE +{ + writeByte( --SP, D ); + writeByte( --SP, E ); +} + +void opcode_d6() // SUB n +{ + A = subByte( fetchByte(), 0 ); +} + +void opcode_d7() // RST 10H +{ + callSub( 0x10 ); +} + +void opcode_d8() // RET C +{ + if( F & Carry ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_d9() // EXX +{ + unsigned char x; + + x = B; B = B1; B1 = x; + x = C; C = C1; C1 = x; + x = D; D = D1; D1 = x; + x = E; E = E1; E1 = x; + x = H; H = H1; H1 = x; + x = L; L = L1; L1 = x; +} + +void opcode_da() // JP C,nn +{ + if( F & Carry ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_db() // IN A,(n) +{ + A = readPort( fetchByte() ); +} + +void opcode_dc() // CALL C,nn +{ + if( F & Carry ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_dd() // [IX Prefix] +{ + do_opcode_xy( OpInfoDD_ ); + IX &= 0xFFFF; +} + +void opcode_de() // SBC A,n +{ + A = subByte( fetchByte(), F & Carry ); +} + +void opcode_df() // RST 18H +{ + callSub( 0x18 ); +} + +void opcode_e0() // RET PO +{ + if( ! (F & Parity) ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_e1() // POP HL +{ + L = readByte( SP++ ); + H = readByte( SP++ ); +} + +void opcode_e2() // JP PO,nn +{ + if( ! (F & Parity) ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_e3() // EX (SP),HL +{ + unsigned char x; + + x = readByte( SP ); writeByte( SP, L ); L = x; + x = readByte( SP+1 ); writeByte( SP+1, H ); H = x; +} + +void opcode_e4() // CALL PO,nn +{ + if( ! (F & Parity) ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_e5() // PUSH HL +{ + writeByte( --SP, H ); + writeByte( --SP, L ); +} + +void opcode_e6() // AND n +{ + A &= fetchByte(); + setFlagsPSZ(); +} + +void opcode_e7() // RST 20H +{ + callSub( 0x20 ); +} + +void opcode_e8() // RET PE +{ + if( F & Parity ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_e9() // JP (HL) +{ + PC = HL(); +} + +void opcode_ea() // JP PE,nn +{ + if( F & Parity ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_eb() // EX DE,HL +{ + unsigned char x; + + x = D; D = H; H = x; + x = E; E = L; L = x; +} + +void opcode_ec() // CALL PE,nn +{ + if( F & Parity ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_ed() // [Prefix] +{ + unsigned op = fetchByte(); + + if( OpInfoED_[ op ].handler ) { + OpInfoED_[ op ].handler(); + cycles_ += OpInfoED_[ op ].cycles; + } + else { + cycles_ += OpInfo_[ 0 ].cycles; // NOP + } +} + +void opcode_ee() // XOR n +{ + A ^= fetchByte(); + setFlags35PSZ000(); +} + +void opcode_ef() // RST 28H +{ + callSub( 0x28 ); +} + +void opcode_f0() // RET P +{ + if( ! (F & Sign) ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_f1() // POP AF +{ + F = readByte( SP++ ); + A = readByte( SP++ ); +} + +void opcode_f2() // JP P,nn +{ + if( ! (F & Sign) ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_f3() // DI +{ + iflags_ &= ~(IFF1 | IFF2); +} + +void opcode_f4() // CALL P,nn +{ + if( ! (F & Sign) ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_f5() // PUSH AF +{ + writeByte( --SP, A ); + writeByte( --SP, F ); +} + +void opcode_f6() // OR n +{ + A |= fetchByte(); + setFlags35PSZ000(); +} + +void opcode_f7() // RST 30H +{ + callSub( 0x30 ); +} + +void opcode_f8() // RET M +{ + if( F & Sign ) { + retFromSub(); + cycles_ += 2; + } +} + +void opcode_f9() // LD SP,HL +{ + SP = HL(); +} + +void opcode_fa() // JP M,nn +{ + if( F & Sign ) + PC = fetchWord(); + else + PC += 2; +} + +void opcode_fb() // EI +{ + iflags_ |= IFF1 | IFF2; +} + +void opcode_fc() // CALL M,nn +{ + if( F & Sign ) { + callSub( fetchWord() ); + cycles_ += 2; + } + else { + PC += 2; + } +} + +void opcode_fd() // [IY Prefix] +{ + do_opcode_xy( OpInfoFD_ ); + IY &= 0xFFFF; +} + + +void opcode_fe() // CP n +{ + subByte( fetchByte(), 0 ); +} + +void opcode_ff() // RST 38H +{ + callSub( 0x38 ); +} + + +/* Executes one instruction */ +void step(void) +{ + // Update memory refresh register (not strictly needed but...) + R = (R+1) & 0x7F; + + if( iflags_ & Halted ) { + // CPU is halted, do a NOP instruction + cycles_ += OpInfo_[0].cycles; // NOP + } + else { + // Get the opcode to execute + unsigned op = fetchByte(); + + // Update the cycles counter with the number of cycles for this opcode + cycles_ += OpInfo_[ op ].cycles; + + // Execute the opcode handler + OpInfo_[ op ].handler(); + + // Update registers + PC &= 0xFFFF; // Clip program counter + SP &= 0xFFFF; // Clip stack pointer + } +} + +/* + Runs the CPU for the specified number of cycles. + + Note: the memory refresh register is not updated! +*/ +unsigned z80_run( unsigned runCycles ) +{ + unsigned target_cycles = cycles_ + runCycles; + + // Execute instructions until the specified number of + // cycles has elapsed + while( cycles_ < target_cycles ) { + if( iflags_ & Halted ) { + // CPU is halted, do NOPs for the rest of cycles + // (this may be off by a few cycles) + cycles_ = target_cycles; + } + else { + // Get the opcode to execute + unsigned op = fetchByte(); + + // Update the cycles counter with the number of cycles for this opcode + cycles_ += OpInfo_[ op ].cycles; + + // Execute the opcode handler + OpInfo_[ op ].handler(); + } + } + + // Update registers + PC &= 0xFFFF; // Clip program counter + SP &= 0xFFFF; // Clip stack pointer + + // Return the number of extra cycles executed + return cycles_ - target_cycles; +} + +/* Interrupt */ +void z80_interrupt( unsigned char data ) +{ + // Execute interrupt only if interrupts are enabled + if( iflags_ & IFF1 ) { + // Disable maskable interrupts and restart the CPU if halted + iflags_ &= ~(IFF1 | IFF2 | Halted); + + switch( getInterruptMode() ) { + case 0: + OpInfo_[ data ].handler(); + cycles_ += 11; + break; + case 1: + callSub( 0x38 ); + cycles_ += 11; + break; + case 2: + callSub( readWord( ((unsigned)I) << 8 | (data & 0xFE) ) ); + cycles_ += 19; + break; + } + } +} + +/* Non-maskable interrupt */ +void nmi(void) +{ + // Disable maskable interrupts but preserve IFF2 (that is a copy of IFF1), + // also restart the CPU if halted + iflags_ &= ~(IFF1 | Halted); + + callSub( 0x66 ); + + cycles_ += 11; +} + +void do_opcode_xy( OpcodeInfo * info ) +{ + unsigned op = fetchByte(); + + if( (op == 0xDD) || (op == 0xFD) ) { + // Exit now, to avoid possible infinite loops + PC--; + cycles_ += OpInfo_[ 0 ].cycles; // NOP + } + else if( op == 0xED ) { + // IX or IY prefix is ignored for this opcode + opcode_ed(); + } + else { + // Handle IX or IY prefix if possible + if( info[ op ].handler ) { + // Extended opcode is valid + cycles_ += info[ op ].cycles; + info[ op ].handler(); + } + else { + // Extended opcode not valid, fall back to standard opcode + cycles_ += OpInfo_[ op ].cycles; + OpInfo_[ op ].handler(); + } + } +} + diff --git a/apps/plugins/pacbox/z80.h b/apps/plugins/pacbox/z80.h new file mode 100644 index 0000000000..b6288981d0 --- /dev/null +++ b/apps/plugins/pacbox/z80.h @@ -0,0 +1,160 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef Z80_H_ +#define Z80_H_ + +/** + Environment for Z80 emulation. + + This class implements all input/output functions for the Z80 emulator class, + that is it provides functions to access the system RAM, ROM and I/O ports. + + An object of this class corresponds to a system that has no RAM, ROM or ports: + users of the Z80 emulator should provide the desired behaviour by writing a + descendant of this class. + + @author Alessandro Scotti + @version 1.0 +*/ + + /** Sets the CPU cycle counter to the specified value. */ +void setCycles( unsigned value ); + +void onReturnFromInterrupt(void); + + +/** + Z80 software emulator. + + @author Alessandro Scotti + @version 1.1 +*/ + /** CPU flags */ + enum { + Carry = 0x01, // C + AddSub = 0x02, Subtraction = AddSub, // N + Parity = 0x04, Overflow = Parity, // P/V, same bit used for parity and overflow + Flag3 = 0x08, // Aka XF, not used + Halfcarry = 0x10, // H + Flag5 = 0x20, // Aka YF, not used + Zero = 0x40, // Z + Sign = 0x80 // S + }; + + /** + Constructor: creates a Z80 object with the specified environment. + */ +// Z80( Z80Environment & ); + + /** + Copy constructor: creates a copy of the specified Z80 object. + */ +// Z80( const Z80 & ); + +// /** Destructor. */ +// virtual ~Z80() { + + /** + Resets the CPU to its initial state. + + The stack pointer (SP) is set to F000h, all other registers are cleared. + */ + void z80_reset(void); + + /** + Runs the CPU for the specified number of cycles. + + Note that the number of CPU cycles performed by this function may be + actually a little more than the value specified. If that happens then the + function returns the number of extra cycles executed. + + @param cycles number of cycles the CPU must execute + + @return the number of extra cycles executed by the last instruction + */ + unsigned z80_run( unsigned cycles ); + + /** + Executes one instruction. + */ + void z80_step(void); + + /** + Invokes an interrupt. + + If interrupts are enabled, the current program counter (PC) is saved on + the stack and assigned the specified address. When the interrupt handler + returns, execution resumes from the point where the interrupt occurred. + + The actual interrupt address depends on the current interrupt mode and + on the interrupt type. For maskable interrupts, data is as follows: + - mode 0: data is an opcode that is executed (usually RST xxh); + - mode 1: data is ignored and a call is made to address 0x38; + - mode 2: a call is made to the 16 bit address given by (256*I + data). + */ + void z80_interrupt( unsigned char data ); + + /** Forces a non-maskable interrupt. */ + void z80_nmi(void); + + /** + Copies CPU register from one object to another. + + Note that the environment is not copied, only registers. + */ +// Z80 & operator = ( const Z80 & ); + + /** Returns the size of the buffer needed to take a snapshot of the CPU. */ + unsigned getSizeOfSnapshotBuffer(void); + + /** + Takes a snapshot of the CPU. + + A snapshot saves all of the CPU registers and internals. It can be + restored at any time to bring the CPU back to the exact status it + had when the snapshot was taken. + + Note: the size of the snapshot buffer must be no less than the size + returned by the getSizeOfSnapshotBuffer() function. + + @param buffer buffer where the snapshot data is stored + + @return the number of bytes written into the buffer + */ + unsigned takeSnapshot( unsigned char * buffer ); + + /** + Restores a snapshot taken with takeSnapshot(). + + This function uses the data saved in the snapshot buffer to restore the + CPU status. + + @param buffer buffer where the snapshot data is stored + + @return the number of bytes read from the buffer + */ + unsigned restoreSnapshot( unsigned char * buffer ); + +#endif // Z80_H_ diff --git a/apps/plugins/pacbox/z80_internal.h b/apps/plugins/pacbox/z80_internal.h new file mode 100644 index 0000000000..4e45aa7d7b --- /dev/null +++ b/apps/plugins/pacbox/z80_internal.h @@ -0,0 +1,1062 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Pacbox - a Pacman Emulator for Rockbox + * + * Based on PIE - Pacman Instructional Emulator + * + * Copyright (c) 1997-2003,2004 Alessandro Scotti + * http://www.ascotti.org/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef Z80_INTERNAL_H_ +#define Z80_INTERNAL_H_ + +// Implementation of opcodes 0x00 to 0xFF +void opcode_00(void); // NOP +void opcode_01(void); // LD BC,nn +void opcode_02(void); // LD (BC),A +void opcode_03(void); // INC BC +void opcode_04(void); // INC B +void opcode_05(void); // DEC B +void opcode_06(void); // LD B,n +void opcode_07(void); // RLCA +void opcode_08(void); // EX AF,AF' +void opcode_09(void); // ADD HL,BC +void opcode_0a(void); // LD A,(BC) +void opcode_0b(void); // DEC BC +void opcode_0c(void); // INC C +void opcode_0d(void); // DEC C +void opcode_0e(void); // LD C,n +void opcode_0f(void); // RRCA +void opcode_10(void); // DJNZ d +void opcode_11(void); // LD DE,nn +void opcode_12(void); // LD (DE),A +void opcode_13(void); // INC DE +void opcode_14(void); // INC D +void opcode_15(void); // DEC D +void opcode_16(void); // LD D,n +void opcode_17(void); // RLA +void opcode_18(void); // JR d +void opcode_19(void); // ADD HL,DE +void opcode_1a(void); // LD A,(DE) +void opcode_1b(void); // DEC DE +void opcode_1c(void); // INC E +void opcode_1d(void); // DEC E +void opcode_1e(void); // LD E,n +void opcode_1f(void); // RRA +void opcode_20(void); // JR NZ,d +void opcode_21(void); // LD HL,nn +void opcode_22(void); // LD (nn),HL +void opcode_23(void); // INC HL +void opcode_24(void); // INC H +void opcode_25(void); // DEC H +void opcode_26(void); // LD H,n +void opcode_27(void); // DAA +void opcode_28(void); // JR Z,d +void opcode_29(void); // ADD HL,HL +void opcode_2a(void); // LD HL,(nn) +void opcode_2b(void); // DEC HL +void opcode_2c(void); // INC L +void opcode_2d(void); // DEC L +void opcode_2e(void); // LD L,n +void opcode_2f(void); // CPL +void opcode_30(void); // JR NC,d +void opcode_31(void); // LD SP,nn +void opcode_32(void); // LD (nn),A +void opcode_33(void); // INC SP +void opcode_34(void); // INC (HL) +void opcode_35(void); // DEC (HL) +void opcode_36(void); // LD (HL),n +void opcode_37(void); // SCF +void opcode_38(void); // JR C,d +void opcode_39(void); // ADD HL,SP +void opcode_3a(void); // LD A,(nn) +void opcode_3b(void); // DEC SP +void opcode_3c(void); // INC A +void opcode_3d(void); // DEC A +void opcode_3e(void); // LD A,n +void opcode_3f(void); // CCF +void opcode_40(void); // LD B,B +void opcode_41(void); // LD B,C +void opcode_42(void); // LD B,D +void opcode_43(void); // LD B,E +void opcode_44(void); // LD B,H +void opcode_45(void); // LD B,L +void opcode_46(void); // LD B,(HL) +void opcode_47(void); // LD B,A +void opcode_48(void); // LD C,B +void opcode_49(void); // LD C,C +void opcode_4a(void); // LD C,D +void opcode_4b(void); // LD C,E +void opcode_4c(void); // LD C,H +void opcode_4d(void); // LD C,L +void opcode_4e(void); // LD C,(HL) +void opcode_4f(void); // LD C,A +void opcode_50(void); // LD D,B +void opcode_51(void); // LD D,C +void opcode_52(void); // LD D,D +void opcode_53(void); // LD D,E +void opcode_54(void); // LD D,H +void opcode_55(void); // LD D,L +void opcode_56(void); // LD D,(HL) +void opcode_57(void); // LD D,A +void opcode_58(void); // LD E,B +void opcode_59(void); // LD E,C +void opcode_5a(void); // LD E,D +void opcode_5b(void); // LD E,E +void opcode_5c(void); // LD E,H +void opcode_5d(void); // LD E,L +void opcode_5e(void); // LD E,(HL) +void opcode_5f(void); // LD E,A +void opcode_60(void); // LD H,B +void opcode_61(void); // LD H,C +void opcode_62(void); // LD H,D +void opcode_63(void); // LD H,E +void opcode_64(void); // LD H,H +void opcode_65(void); // LD H,L +void opcode_66(void); // LD H,(HL) +void opcode_67(void); // LD H,A +void opcode_68(void); // LD L,B +void opcode_69(void); // LD L,C +void opcode_6a(void); // LD L,D +void opcode_6b(void); // LD L,E +void opcode_6c(void); // LD L,H +void opcode_6d(void); // LD L,L +void opcode_6e(void); // LD L,(HL) +void opcode_6f(void); // LD L,A +void opcode_70(void); // LD (HL),B +void opcode_71(void); // LD (HL),C +void opcode_72(void); // LD (HL),D +void opcode_73(void); // LD (HL),E +void opcode_74(void); // LD (HL),H +void opcode_75(void); // LD (HL),L +void opcode_76(void); // HALT +void opcode_77(void); // LD (HL),A +void opcode_78(void); // LD A,B +void opcode_79(void); // LD A,C +void opcode_7a(void); // LD A,D +void opcode_7b(void); // LD A,E +void opcode_7c(void); // LD A,H +void opcode_7d(void); // LD A,L +void opcode_7e(void); // LD A,(HL) +void opcode_7f(void); // LD A,A +void opcode_80(void); // ADD A,B +void opcode_81(void); // ADD A,C +void opcode_82(void); // ADD A,D +void opcode_83(void); // ADD A,E +void opcode_84(void); // ADD A,H +void opcode_85(void); // ADD A,L +void opcode_86(void); // ADD A,(HL) +void opcode_87(void); // ADD A,A +void opcode_88(void); // ADC A,B +void opcode_89(void); // ADC A,C +void opcode_8a(void); // ADC A,D +void opcode_8b(void); // ADC A,E +void opcode_8c(void); // ADC A,H +void opcode_8d(void); // ADC A,L +void opcode_8e(void); // ADC A,(HL) +void opcode_8f(void); // ADC A,A +void opcode_90(void); // SUB B +void opcode_91(void); // SUB C +void opcode_92(void); // SUB D +void opcode_93(void); // SUB E +void opcode_94(void); // SUB H +void opcode_95(void); // SUB L +void opcode_96(void); // SUB (HL) +void opcode_97(void); // SUB A +void opcode_98(void); // SBC A,B +void opcode_99(void); // SBC A,C +void opcode_9a(void); // SBC A,D +void opcode_9b(void); // SBC A,E +void opcode_9c(void); // SBC A,H +void opcode_9d(void); // SBC A,L +void opcode_9e(void); // SBC A,(HL) +void opcode_9f(void); // SBC A,A +void opcode_a0(void); // AND B +void opcode_a1(void); // AND C +void opcode_a2(void); // AND D +void opcode_a3(void); // AND E +void opcode_a4(void); // AND H +void opcode_a5(void); // AND L +void opcode_a6(void); // AND (HL) +void opcode_a7(void); // AND A +void opcode_a8(void); // XOR B +void opcode_a9(void); // XOR C +void opcode_aa(void); // XOR D +void opcode_ab(void); // XOR E +void opcode_ac(void); // XOR H +void opcode_ad(void); // XOR L +void opcode_ae(void); // XOR (HL) +void opcode_af(void); // XOR A +void opcode_b0(void); // OR B +void opcode_b1(void); // OR C +void opcode_b2(void); // OR D +void opcode_b3(void); // OR E +void opcode_b4(void); // OR H +void opcode_b5(void); // OR L +void opcode_b6(void); // OR (HL) +void opcode_b7(void); // OR A +void opcode_b8(void); // CP B +void opcode_b9(void); // CP C +void opcode_ba(void); // CP D +void opcode_bb(void); // CP E +void opcode_bc(void); // CP H +void opcode_bd(void); // CP L +void opcode_be(void); // CP (HL) +void opcode_bf(void); // CP A +void opcode_c0(void); // RET NZ +void opcode_c1(void); // POP BC +void opcode_c2(void); // JP NZ,nn +void opcode_c3(void); // JP nn +void opcode_c4(void); // CALL NZ,nn +void opcode_c5(void); // PUSH BC +void opcode_c6(void); // ADD A,n +void opcode_c7(void); // RST 0 +void opcode_c8(void); // RET Z +void opcode_c9(void); // RET +void opcode_ca(void); // JP Z,nn +void opcode_cb(void); // [Prefix] +void opcode_cc(void); // CALL Z,nn +void opcode_cd(void); // CALL nn +void opcode_ce(void); // ADC A,n +void opcode_cf(void); // RST 8 +void opcode_d0(void); // RET NC +void opcode_d1(void); // POP DE +void opcode_d2(void); // JP NC,nn +void opcode_d3(void); // OUT (n),A +void opcode_d4(void); // CALL NC,nn +void opcode_d5(void); // PUSH DE +void opcode_d6(void); // SUB n +void opcode_d7(void); // RST 10H +void opcode_d8(void); // RET C +void opcode_d9(void); // EXX +void opcode_da(void); // JP C,nn +void opcode_db(void); // IN A,(n) +void opcode_dc(void); // CALL C,nn +void opcode_dd(void); // [IX Prefix] +void opcode_de(void); // SBC A,n +void opcode_df(void); // RST 18H +void opcode_e0(void); // RET PO +void opcode_e1(void); // POP HL +void opcode_e2(void); // JP PO,nn +void opcode_e3(void); // EX (SP),HL +void opcode_e4(void); // CALL PO,nn +void opcode_e5(void); // PUSH HL +void opcode_e6(void); // AND n +void opcode_e7(void); // RST 20H +void opcode_e8(void); // RET PE +void opcode_e9(void); // JP (HL) +void opcode_ea(void); // JP PE,nn +void opcode_eb(void); // EX DE,HL +void opcode_ec(void); // CALL PE,nn +void opcode_ed(void); // [Prefix] +void opcode_ee(void); // XOR n +void opcode_ef(void); // RST 28H +void opcode_f0(void); // RET P +void opcode_f1(void); // POP AF +void opcode_f2(void); // JP P,nn +void opcode_f3(void); // DI +void opcode_f4(void); // CALL P,nn +void opcode_f5(void); // PUSH AF +void opcode_f6(void); // OR n +void opcode_f7(void); // RST 30H +void opcode_f8(void); // RET M +void opcode_f9(void); // LD SP,HL +void opcode_fa(void); // JP M,nn +void opcode_fb(void); // EI +void opcode_fc(void); // CALL M,nn +void opcode_fd(void); // [IY Prefix] +void opcode_fe(void); // CP n +void opcode_ff(void); // RST 38H + +// Handlers for the 0xCB prefix +void opcode_cb_00(void); // RLC B +void opcode_cb_01(void); // RLC C +void opcode_cb_02(void); // RLC D +void opcode_cb_03(void); // RLC E +void opcode_cb_04(void); // RLC H +void opcode_cb_05(void); // RLC L +void opcode_cb_06(void); // RLC (HL) +void opcode_cb_07(void); // RLC A +void opcode_cb_08(void); // RRC B +void opcode_cb_09(void); // RRC C +void opcode_cb_0a(void); // RRC D +void opcode_cb_0b(void); // RRC E +void opcode_cb_0c(void); // RRC H +void opcode_cb_0d(void); // RRC L +void opcode_cb_0e(void); // RRC (HL) +void opcode_cb_0f(void); // RRC A +void opcode_cb_10(void); // RL B +void opcode_cb_11(void); // RL C +void opcode_cb_12(void); // RL D +void opcode_cb_13(void); // RL E +void opcode_cb_14(void); // RL H +void opcode_cb_15(void); // RL L +void opcode_cb_16(void); // RL (HL) +void opcode_cb_17(void); // RL A +void opcode_cb_18(void); // RR B +void opcode_cb_19(void); // RR C +void opcode_cb_1a(void); // RR D +void opcode_cb_1b(void); // RR E +void opcode_cb_1c(void); // RR H +void opcode_cb_1d(void); // RR L +void opcode_cb_1e(void); // RR (HL) +void opcode_cb_1f(void); // RR A +void opcode_cb_20(void); // SLA B +void opcode_cb_21(void); // SLA C +void opcode_cb_22(void); // SLA D +void opcode_cb_23(void); // SLA E +void opcode_cb_24(void); // SLA H +void opcode_cb_25(void); // SLA L +void opcode_cb_26(void); // SLA (HL) +void opcode_cb_27(void); // SLA A +void opcode_cb_28(void); // SRA B +void opcode_cb_29(void); // SRA C +void opcode_cb_2a(void); // SRA D +void opcode_cb_2b(void); // SRA E +void opcode_cb_2c(void); // SRA H +void opcode_cb_2d(void); // SRA L +void opcode_cb_2e(void); // SRA (HL) +void opcode_cb_2f(void); // SRA A +void opcode_cb_30(void); // SLL B [undocumented] +void opcode_cb_31(void); // SLL C [undocumented] +void opcode_cb_32(void); // SLL D [undocumented] +void opcode_cb_33(void); // SLL E [undocumented] +void opcode_cb_34(void); // SLL H [undocumented] +void opcode_cb_35(void); // SLL L [undocumented] +void opcode_cb_36(void); // SLL (HL) [undocumented] +void opcode_cb_37(void); // SLL A [undocumented] +void opcode_cb_38(void); // SRL B +void opcode_cb_39(void); // SRL C +void opcode_cb_3a(void); // SRL D +void opcode_cb_3b(void); // SRL E +void opcode_cb_3c(void); // SRL H +void opcode_cb_3d(void); // SRL L +void opcode_cb_3e(void); // SRL (HL) +void opcode_cb_3f(void); // SRL A +void opcode_cb_40(void); // BIT 0, B +void opcode_cb_41(void); // BIT 0, C +void opcode_cb_42(void); // BIT 0, D +void opcode_cb_43(void); // BIT 0, E +void opcode_cb_44(void); // BIT 0, H +void opcode_cb_45(void); // BIT 0, L +void opcode_cb_46(void); // BIT 0, (HL) +void opcode_cb_47(void); // BIT 0, A +void opcode_cb_48(void); // BIT 1, B +void opcode_cb_49(void); // BIT 1, C +void opcode_cb_4a(void); // BIT 1, D +void opcode_cb_4b(void); // BIT 1, E +void opcode_cb_4c(void); // BIT 1, H +void opcode_cb_4d(void); // BIT 1, L +void opcode_cb_4e(void); // BIT 1, (HL) +void opcode_cb_4f(void); // BIT 1, A +void opcode_cb_50(void); // BIT 2, B +void opcode_cb_51(void); // BIT 2, C +void opcode_cb_52(void); // BIT 2, D +void opcode_cb_53(void); // BIT 2, E +void opcode_cb_54(void); // BIT 2, H +void opcode_cb_55(void); // BIT 2, L +void opcode_cb_56(void); // BIT 2, (HL) +void opcode_cb_57(void); // BIT 2, A +void opcode_cb_58(void); // BIT 3, B +void opcode_cb_59(void); // BIT 3, C +void opcode_cb_5a(void); // BIT 3, D +void opcode_cb_5b(void); // BIT 3, E +void opcode_cb_5c(void); // BIT 3, H +void opcode_cb_5d(void); // BIT 3, L +void opcode_cb_5e(void); // BIT 3, (HL) +void opcode_cb_5f(void); // BIT 3, A +void opcode_cb_60(void); // BIT 4, B +void opcode_cb_61(void); // BIT 4, C +void opcode_cb_62(void); // BIT 4, D +void opcode_cb_63(void); // BIT 4, E +void opcode_cb_64(void); // BIT 4, H +void opcode_cb_65(void); // BIT 4, L +void opcode_cb_66(void); // BIT 4, (HL) +void opcode_cb_67(void); // BIT 4, A +void opcode_cb_68(void); // BIT 5, B +void opcode_cb_69(void); // BIT 5, C +void opcode_cb_6a(void); // BIT 5, D +void opcode_cb_6b(void); // BIT 5, E +void opcode_cb_6c(void); // BIT 5, H +void opcode_cb_6d(void); // BIT 5, L +void opcode_cb_6e(void); // BIT 5, (HL) +void opcode_cb_6f(void); // BIT 5, A +void opcode_cb_70(void); // BIT 6, B +void opcode_cb_71(void); // BIT 6, C +void opcode_cb_72(void); // BIT 6, D +void opcode_cb_73(void); // BIT 6, E +void opcode_cb_74(void); // BIT 6, H +void opcode_cb_75(void); // BIT 6, L +void opcode_cb_76(void); // BIT 6, (HL) +void opcode_cb_77(void); // BIT 6, A +void opcode_cb_78(void); // BIT 7, B +void opcode_cb_79(void); // BIT 7, C +void opcode_cb_7a(void); // BIT 7, D +void opcode_cb_7b(void); // BIT 7, E +void opcode_cb_7c(void); // BIT 7, H +void opcode_cb_7d(void); // BIT 7, L +void opcode_cb_7e(void); // BIT 7, (HL) +void opcode_cb_7f(void); // BIT 7, A +void opcode_cb_80(void); // RES 0, B +void opcode_cb_81(void); // RES 0, C +void opcode_cb_82(void); // RES 0, D +void opcode_cb_83(void); // RES 0, E +void opcode_cb_84(void); // RES 0, H +void opcode_cb_85(void); // RES 0, L +void opcode_cb_86(void); // RES 0, (HL) +void opcode_cb_87(void); // RES 0, A +void opcode_cb_88(void); // RES 1, B +void opcode_cb_89(void); // RES 1, C +void opcode_cb_8a(void); // RES 1, D +void opcode_cb_8b(void); // RES 1, E +void opcode_cb_8c(void); // RES 1, H +void opcode_cb_8d(void); // RES 1, L +void opcode_cb_8e(void); // RES 1, (HL) +void opcode_cb_8f(void); // RES 1, A +void opcode_cb_90(void); // RES 2, B +void opcode_cb_91(void); // RES 2, C +void opcode_cb_92(void); // RES 2, D +void opcode_cb_93(void); // RES 2, E +void opcode_cb_94(void); // RES 2, H +void opcode_cb_95(void); // RES 2, L +void opcode_cb_96(void); // RES 2, (HL) +void opcode_cb_97(void); // RES 2, A +void opcode_cb_98(void); // RES 3, B +void opcode_cb_99(void); // RES 3, C +void opcode_cb_9a(void); // RES 3, D +void opcode_cb_9b(void); // RES 3, E +void opcode_cb_9c(void); // RES 3, H +void opcode_cb_9d(void); // RES 3, L +void opcode_cb_9e(void); // RES 3, (HL) +void opcode_cb_9f(void); // RES 3, A +void opcode_cb_a0(void); // RES 4, B +void opcode_cb_a1(void); // RES 4, C +void opcode_cb_a2(void); // RES 4, D +void opcode_cb_a3(void); // RES 4, E +void opcode_cb_a4(void); // RES 4, H +void opcode_cb_a5(void); // RES 4, L +void opcode_cb_a6(void); // RES 4, (HL) +void opcode_cb_a7(void); // RES 4, A +void opcode_cb_a8(void); // RES 5, B +void opcode_cb_a9(void); // RES 5, C +void opcode_cb_aa(void); // RES 5, D +void opcode_cb_ab(void); // RES 5, E +void opcode_cb_ac(void); // RES 5, H +void opcode_cb_ad(void); // RES 5, L +void opcode_cb_ae(void); // RES 5, (HL) +void opcode_cb_af(void); // RES 5, A +void opcode_cb_b0(void); // RES 6, B +void opcode_cb_b1(void); // RES 6, C +void opcode_cb_b2(void); // RES 6, D +void opcode_cb_b3(void); // RES 6, E +void opcode_cb_b4(void); // RES 6, H +void opcode_cb_b5(void); // RES 6, L +void opcode_cb_b6(void); // RES 6, (HL) +void opcode_cb_b7(void); // RES 6, A +void opcode_cb_b8(void); // RES 7, B +void opcode_cb_b9(void); // RES 7, C +void opcode_cb_ba(void); // RES 7, D +void opcode_cb_bb(void); // RES 7, E +void opcode_cb_bc(void); // RES 7, H +void opcode_cb_bd(void); // RES 7, L +void opcode_cb_be(void); // RES 7, (HL) +void opcode_cb_bf(void); // RES 7, A +void opcode_cb_c0(void); // SET 0, B +void opcode_cb_c1(void); // SET 0, C +void opcode_cb_c2(void); // SET 0, D +void opcode_cb_c3(void); // SET 0, E +void opcode_cb_c4(void); // SET 0, H +void opcode_cb_c5(void); // SET 0, L +void opcode_cb_c6(void); // SET 0, (HL) +void opcode_cb_c7(void); // SET 0, A +void opcode_cb_c8(void); // SET 1, B +void opcode_cb_c9(void); // SET 1, C +void opcode_cb_ca(void); // SET 1, D +void opcode_cb_cb(void); // SET 1, E +void opcode_cb_cc(void); // SET 1, H +void opcode_cb_cd(void); // SET 1, L +void opcode_cb_ce(void); // SET 1, (HL) +void opcode_cb_cf(void); // SET 1, A +void opcode_cb_d0(void); // SET 2, B +void opcode_cb_d1(void); // SET 2, C +void opcode_cb_d2(void); // SET 2, D +void opcode_cb_d3(void); // SET 2, E +void opcode_cb_d4(void); // SET 2, H +void opcode_cb_d5(void); // SET 2, L +void opcode_cb_d6(void); // SET 2, (HL) +void opcode_cb_d7(void); // SET 2, A +void opcode_cb_d8(void); // SET 3, B +void opcode_cb_d9(void); // SET 3, C +void opcode_cb_da(void); // SET 3, D +void opcode_cb_db(void); // SET 3, E +void opcode_cb_dc(void); // SET 3, H +void opcode_cb_dd(void); // SET 3, L +void opcode_cb_de(void); // SET 3, (HL) +void opcode_cb_df(void); // SET 3, A +void opcode_cb_e0(void); // SET 4, B +void opcode_cb_e1(void); // SET 4, C +void opcode_cb_e2(void); // SET 4, D +void opcode_cb_e3(void); // SET 4, E +void opcode_cb_e4(void); // SET 4, H +void opcode_cb_e5(void); // SET 4, L +void opcode_cb_e6(void); // SET 4, (HL) +void opcode_cb_e7(void); // SET 4, A +void opcode_cb_e8(void); // SET 5, B +void opcode_cb_e9(void); // SET 5, C +void opcode_cb_ea(void); // SET 5, D +void opcode_cb_eb(void); // SET 5, E +void opcode_cb_ec(void); // SET 5, H +void opcode_cb_ed(void); // SET 5, L +void opcode_cb_ee(void); // SET 5, (HL) +void opcode_cb_ef(void); // SET 5, A +void opcode_cb_f0(void); // SET 6, B +void opcode_cb_f1(void); // SET 6, C +void opcode_cb_f2(void); // SET 6, D +void opcode_cb_f3(void); // SET 6, E +void opcode_cb_f4(void); // SET 6, H +void opcode_cb_f5(void); // SET 6, L +void opcode_cb_f6(void); // SET 6, (HL) +void opcode_cb_f7(void); // SET 6, A +void opcode_cb_f8(void); // SET 7, B +void opcode_cb_f9(void); // SET 7, C +void opcode_cb_fa(void); // SET 7, D +void opcode_cb_fb(void); // SET 7, E +void opcode_cb_fc(void); // SET 7, H +void opcode_cb_fd(void); // SET 7, L +void opcode_cb_fe(void); // SET 7, (HL) +void opcode_cb_ff(void); // SET 7, A + +// Handlers for the 0xED prefix +void opcode_ed_40(void); // IN B, (C) +void opcode_ed_41(void); // OUT (C), B +void opcode_ed_42(void); // SBC HL, BC +void opcode_ed_43(void); // LD (nn), BC +void opcode_ed_44(void); // NEG +void opcode_ed_45(void); // RETN +void opcode_ed_46(void); // IM 0 +void opcode_ed_47(void); // LD I, A +void opcode_ed_48(void); // IN C, (C) +void opcode_ed_49(void); // OUT (C), C +void opcode_ed_4a(void); // ADC HL, BC +void opcode_ed_4b(void); // LD BC, (nn) +void opcode_ed_4c(void); // NEG [undocumented] +void opcode_ed_4d(void); // RETI +void opcode_ed_4e(void); // IM 0/1 [undocumented] +void opcode_ed_4f(void); // LD R, A +void opcode_ed_50(void); // IN D, (C) +void opcode_ed_51(void); // OUT (C), D +void opcode_ed_52(void); // SBC HL, DE +void opcode_ed_53(void); // LD (nn), DE +void opcode_ed_54(void); // NEG [undocumented] +void opcode_ed_55(void); // RETN [undocumented] +void opcode_ed_56(void); // IM 1 +void opcode_ed_57(void); // LD A, I +void opcode_ed_58(void); // IN E, (C) +void opcode_ed_59(void); // OUT (C), E +void opcode_ed_5a(void); // ADC HL, DE +void opcode_ed_5b(void); // LD DE, (nn) +void opcode_ed_5c(void); // NEG [undocumented] +void opcode_ed_5d(void); // RETN [undocumented] +void opcode_ed_5e(void); // IM 2 +void opcode_ed_5f(void); // LD A, R +void opcode_ed_60(void); // IN H, (C) +void opcode_ed_61(void); // OUT (C), H +void opcode_ed_62(void); // SBC HL, HL +void opcode_ed_63(void); // LD (nn), HL +void opcode_ed_64(void); // NEG [undocumented] +void opcode_ed_65(void); // RETN [undocumented] +void opcode_ed_66(void); // IM 0 [undocumented] +void opcode_ed_67(void); // RRD +void opcode_ed_68(void); // IN L, (C) +void opcode_ed_69(void); // OUT (C), L +void opcode_ed_6a(void); // ADC HL, HL +void opcode_ed_6b(void); // LD HL, (nn) +void opcode_ed_6c(void); // NEG [undocumented] +void opcode_ed_6d(void); // RETN [undocumented] +void opcode_ed_6e(void); // IM 0/1 [undocumented] +void opcode_ed_6f(void); // RLD +void opcode_ed_70(void); // IN (C)/IN F, (C) [undocumented] +void opcode_ed_71(void); // OUT (C), 0 [undocumented] +void opcode_ed_72(void); // SBC HL, SP +void opcode_ed_73(void); // LD (nn), SP +void opcode_ed_74(void); // NEG [undocumented] +void opcode_ed_75(void); // RETN [undocumented] +void opcode_ed_76(void); // IM 1 [undocumented] +void opcode_ed_78(void); // IN A, (C) +void opcode_ed_79(void); // OUT (C), A +void opcode_ed_7a(void); // ADC HL, SP +void opcode_ed_7b(void); // nLD SP, (nn) +void opcode_ed_7c(void); // NEG [undocumented] +void opcode_ed_7d(void); // RETN [undocumented] +void opcode_ed_7e(void); // IM 2 [undocumented] +void opcode_ed_a0(void); // LDI +void opcode_ed_a1(void); // CPI +void opcode_ed_a2(void); // INI +void opcode_ed_a3(void); // OUTI +void opcode_ed_a8(void); // LDD +void opcode_ed_a9(void); // CPD +void opcode_ed_aa(void); // IND +void opcode_ed_ab(void); // OUTD +void opcode_ed_b0(void); // LDIR +void opcode_ed_b1(void); // CPIR +void opcode_ed_b2(void); // INIR +void opcode_ed_b3(void); // OTIR +void opcode_ed_b8(void); // LDDR +void opcode_ed_b9(void); // CPDR +void opcode_ed_ba(void); // INDR +void opcode_ed_bb(void); // OTDR + +// Handlers for the 0xDD prefix (IX) +void opcode_dd_09(void); // ADD IX, BC +void opcode_dd_19(void); // ADD IX, DE +void opcode_dd_21(void); // LD IX, nn +void opcode_dd_22(void); // LD (nn), IX +void opcode_dd_23(void); // INC IX +void opcode_dd_24(void); // INC IXH [undocumented] +void opcode_dd_25(void); // DEC IXH [undocumented] +void opcode_dd_26(void); // LD IXH, n [undocumented] +void opcode_dd_29(void); // ADD IX, IX +void opcode_dd_2a(void); // LD IX, (nn) +void opcode_dd_2b(void); // DEC IX +void opcode_dd_2c(void); // INC IXL [undocumented] +void opcode_dd_2d(void); // DEC IXL [undocumented] +void opcode_dd_2e(void); // LD IXL, n [undocumented] +void opcode_dd_34(void); // INC (IX + d) +void opcode_dd_35(void); // DEC (IX + d) +void opcode_dd_36(void); // LD (IX + d), n +void opcode_dd_39(void); // ADD IX, SP +void opcode_dd_44(void); // LD B, IXH [undocumented] +void opcode_dd_45(void); // LD B, IXL [undocumented] +void opcode_dd_46(void); // LD B, (IX + d) +void opcode_dd_4c(void); // LD C, IXH [undocumented] +void opcode_dd_4d(void); // LD C, IXL [undocumented] +void opcode_dd_4e(void); // LD C, (IX + d) +void opcode_dd_54(void); // LD D, IXH [undocumented] +void opcode_dd_55(void); // LD D, IXL [undocumented] +void opcode_dd_56(void); // LD D, (IX + d) +void opcode_dd_5c(void); // LD E, IXH [undocumented] +void opcode_dd_5d(void); // LD E, IXL [undocumented] +void opcode_dd_5e(void); // LD E, (IX + d) +void opcode_dd_60(void); // LD IXH, B [undocumented] +void opcode_dd_61(void); // LD IXH, C [undocumented] +void opcode_dd_62(void); // LD IXH, D [undocumented] +void opcode_dd_63(void); // LD IXH, E [undocumented] +void opcode_dd_64(void); // LD IXH, IXH [undocumented] +void opcode_dd_65(void); // LD IXH, IXL [undocumented] +void opcode_dd_66(void); // LD H, (IX + d) +void opcode_dd_67(void); // LD IXH, A [undocumented] +void opcode_dd_68(void); // LD IXL, B [undocumented] +void opcode_dd_69(void); // LD IXL, C [undocumented] +void opcode_dd_6a(void); // LD IXL, D [undocumented] +void opcode_dd_6b(void); // LD IXL, E [undocumented] +void opcode_dd_6c(void); // LD IXL, IXH [undocumented] +void opcode_dd_6d(void); // LD IXL, IXL [undocumented] +void opcode_dd_6e(void); // LD L, (IX + d) +void opcode_dd_6f(void); // LD IXL, A [undocumented] +void opcode_dd_70(void); // LD (IX + d), B +void opcode_dd_71(void); // LD (IX + d), C +void opcode_dd_72(void); // LD (IX + d), D +void opcode_dd_73(void); // LD (IX + d), E +void opcode_dd_74(void); // LD (IX + d), H +void opcode_dd_75(void); // LD (IX + d), L +void opcode_dd_77(void); // LD (IX + d), A +void opcode_dd_7c(void); // LD A, IXH [undocumented] +void opcode_dd_7d(void); // LD A, IXL [undocumented] +void opcode_dd_7e(void); // LD A, (IX + d) +void opcode_dd_84(void); // ADD A, IXH [undocumented] +void opcode_dd_85(void); // ADD A, IXL [undocumented] +void opcode_dd_86(void); // ADD A, (IX + d) +void opcode_dd_8c(void); // ADC A, IXH [undocumented] +void opcode_dd_8d(void); // ADC A, IXL [undocumented] +void opcode_dd_8e(void); // ADC A, (IX + d) +void opcode_dd_94(void); // SUB IXH [undocumented] +void opcode_dd_95(void); // SUB IXL [undocumented] +void opcode_dd_96(void); // SUB (IX + d) +void opcode_dd_9c(void); // SBC A, IXH [undocumented] +void opcode_dd_9d(void); // SBC A, IXL [undocumented] +void opcode_dd_9e(void); // SBC A, (IX + d) +void opcode_dd_a4(void); // AND IXH [undocumented] +void opcode_dd_a5(void); // AND IXL [undocumented] +void opcode_dd_a6(void); // AND (IX + d) +void opcode_dd_ac(void); // XOR IXH [undocumented] +void opcode_dd_ad(void); // XOR IXL [undocumented] +void opcode_dd_ae(void); // XOR (IX + d) +void opcode_dd_b4(void); // OR IXH [undocumented] +void opcode_dd_b5(void); // OR IXL [undocumented] +void opcode_dd_b6(void); // OR (IX + d) +void opcode_dd_bc(void); // CP IXH [undocumented] +void opcode_dd_bd(void); // CP IXL [undocumented] +void opcode_dd_be(void); // CP (IX + d) +void opcode_dd_cb(void); // +void opcode_dd_e1(void); // POP IX +void opcode_dd_e3(void); // EX (SP), IX +void opcode_dd_e5(void); // PUSH IX +void opcode_dd_e9(void); // JP (IX) +void opcode_dd_f9(void); // LD SP, IX + +// Handlers for the 0xFD prefix (IY) +void opcode_fd_09(void); // ADD IY, BC +void opcode_fd_19(void); // ADD IY, DE +void opcode_fd_21(void); // LD IY, nn +void opcode_fd_22(void); // LD (nn), IY +void opcode_fd_23(void); // INC IY +void opcode_fd_24(void); // INC IYH [undocumented] +void opcode_fd_25(void); // DEC IYH [undocumented] +void opcode_fd_26(void); // LD IYH, n [undocumented] +void opcode_fd_29(void); // ADD IY, IY +void opcode_fd_2a(void); // LD IY, (nn) +void opcode_fd_2b(void); // DEC IY +void opcode_fd_2c(void); // INC IYL [undocumented] +void opcode_fd_2d(void); // DEC IYL [undocumented] +void opcode_fd_2e(void); // LD IYL, n [undocumented] +void opcode_fd_34(void); // INC (IY + d) +void opcode_fd_35(void); // DEC (IY + d) +void opcode_fd_36(void); // LD (IY + d), n +void opcode_fd_39(void); // ADD IY, SP +void opcode_fd_44(void); // LD B, IYH [undocumented] +void opcode_fd_45(void); // LD B, IYL [undocumented] +void opcode_fd_46(void); // LD B, (IY + d) +void opcode_fd_4c(void); // LD C, IYH [undocumented] +void opcode_fd_4d(void); // LD C, IYL [undocumented] +void opcode_fd_4e(void); // LD C, (IY + d) +void opcode_fd_54(void); // LD D, IYH [undocumented] +void opcode_fd_55(void); // LD D, IYL [undocumented] +void opcode_fd_56(void); // LD D, (IY + d) +void opcode_fd_5c(void); // LD E, IYH [undocumented] +void opcode_fd_5d(void); // LD E, IYL [undocumented] +void opcode_fd_5e(void); // LD E, (IY + d) +void opcode_fd_60(void); // LD IYH, B [undocumented] +void opcode_fd_61(void); // LD IYH, C [undocumented] +void opcode_fd_62(void); // LD IYH, D [undocumented] +void opcode_fd_63(void); // LD IYH, E [undocumented] +void opcode_fd_64(void); // LD IYH, IYH [undocumented] +void opcode_fd_65(void); // LD IYH, IYL [undocumented] +void opcode_fd_66(void); // LD H, (IY + d) +void opcode_fd_67(void); // LD IYH, A [undocumented] +void opcode_fd_68(void); // LD IYL, B [undocumented] +void opcode_fd_69(void); // LD IYL, C [undocumented] +void opcode_fd_6a(void); // LD IYL, D [undocumented] +void opcode_fd_6b(void); // LD IYL, E [undocumented] +void opcode_fd_6c(void); // LD IYL, IYH [undocumented] +void opcode_fd_6d(void); // LD IYL, IYL [undocumented] +void opcode_fd_6e(void); // LD L, (IY + d) +void opcode_fd_6f(void); // LD IYL, A [undocumented] +void opcode_fd_70(void); // LD (IY + d), B +void opcode_fd_71(void); // LD (IY + d), C +void opcode_fd_72(void); // LD (IY + d), D +void opcode_fd_73(void); // LD (IY + d), E +void opcode_fd_74(void); // LD (IY + d), H +void opcode_fd_75(void); // LD (IY + d), L +void opcode_fd_77(void); // LD (IY + d), A +void opcode_fd_7c(void); // LD A, IYH [undocumented] +void opcode_fd_7d(void); // LD A, IYL [undocumented] +void opcode_fd_7e(void); // LD A, (IY + d) +void opcode_fd_84(void); // ADD A, IYH [undocumented] +void opcode_fd_85(void); // ADD A, IYL [undocumented] +void opcode_fd_86(void); // ADD A, (IY + d) +void opcode_fd_8c(void); // ADC A, IYH [undocumented] +void opcode_fd_8d(void); // ADC A, IYL [undocumented] +void opcode_fd_8e(void); // ADC A, (IY + d) +void opcode_fd_94(void); // SUB IYH [undocumented] +void opcode_fd_95(void); // SUB IYL [undocumented] +void opcode_fd_96(void); // SUB (IY + d) +void opcode_fd_9c(void); // SBC A, IYH [undocumented] +void opcode_fd_9d(void); // SBC A, IYL [undocumented] +void opcode_fd_9e(void); // SBC A, (IY + d) +void opcode_fd_a4(void); // AND IYH [undocumented] +void opcode_fd_a5(void); // AND IYL [undocumented] +void opcode_fd_a6(void); // AND (IY + d) +void opcode_fd_ac(void); // XOR IYH [undocumented] +void opcode_fd_ad(void); // XOR IYL [undocumented] +void opcode_fd_ae(void); // XOR (IY + d) +void opcode_fd_b4(void); // OR IYH [undocumented] +void opcode_fd_b5(void); // OR IYL [undocumented] +void opcode_fd_b6(void); // OR (IY + d) +void opcode_fd_bc(void); // CP IYH [undocumented] +void opcode_fd_bd(void); // CP IYL [undocumented] +void opcode_fd_be(void); // CP (IY + d) +void opcode_fd_cb(void); // +void opcode_fd_e1(void); // POP IY +void opcode_fd_e3(void); // EX (SP), IY +void opcode_fd_e5(void); // PUSH IY +void opcode_fd_e9(void); // JP (IY) +void opcode_fd_f9(void); // LD SP, IY + +// Handlers for 0xDDCB and 0xFDCB prefixes +void opcode_xycb_00( unsigned ); // LD B, RLC (IX + d) [undocumented] +void opcode_xycb_01( unsigned ); // LD C, RLC (IX + d) [undocumented] +void opcode_xycb_02( unsigned ); // LD D, RLC (IX + d) [undocumented] +void opcode_xycb_03( unsigned ); // LD E, RLC (IX + d) [undocumented] +void opcode_xycb_04( unsigned ); // LD H, RLC (IX + d) [undocumented] +void opcode_xycb_05( unsigned ); // LD L, RLC (IX + d) [undocumented] +void opcode_xycb_06( unsigned ); // RLC (IX + d) +void opcode_xycb_07( unsigned ); // LD A, RLC (IX + d) [undocumented] +void opcode_xycb_08( unsigned ); // LD B, RRC (IX + d) [undocumented] +void opcode_xycb_09( unsigned ); // LD C, RRC (IX + d) [undocumented] +void opcode_xycb_0a( unsigned ); // LD D, RRC (IX + d) [undocumented] +void opcode_xycb_0b( unsigned ); // LD E, RRC (IX + d) [undocumented] +void opcode_xycb_0c( unsigned ); // LD H, RRC (IX + d) [undocumented] +void opcode_xycb_0d( unsigned ); // LD L, RRC (IX + d) [undocumented] +void opcode_xycb_0e( unsigned ); // RRC (IX + d) +void opcode_xycb_0f( unsigned ); // LD A, RRC (IX + d) [undocumented] +void opcode_xycb_10( unsigned ); // LD B, RL (IX + d) [undocumented] +void opcode_xycb_11( unsigned ); // LD C, RL (IX + d) [undocumented] +void opcode_xycb_12( unsigned ); // LD D, RL (IX + d) [undocumented] +void opcode_xycb_13( unsigned ); // LD E, RL (IX + d) [undocumented] +void opcode_xycb_14( unsigned ); // LD H, RL (IX + d) [undocumented] +void opcode_xycb_15( unsigned ); // LD L, RL (IX + d) [undocumented] +void opcode_xycb_16( unsigned ); // RL (IX + d) +void opcode_xycb_17( unsigned ); // LD A, RL (IX + d) [undocumented] +void opcode_xycb_18( unsigned ); // LD B, RR (IX + d) [undocumented] +void opcode_xycb_19( unsigned ); // LD C, RR (IX + d) [undocumented] +void opcode_xycb_1a( unsigned ); // LD D, RR (IX + d) [undocumented] +void opcode_xycb_1b( unsigned ); // LD E, RR (IX + d) [undocumented] +void opcode_xycb_1c( unsigned ); // LD H, RR (IX + d) [undocumented] +void opcode_xycb_1d( unsigned ); // LD L, RR (IX + d) [undocumented] +void opcode_xycb_1e( unsigned ); // RR (IX + d) +void opcode_xycb_1f( unsigned ); // LD A, RR (IX + d) [undocumented] +void opcode_xycb_20( unsigned ); // LD B, SLA (IX + d) [undocumented] +void opcode_xycb_21( unsigned ); // LD C, SLA (IX + d) [undocumented] +void opcode_xycb_22( unsigned ); // LD D, SLA (IX + d) [undocumented] +void opcode_xycb_23( unsigned ); // LD E, SLA (IX + d) [undocumented] +void opcode_xycb_24( unsigned ); // LD H, SLA (IX + d) [undocumented] +void opcode_xycb_25( unsigned ); // LD L, SLA (IX + d) [undocumented] +void opcode_xycb_26( unsigned ); // SLA (IX + d) +void opcode_xycb_27( unsigned ); // LD A, SLA (IX + d) [undocumented] +void opcode_xycb_28( unsigned ); // LD B, SRA (IX + d) [undocumented] +void opcode_xycb_29( unsigned ); // LD C, SRA (IX + d) [undocumented] +void opcode_xycb_2a( unsigned ); // LD D, SRA (IX + d) [undocumented] +void opcode_xycb_2b( unsigned ); // LD E, SRA (IX + d) [undocumented] +void opcode_xycb_2c( unsigned ); // LD H, SRA (IX + d) [undocumented] +void opcode_xycb_2d( unsigned ); // LD L, SRA (IX + d) [undocumented] +void opcode_xycb_2e( unsigned ); // SRA (IX + d) +void opcode_xycb_2f( unsigned ); // LD A, SRA (IX + d) [undocumented] +void opcode_xycb_30( unsigned ); // LD B, SLL (IX + d) [undocumented] +void opcode_xycb_31( unsigned ); // LD C, SLL (IX + d) [undocumented] +void opcode_xycb_32( unsigned ); // LD D, SLL (IX + d) [undocumented] +void opcode_xycb_33( unsigned ); // LD E, SLL (IX + d) [undocumented] +void opcode_xycb_34( unsigned ); // LD H, SLL (IX + d) [undocumented] +void opcode_xycb_35( unsigned ); // LD L, SLL (IX + d) [undocumented] +void opcode_xycb_36( unsigned ); // SLL (IX + d) [undocumented] +void opcode_xycb_37( unsigned ); // LD A, SLL (IX + d) [undocumented] +void opcode_xycb_38( unsigned ); // LD B, SRL (IX + d) [undocumented] +void opcode_xycb_39( unsigned ); // LD C, SRL (IX + d) [undocumented] +void opcode_xycb_3a( unsigned ); // LD D, SRL (IX + d) [undocumented] +void opcode_xycb_3b( unsigned ); // LD E, SRL (IX + d) [undocumented] +void opcode_xycb_3c( unsigned ); // LD H, SRL (IX + d) [undocumented] +void opcode_xycb_3d( unsigned ); // LD L, SRL (IX + d) [undocumented] +void opcode_xycb_3e( unsigned ); // SRL (IX + d) +void opcode_xycb_3f( unsigned ); // LD A, SRL (IX + d) [undocumented] +void opcode_xycb_40( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_41( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_42( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_43( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_44( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_45( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_46( unsigned ); // BIT 0, (IX + d) +void opcode_xycb_47( unsigned ); // BIT 0, (IX + d) [undocumented] +void opcode_xycb_48( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_49( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_4a( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_4b( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_4c( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_4d( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_4e( unsigned ); // BIT 1, (IX + d) +void opcode_xycb_4f( unsigned ); // BIT 1, (IX + d) [undocumented] +void opcode_xycb_50( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_51( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_52( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_53( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_54( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_55( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_56( unsigned ); // BIT 2, (IX + d) +void opcode_xycb_57( unsigned ); // BIT 2, (IX + d) [undocumented] +void opcode_xycb_58( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_59( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_5a( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_5b( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_5c( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_5d( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_5e( unsigned ); // BIT 3, (IX + d) +void opcode_xycb_5f( unsigned ); // BIT 3, (IX + d) [undocumented] +void opcode_xycb_60( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_61( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_62( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_63( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_64( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_65( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_66( unsigned ); // BIT 4, (IX + d) +void opcode_xycb_67( unsigned ); // BIT 4, (IX + d) [undocumented] +void opcode_xycb_68( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_69( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_6a( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_6b( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_6c( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_6d( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_6e( unsigned ); // BIT 5, (IX + d) +void opcode_xycb_6f( unsigned ); // BIT 5, (IX + d) [undocumented] +void opcode_xycb_70( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_71( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_72( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_73( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_74( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_75( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_76( unsigned ); // BIT 6, (IX + d) +void opcode_xycb_77( unsigned ); // BIT 6, (IX + d) [undocumented] +void opcode_xycb_78( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_79( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_7a( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_7b( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_7c( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_7d( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_7e( unsigned ); // BIT 7, (IX + d) +void opcode_xycb_7f( unsigned ); // BIT 7, (IX + d) [undocumented] +void opcode_xycb_80( unsigned ); // LD B, RES 0, (IX + d) [undocumented] +void opcode_xycb_81( unsigned ); // LD C, RES 0, (IX + d) [undocumented] +void opcode_xycb_82( unsigned ); // LD D, RES 0, (IX + d) [undocumented] +void opcode_xycb_83( unsigned ); // LD E, RES 0, (IX + d) [undocumented] +void opcode_xycb_84( unsigned ); // LD H, RES 0, (IX + d) [undocumented] +void opcode_xycb_85( unsigned ); // LD L, RES 0, (IX + d) [undocumented] +void opcode_xycb_86( unsigned ); // RES 0, (IX + d) +void opcode_xycb_87( unsigned ); // LD A, RES 0, (IX + d) [undocumented] +void opcode_xycb_88( unsigned ); // LD B, RES 1, (IX + d) [undocumented] +void opcode_xycb_89( unsigned ); // LD C, RES 1, (IX + d) [undocumented] +void opcode_xycb_8a( unsigned ); // LD D, RES 1, (IX + d) [undocumented] +void opcode_xycb_8b( unsigned ); // LD E, RES 1, (IX + d) [undocumented] +void opcode_xycb_8c( unsigned ); // LD H, RES 1, (IX + d) [undocumented] +void opcode_xycb_8d( unsigned ); // LD L, RES 1, (IX + d) [undocumented] +void opcode_xycb_8e( unsigned ); // RES 1, (IX + d) +void opcode_xycb_8f( unsigned ); // LD A, RES 1, (IX + d) [undocumented] +void opcode_xycb_90( unsigned ); // LD B, RES 2, (IX + d) [undocumented] +void opcode_xycb_91( unsigned ); // LD C, RES 2, (IX + d) [undocumented] +void opcode_xycb_92( unsigned ); // LD D, RES 2, (IX + d) [undocumented] +void opcode_xycb_93( unsigned ); // LD E, RES 2, (IX + d) [undocumented] +void opcode_xycb_94( unsigned ); // LD H, RES 2, (IX + d) [undocumented] +void opcode_xycb_95( unsigned ); // LD L, RES 2, (IX + d) [undocumented] +void opcode_xycb_96( unsigned ); // RES 2, (IX + d) +void opcode_xycb_97( unsigned ); // LD A, RES 2, (IX + d) [undocumented] +void opcode_xycb_98( unsigned ); // LD B, RES 3, (IX + d) [undocumented] +void opcode_xycb_99( unsigned ); // LD C, RES 3, (IX + d) [undocumented] +void opcode_xycb_9a( unsigned ); // LD D, RES 3, (IX + d) [undocumented] +void opcode_xycb_9b( unsigned ); // LD E, RES 3, (IX + d) [undocumented] +void opcode_xycb_9c( unsigned ); // LD H, RES 3, (IX + d) [undocumented] +void opcode_xycb_9d( unsigned ); // LD L, RES 3, (IX + d) [undocumented] +void opcode_xycb_9e( unsigned ); // RES 3, (IX + d) +void opcode_xycb_9f( unsigned ); // LD A, RES 3, (IX + d) [undocumented] +void opcode_xycb_a0( unsigned ); // LD B, RES 4, (IX + d) [undocumented] +void opcode_xycb_a1( unsigned ); // LD C, RES 4, (IX + d) [undocumented] +void opcode_xycb_a2( unsigned ); // LD D, RES 4, (IX + d) [undocumented] +void opcode_xycb_a3( unsigned ); // LD E, RES 4, (IX + d) [undocumented] +void opcode_xycb_a4( unsigned ); // LD H, RES 4, (IX + d) [undocumented] +void opcode_xycb_a5( unsigned ); // LD L, RES 4, (IX + d) [undocumented] +void opcode_xycb_a6( unsigned ); // RES 4, (IX + d) +void opcode_xycb_a7( unsigned ); // LD A, RES 4, (IX + d) [undocumented] +void opcode_xycb_a8( unsigned ); // LD B, RES 5, (IX + d) [undocumented] +void opcode_xycb_a9( unsigned ); // LD C, RES 5, (IX + d) [undocumented] +void opcode_xycb_aa( unsigned ); // LD D, RES 5, (IX + d) [undocumented] +void opcode_xycb_ab( unsigned ); // LD E, RES 5, (IX + d) [undocumented] +void opcode_xycb_ac( unsigned ); // LD H, RES 5, (IX + d) [undocumented] +void opcode_xycb_ad( unsigned ); // LD L, RES 5, (IX + d) [undocumented] +void opcode_xycb_ae( unsigned ); // RES 5, (IX + d) +void opcode_xycb_af( unsigned ); // LD A, RES 5, (IX + d) [undocumented] +void opcode_xycb_b0( unsigned ); // LD B, RES 6, (IX + d) [undocumented] +void opcode_xycb_b1( unsigned ); // LD C, RES 6, (IX + d) [undocumented] +void opcode_xycb_b2( unsigned ); // LD D, RES 6, (IX + d) [undocumented] +void opcode_xycb_b3( unsigned ); // LD E, RES 6, (IX + d) [undocumented] +void opcode_xycb_b4( unsigned ); // LD H, RES 6, (IX + d) [undocumented] +void opcode_xycb_b5( unsigned ); // LD L, RES 6, (IX + d) [undocumented] +void opcode_xycb_b6( unsigned ); // RES 6, (IX + d) +void opcode_xycb_b7( unsigned ); // LD A, RES 6, (IX + d) [undocumented] +void opcode_xycb_b8( unsigned ); // LD B, RES 7, (IX + d) [undocumented] +void opcode_xycb_b9( unsigned ); // LD C, RES 7, (IX + d) [undocumented] +void opcode_xycb_ba( unsigned ); // LD D, RES 7, (IX + d) [undocumented] +void opcode_xycb_bb( unsigned ); // LD E, RES 7, (IX + d) [undocumented] +void opcode_xycb_bc( unsigned ); // LD H, RES 7, (IX + d) [undocumented] +void opcode_xycb_bd( unsigned ); // LD L, RES 7, (IX + d) [undocumented] +void opcode_xycb_be( unsigned ); // RES 7, (IX + d) +void opcode_xycb_bf( unsigned ); // LD A, RES 7, (IX + d) [undocumented] +void opcode_xycb_c0( unsigned ); // LD B, SET 0, (IX + d) [undocumented] +void opcode_xycb_c1( unsigned ); // LD C, SET 0, (IX + d) [undocumented] +void opcode_xycb_c2( unsigned ); // LD D, SET 0, (IX + d) [undocumented] +void opcode_xycb_c3( unsigned ); // LD E, SET 0, (IX + d) [undocumented] +void opcode_xycb_c4( unsigned ); // LD H, SET 0, (IX + d) [undocumented] +void opcode_xycb_c5( unsigned ); // LD L, SET 0, (IX + d) [undocumented] +void opcode_xycb_c6( unsigned ); // SET 0, (IX + d) +void opcode_xycb_c7( unsigned ); // LD A, SET 0, (IX + d) [undocumented] +void opcode_xycb_c8( unsigned ); // LD B, SET 1, (IX + d) [undocumented] +void opcode_xycb_c9( unsigned ); // LD C, SET 1, (IX + d) [undocumented] +void opcode_xycb_ca( unsigned ); // LD D, SET 1, (IX + d) [undocumented] +void opcode_xycb_cb( unsigned ); // LD E, SET 1, (IX + d) [undocumented] +void opcode_xycb_cc( unsigned ); // LD H, SET 1, (IX + d) [undocumented] +void opcode_xycb_cd( unsigned ); // LD L, SET 1, (IX + d) [undocumented] +void opcode_xycb_ce( unsigned ); // SET 1, (IX + d) +void opcode_xycb_cf( unsigned ); // LD A, SET 1, (IX + d) [undocumented] +void opcode_xycb_d0( unsigned ); // LD B, SET 2, (IX + d) [undocumented] +void opcode_xycb_d1( unsigned ); // LD C, SET 2, (IX + d) [undocumented] +void opcode_xycb_d2( unsigned ); // LD D, SET 2, (IX + d) [undocumented] +void opcode_xycb_d3( unsigned ); // LD E, SET 2, (IX + d) [undocumented] +void opcode_xycb_d4( unsigned ); // LD H, SET 2, (IX + d) [undocumented] +void opcode_xycb_d5( unsigned ); // LD L, SET 2, (IX + d) [undocumented] +void opcode_xycb_d6( unsigned ); // SET 2, (IX + d) +void opcode_xycb_d7( unsigned ); // LD A, SET 2, (IX + d) [undocumented] +void opcode_xycb_d8( unsigned ); // LD B, SET 3, (IX + d) [undocumented] +void opcode_xycb_d9( unsigned ); // LD C, SET 3, (IX + d) [undocumented] +void opcode_xycb_da( unsigned ); // LD D, SET 3, (IX + d) [undocumented] +void opcode_xycb_db( unsigned ); // LD E, SET 3, (IX + d) [undocumented] +void opcode_xycb_dc( unsigned ); // LD H, SET 3, (IX + d) [undocumented] +void opcode_xycb_dd( unsigned ); // LD L, SET 3, (IX + d) [undocumented] +void opcode_xycb_de( unsigned ); // SET 3, (IX + d) +void opcode_xycb_df( unsigned ); // LD A, SET 3, (IX + d) [undocumented] +void opcode_xycb_e0( unsigned ); // LD B, SET 4, (IX + d) [undocumented] +void opcode_xycb_e1( unsigned ); // LD C, SET 4, (IX + d) [undocumented] +void opcode_xycb_e2( unsigned ); // LD D, SET 4, (IX + d) [undocumented] +void opcode_xycb_e3( unsigned ); // LD E, SET 4, (IX + d) [undocumented] +void opcode_xycb_e4( unsigned ); // LD H, SET 4, (IX + d) [undocumented] +void opcode_xycb_e5( unsigned ); // LD L, SET 4, (IX + d) [undocumented] +void opcode_xycb_e6( unsigned ); // SET 4, (IX + d) +void opcode_xycb_e7( unsigned ); // LD A, SET 4, (IX + d) [undocumented] +void opcode_xycb_e8( unsigned ); // LD B, SET 5, (IX + d) [undocumented] +void opcode_xycb_e9( unsigned ); // LD C, SET 5, (IX + d) [undocumented] +void opcode_xycb_ea( unsigned ); // LD D, SET 5, (IX + d) [undocumented] +void opcode_xycb_eb( unsigned ); // LD E, SET 5, (IX + d) [undocumented] +void opcode_xycb_ec( unsigned ); // LD H, SET 5, (IX + d) [undocumented] +void opcode_xycb_ed( unsigned ); // LD L, SET 5, (IX + d) [undocumented] +void opcode_xycb_ee( unsigned ); // SET 5, (IX + d) +void opcode_xycb_ef( unsigned ); // LD A, SET 5, (IX + d) [undocumented] +void opcode_xycb_f0( unsigned ); // LD B, SET 6, (IX + d) [undocumented] +void opcode_xycb_f1( unsigned ); // LD C, SET 6, (IX + d) [undocumented] +void opcode_xycb_f2( unsigned ); // LD D, SET 6, (IX + d) [undocumented] +void opcode_xycb_f3( unsigned ); // LD E, SET 6, (IX + d) [undocumented] +void opcode_xycb_f4( unsigned ); // LD H, SET 6, (IX + d) [undocumented] +void opcode_xycb_f5( unsigned ); // LD L, SET 6, (IX + d) [undocumented] +void opcode_xycb_f6( unsigned ); // SET 6, (IX + d) +void opcode_xycb_f7( unsigned ); // LD A, SET 6, (IX + d) [undocumented] +void opcode_xycb_f8( unsigned ); // LD B, SET 7, (IX + d) [undocumented] +void opcode_xycb_f9( unsigned ); // LD C, SET 7, (IX + d) [undocumented] +void opcode_xycb_fa( unsigned ); // LD D, SET 7, (IX + d) [undocumented] +void opcode_xycb_fb( unsigned ); // LD E, SET 7, (IX + d) [undocumented] +void opcode_xycb_fc( unsigned ); // LD H, SET 7, (IX + d) [undocumented] +void opcode_xycb_fd( unsigned ); // LD L, SET 7, (IX + d) [undocumented] +void opcode_xycb_fe( unsigned ); // SET 7, (IX + d) +void opcode_xycb_ff( unsigned ); // LD A, SET 7, (IX + d) [undocumented] + +// Trivia: there are 1018 opcode_xxx() functions in this class, +// for a total of 1274 emulated opcodes. Fortunately, most of them +// were automatically generated by custom made programs and scripts. + +#endif -- cgit v1.2.3