From 67919881a843f174368412a0cc9b2940b28e53c7 Mon Sep 17 00:00:00 2001 From: tomch Date: Fri, 9 Jan 2009 23:27:29 +0000 Subject: [PATCH] Merge from AppleWin-Tom (r396-423): - Replaced all non-GPL modules with GPL ones (6821, AY8910, Z80) . 6821 now from VICE (was MAME) . AY8910 now from FUSE (was MAME) . Z80 now from VICE (was Z80Em) - Fix for Willy Byte & MB support (strange 6522 behaviour!) --- AppleWin/Applewin.vcproj | 50 +- AppleWin/source/6821.cpp | 690 +- AppleWin/source/6821.h | 155 +- AppleWin/source/AY8910.cpp | 1637 +++-- AppleWin/source/AY8910.h | 78 +- AppleWin/source/Applewin.cpp | 61 +- AppleWin/source/CPU.cpp | 17 +- AppleWin/source/Common.h | 4 +- AppleWin/source/CommonVICE/6510core.h | 87 + AppleWin/source/CommonVICE/alarm.h | 191 + AppleWin/source/CommonVICE/interrupt.h | 314 + AppleWin/source/CommonVICE/mem.h | 95 + .../{Tfe/Types.h => CommonVICE/types.h} | 0 AppleWin/source/Frame.cpp | 2 +- AppleWin/source/Memory.cpp | 9 +- AppleWin/source/Memory.h | 2 +- AppleWin/source/Mockingboard.cpp | 81 +- AppleWin/source/Mockingboard.h | 2 + AppleWin/source/MouseInterface.cpp | 11 +- AppleWin/source/MouseInterface.h | 8 +- AppleWin/source/PropertySheetPage.cpp | 68 +- AppleWin/source/StdAfx.h | 1 - AppleWin/source/Tfe/Tfe.h | 2 +- AppleWin/source/Tfe/Tfearch.h | 2 +- AppleWin/source/Video.cpp | 2 +- AppleWin/source/Z80/README.txt | 35 - AppleWin/source/Z80/z80.cpp | 2691 ------- AppleWin/source/Z80/z80.h | 146 - AppleWin/source/Z80/z80codes.h | 219 - AppleWin/source/Z80/z80daa.h | 2063 ------ AppleWin/source/Z80/z80io.h | 70 - AppleWin/source/Z80VICE/daa.cpp | 547 ++ AppleWin/source/Z80VICE/daa.h | 36 + AppleWin/source/Z80VICE/z80.cpp | 6418 +++++++++++++++++ AppleWin/source/Z80VICE/z80.h | 47 + AppleWin/source/Z80VICE/z80mem.cpp | 452 ++ AppleWin/source/Z80VICE/z80mem.h | 64 + AppleWin/source/Z80VICE/z80regs.h | 80 + AppleWin/source/{Z80 => }/z80emu.cpp | 17 +- AppleWin/source/{Z80 => }/z80emu.h | 0 40 files changed, 9839 insertions(+), 6615 deletions(-) create mode 100644 AppleWin/source/CommonVICE/6510core.h create mode 100644 AppleWin/source/CommonVICE/alarm.h create mode 100644 AppleWin/source/CommonVICE/interrupt.h create mode 100644 AppleWin/source/CommonVICE/mem.h rename AppleWin/source/{Tfe/Types.h => CommonVICE/types.h} (100%) delete mode 100644 AppleWin/source/Z80/README.txt delete mode 100644 AppleWin/source/Z80/z80.cpp delete mode 100644 AppleWin/source/Z80/z80.h delete mode 100644 AppleWin/source/Z80/z80codes.h delete mode 100644 AppleWin/source/Z80/z80daa.h delete mode 100644 AppleWin/source/Z80/z80io.h create mode 100644 AppleWin/source/Z80VICE/daa.cpp create mode 100644 AppleWin/source/Z80VICE/daa.h create mode 100644 AppleWin/source/Z80VICE/z80.cpp create mode 100644 AppleWin/source/Z80VICE/z80.h create mode 100644 AppleWin/source/Z80VICE/z80mem.cpp create mode 100644 AppleWin/source/Z80VICE/z80mem.h create mode 100644 AppleWin/source/Z80VICE/z80regs.h rename AppleWin/source/{Z80 => }/z80emu.cpp (72%) rename AppleWin/source/{Z80 => }/z80emu.h (100%) diff --git a/AppleWin/Applewin.vcproj b/AppleWin/Applewin.vcproj index da362e1f..67b1a6b2 100644 --- a/AppleWin/Applewin.vcproj +++ b/AppleWin/Applewin.vcproj @@ -409,6 +409,14 @@ RelativePath=".\source\Video.h" > + + + + @@ -512,10 +520,6 @@ RelativePath=".\source\Tfe\Tfesupp.h" > - - @@ -526,38 +530,58 @@ + + + + + + + + + + diff --git a/AppleWin/source/6821.cpp b/AppleWin/source/6821.cpp index c0266ccf..cda120e1 100644 --- a/AppleWin/source/6821.cpp +++ b/AppleWin/source/6821.cpp @@ -1,531 +1,271 @@ -// Based on MAME's 6821pia.c -// - by Kyle Kim (Apple in PC) +/* + * mc6821.c - MC6821 emulation for the 1571 disk drives with DD3. + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ -// -// From mame.txt (http://www.mame.net/readme.html) -// -// VI. Reuse of Source Code -// -------------------------- -// This chapter might not apply to specific portions of MAME (e.g. CPU -// emulators) which bear different copyright notices. -// The source code cannot be used in a commercial product without the written -// authorization of the authors. Use in non-commercial products is allowed, and -// indeed encouraged. If you use portions of the MAME source code in your -// program, however, you must make the full source code freely available as -// well. -// Usage of the _information_ contained in the source code is free for any use. -// However, given the amount of time and energy it took to collect this -// information, if you find new information we would appreciate if you made it -// freely available as well. -// +/*#define MC_DEBUG*/ #include "stdafx.h" #include "6821.h" -// Ctrl-A(B) register bit mask define -/* - 0 1 - bit0 IRQ1_DISABLED IRQ1_ENABLED - bit1 C1_HIGH_TO_LOW C1_LOW_TO_HIGH - bit2 DDR_SELECTED OUTPUT_SELECTED - - bit3 RESET_C2 SET_C2 ( C2_OUTPUT & C2_SETMODE ) - bit3 STROBE_C1_RESET STROBE_E_RESET ( C2_OUTPUT & C2_STROBE_MODE ) - bit4 C2_STROBE_MODE C2_SETMODE ( C2_OUTPUT ) - - bit3 IRQ2_DISABLED IRQ2_ENABLED ( C2_INPUT ) - bit4 C2_HIGH_TO_LOW C2_HIGH_TO_LOW ( C2_INPUT ) - bit5 C2_INPUT C2_OUTPUT -*/ -#define PIA_IRQ1 0x80 -#define PIA_IRQ2 0x40 -#define SET_IRQ1(c) c |= PIA_IRQ1; -#define SET_IRQ2(c) c |= PIA_IRQ2; -#define CLEAR_IRQ1(c) c &= ~PIA_IRQ1; -#define CLEAR_IRQ2(c) c &= ~PIA_IRQ2; -#define IRQ1(c) ( c & PIA_IRQ1 ) -#define IRQ2(c) ( c & PIA_IRQ2 ) - -#define IRQ1_ENABLED(c) ( c & 0x01 ) -#define IRQ1_DISABLED(c) !( c & 0x01 ) -#define C1_LOW_TO_HIGH(c) ( c & 0x02 ) -#define C1_HIGH_TO_LOW(c) !( c & 0x02 ) -#define OUTPUT_SELECTED(c) ( c & 0x04 ) -#define DDR_SELECTED(c) !( c & 0x04 ) -#define IRQ2_ENABLED(c) ( c & 0x08 ) -#define IRQ2_DISABLED(c) !( c & 0x08 ) -#define STROBE_E_RESET(c) ( c & 0x08 ) -#define STROBE_C1_RESET(c) !( c & 0x08 ) -#define SET_C2(c) ( c & 0x08 ) -#define RESET_C2(c) !( c & 0x08 ) -#define C2_LOW_TO_HIGH(c) ( c & 0x10 ) -#define C2_HIGH_TO_LOW(c) !( c & 0x10 ) -#define C2_SET_MODE(c) ( c & 0x10 ) -#define C2_STROBE_MODE(c) !( c & 0x10 ) -#define C2_OUTPUT(c) ( c & 0x20 ) -#define C2_INPUT(c) !( c & 0x20 ) - #define PIA_W_CALLBACK(st, val) \ - if ( st.func ) st.func( this, st.objTo, 0, val ) + if ( st.func ) st.func( st.objTo, val ) -////////////////////////////////////////////////////////////////////// +/*-----------------------------------------------------------------------*/ +/* MC6821 register functions. */ -C6821::C6821() +void C6821::mc6821_write_pra(BYTE byte, unsigned int dnr) { - Reset(); - m_stOutA.objTo = NULL; - m_stOutA.func = NULL; - m_stOutB.objTo = NULL; - m_stOutB.func = NULL; - m_stOutCA2.objTo = NULL; - m_stOutCA2.func = NULL; - m_stOutCB2.objTo = NULL; - m_stOutCB2.func = NULL; - m_stOutIRQA.objTo = NULL; - m_stOutIRQA.func = NULL; - m_stOutIRQB.objTo = NULL; - m_stOutIRQB.func = NULL; + //if (mc6821[dnr].drive->parallel_cable == DRIVE_PC_DD3) + // parallel_cable_drive_write(byte, PARALLEL_WRITE, dnr); + + mc6821[dnr].pra = byte; + + if (mc6821[dnr].ddra) // AppleWin:TC + PIA_W_CALLBACK( m_stOutA, mc6821[dnr].pra & mc6821[dnr].ddra ); } -C6821::~C6821() +void C6821::mc6821_write_ddra(BYTE byte, unsigned int dnr) { + //parallel_cable_drive_write((BYTE)((~byte) | mc6821[dnr].pra), PARALLEL_WRITE, dnr); + if (mc6821[dnr].ddra == byte) // AppleWin:TC + return; + + mc6821[dnr].ddra = byte; + + if (mc6821[dnr].ddra) // AppleWin:TC + PIA_W_CALLBACK( m_stOutA, mc6821[dnr].pra & mc6821[dnr].ddra ); } -void C6821::SetListenerA(void *objTo, mem_write_handler func) +BYTE C6821::mc6821_read_pra(unsigned int dnr) { - m_stOutA.objTo = objTo; - m_stOutA.func = func; + BYTE byte = m_byIA; // AppleWin:TC + //BYTE byte = 0xff; + //int hs = 0; + + //if ((mc6821[dnr].cra & 0x28) == 0x28) + // hs = 1; + + //if (mc6821[dnr].drive->parallel_cable == DRIVE_PC_DD3) + // byte = parallel_cable_drive_read(hs); + + mc6821[dnr].cra = (BYTE)(mc6821[dnr].cra & 0x7f); + mc6821[dnr].cra = (BYTE)(mc6821[dnr].cra & 0xbf); // AppleWin:TC (Clear IRQ2) + + return (mc6821[dnr].pra & mc6821[dnr].ddra) + | (byte & ~(mc6821[dnr].ddra)); } -void C6821::SetListenerB(void *objTo, mem_write_handler func) +void C6821::mc6821_write_prb(BYTE byte, unsigned int dnr) { - m_stOutB.objTo = objTo; - m_stOutB.func = func; + mc6821[dnr].prb = byte; + + if (mc6821[dnr].ddrb) // AppleWin:TC + PIA_W_CALLBACK( m_stOutB, mc6821[dnr].prb & mc6821[dnr].ddrb ); } -void C6821::SetListenerCA2(void *objTo, mem_write_handler func) +void C6821::mc6821_write_ddrb(BYTE byte, unsigned int dnr) { - m_stOutCA2.objTo = objTo; - m_stOutCA2.func = func; + if (mc6821[dnr].ddrb == byte) // AppleWin:TC + return; + + mc6821[dnr].ddrb = byte; + + if (mc6821[dnr].ddrb) // AppleWin:TC + PIA_W_CALLBACK( m_stOutB, mc6821[dnr].prb & mc6821[dnr].ddrb ); } -void C6821::SetListenerCB2(void *objTo, mem_write_handler func) +BYTE C6821::mc6821_read_prb(unsigned int dnr) { - m_stOutCB2.objTo = objTo; - m_stOutCB2.func = func; + mc6821[dnr].crb = (BYTE)(mc6821[dnr].crb & 0x7f); // AppleWin:TC (Clear IRQ1) + mc6821[dnr].crb = (BYTE)(mc6821[dnr].crb & 0xbf); // AppleWin:TC (Clear IRQ2) + + BYTE byte = m_byIB; // AppleWin:TC + + return (mc6821[dnr].prb & mc6821[dnr].ddrb) + | (byte & ~(mc6821[dnr].ddrb)); } -BYTE C6821::Read(BYTE byRS) +void C6821::mc6821_write_cra(BYTE byte, unsigned int dnr) { - BYTE retval = 0; - byRS &= 3; - switch ( byRS ) - { - /******************* port A output/DDR read *******************/ - case PIA_DDRA: - // read output register - if ( OUTPUT_SELECTED(m_byCTLA) ) - { - // combine input and output values - retval = ( m_byOA & m_byDDRA ) | ( m_byIA & ~m_byDDRA ); - // IRQ flags implicitly cleared by a read - CLEAR_IRQ1( m_byCTLA ); - CLEAR_IRQ1( m_byCTLB ); - UpdateInterrupts(); - // CA2 is configured as output and in read strobe mode - if ( C2_OUTPUT(m_byCTLA) && C2_STROBE_MODE(m_byCTLA) ) - { - // this will cause a transition low; call the output function if we're currently high - if ( m_byOCA2 ) - PIA_W_CALLBACK( m_stOutCA2, 0 ); - m_byOCA2 = 0; - - // if the CA2 strobe is cleared by the E, reset it right away - if ( STROBE_E_RESET( m_byCTLA ) ) - { - PIA_W_CALLBACK( m_stOutCA2, 1 ); - m_byOCA2 = 1; - } - } - } - // read DDR register - else - { - retval = m_byDDRA; - } - break; - - /******************* port B output/DDR read *******************/ - case PIA_DDRB: - - // read output register - if ( OUTPUT_SELECTED( m_byCTLB ) ) - { - // combine input and output values - retval = ( m_byOB & m_byDDRB ) + ( m_byIB & ~m_byDDRB ); - - // IRQ flags implicitly cleared by a read - CLEAR_IRQ2( m_byCTLA ); - CLEAR_IRQ2( m_byCTLB ); - UpdateInterrupts(); - } - /* read DDR register */ - else - { - retval = m_byDDRB; - } - break; - - /******************* port A control read *******************/ - case PIA_CTLA: - // read control register - retval = m_byCTLA; - // when CA2 is an output, IRQA2 = 0, and is not affected by CA2 transitions. - if ( C2_OUTPUT( m_byCTLA ) ) - retval &= ~PIA_IRQ2; - break; - - /******************* port B control read *******************/ - case PIA_CTLB: - retval = m_byCTLB; - // when CB2 is an output, IRQB2 = 0, and is not affected by CB2 transitions. - if ( C2_OUTPUT( m_byCTLB ) ) - retval &= ~PIA_IRQ2; - break; - - } +// static BYTE old_cra = 0; +// +// if ((old_cra & 0x38) != (byte & 0x38)) { +//#ifdef MC_DEBUG +// log_debug("MODE %02x", byte & 0x38); +//#endif +// old_cra = byte; +// } - return retval; + mc6821[dnr].cra = byte; } -void C6821::Write(BYTE byRS, BYTE byData) +void C6821::mc6821_write_crb(BYTE byte, unsigned int dnr) { - byRS &= 3; - - switch( byRS ) - { - /******************* port A output/DDR write *******************/ - case PIA_DDRA: - - // write output register - if ( OUTPUT_SELECTED( m_byCTLA ) ) - { - // update the output value - m_byOA = byData; - - // send it to the output function - if ( m_byDDRA ) - PIA_W_CALLBACK( m_stOutA, m_byOA & m_byDDRA ); - } - - // write DDR register - else - { - if ( m_byDDRA != byData ) - { - m_byDDRA = byData; - - // send it to the output function - if ( m_byDDRA ) - PIA_W_CALLBACK( m_stOutA, m_byOA & m_byDDRA ); - } - } - break; - - /******************* port B output/DDR write *******************/ - case PIA_DDRB: - - // write output register - if ( OUTPUT_SELECTED( m_byCTLB ) ) - { - // update the output value - m_byOB = byData; - - // send it to the output function - if ( m_byDDRB ) - PIA_W_CALLBACK( m_stOutB, m_byOB & m_byDDRB ); - - // CB2 is configured as output and in write strobe mode - if ( C2_OUTPUT( m_byCTLB ) && C2_STROBE_MODE( m_byCTLB ) ) - { - // this will cause a transition low; call the output function if we're currently high - if ( m_byOCB2 ) - PIA_W_CALLBACK( m_stOutCB2, 0 ); - m_byOCB2 = 0; - - // if the CB2 strobe is cleared by the E, reset it right away - if ( STROBE_E_RESET( m_byCTLB ) ) - { - PIA_W_CALLBACK( m_stOutCB2, 1 ); - m_byOCB2 = 1; - } - } - } - // write DDR register - else - { - if ( m_byDDRB != byData ) - { - m_byDDRB = byData; - - // send it to the output function - if ( m_byDDRB ) - PIA_W_CALLBACK( m_stOutB, m_byOB & m_byDDRB ); - } - } - break; - - /******************* port A control write *******************/ - case PIA_CTLA: - // Bit 7 and 6 read only - byData &= 0x3f; - - // CA2 is configured as output and in set/reset mode - if ( C2_OUTPUT( byData ) ) - { - // determine the new value - int temp = SET_C2( byData ) ? 1 : 0; - - // if this creates a transition, call the CA2 output function - if ( m_byOCA2 ^ temp) - PIA_W_CALLBACK( m_stOutCA2, temp ); - - // set the new value - m_byOCA2 = temp; - } - - // update the control register - m_byCTLA = ( m_byCTLA & ~0x3F ) | byData; - - // update externals - UpdateInterrupts(); - break; - - /******************* port B control write *******************/ - case PIA_CTLB: - - /* Bit 7 and 6 read only - PD 16/01/00 */ - - byData &= 0x3f; - - // CB2 is configured as output and in set/reset mode - if ( C2_OUTPUT( byData ) ) - { - // determine the new value - int temp = SET_C2( byData ) ? 1 : 0; - - // if this creates a transition, call the CA2 output function - if ( m_byOCB2 ^ temp) - PIA_W_CALLBACK( m_stOutCB2, temp ); - - // set the new value - m_byOCB2 = temp; - } - - // update the control register - m_byCTLB = ( m_byCTLB & ~0x3F ) | byData; - - // update externals - UpdateInterrupts(); - break; - } - + mc6821[dnr].crb = byte; } -void C6821::Reset() -{ - m_byIA = 0; - m_byCA1 = 0; - m_byICA2 = 0; - m_byOA = 0; - m_byOCA2 = 0; - m_byDDRA = 0; - m_byCTLA = 0; - m_byIRQAState = 0; +/*-----------------------------------------------------------------------*/ +/* MC6821 signals. */ - m_byIB = 0; - m_byCB1 = 0; - m_byICB2 = 0; - m_byOB = 0; - m_byOCB2 = 0; - m_byDDRB = 0; - m_byCTLB = 0; - m_byIRQBState = 0; +void C6821::mc6821_set_signal(/*drive_context_t *drive_context,*/ int line) +{ + unsigned int dnr = 0; + +// dnr = drive_context->mynumber; + + switch (line) { + case MC6821_SIG_CA1: + mc6821[dnr].cra = (BYTE)(mc6821[dnr].cra | 0x80); + break; + case MC6821_SIG_CA2: + mc6821[dnr].cra = (BYTE)(mc6821[dnr].cra | 0x40); + break; + case MC6821_SIG_CB1: + mc6821[dnr].crb = (BYTE)(mc6821[dnr].crb | 0x80); + break; + case MC6821_SIG_CB2: + mc6821[dnr].crb = (BYTE)(mc6821[dnr].crb | 0x40); + break; + } } -void C6821::UpdateInterrupts() +/*-----------------------------------------------------------------------*/ +/* MC6821 register read/write access. */ + +void C6821::mc6821_store_internal(WORD addr, BYTE byte, unsigned int dnr) { - BYTE byNewState; +#ifdef MC_DEBUG + log_debug("MC WRITE ADDR: %i DATA:%02x CLK:%i", + addr, byte, drive_clk[dnr]); +#endif - // start with IRQ A - byNewState = 0; - if ( ( IRQ1( m_byCTLA ) && IRQ1_ENABLED( m_byCTLA ) ) || - ( IRQ2( m_byCTLA ) && IRQ2_ENABLED( m_byCTLA ) ) ) - byNewState = 1; - - if ( byNewState != m_byIRQAState ) - { - m_byIRQAState = byNewState; - PIA_W_CALLBACK( m_stOutIRQA, m_byIRQAState ); - } - - /* then do IRQ B */ - byNewState = 0; - if ( ( IRQ1( m_byCTLB ) && IRQ1_ENABLED( m_byCTLB ) ) || - ( IRQ2( m_byCTLB ) && IRQ2_ENABLED( m_byCTLB ) ) ) - byNewState = 1; - - if ( byNewState != m_byIRQBState ) - { - m_byIRQBState = byNewState; - PIA_W_CALLBACK( m_stOutIRQB, m_byIRQBState ); - } + switch (addr) { + case 0: // PIA_DDRA + if (mc6821[dnr].cra & 0x04) + mc6821_write_pra(byte, dnr); + else + mc6821_write_ddra(byte, dnr); + break; + case 1: // PIA_CTLA + mc6821_write_cra(byte, dnr); + break; + case 2: // PIA_DDRB + if (mc6821[dnr].crb & 0x04) + mc6821_write_prb(byte, dnr); + else + mc6821_write_ddrb(byte, dnr); + break; + case 3: // PIA_CTLB + mc6821_write_crb(byte, dnr); + break; + } } -void C6821::SetCA1(BYTE byData) +BYTE C6821::mc6821_read_internal(WORD addr, unsigned int dnr) { - byData = byData ? 1 : 0; + BYTE tmp = 0; - // the new state has caused a transition - if ( m_byCA1 ^ byData ) - { - // handle the active transition - if ( ( byData && C1_LOW_TO_HIGH( m_byCTLA ) ) || - ( !byData && C1_HIGH_TO_LOW( m_byCTLA ) ) ) - { - // mark the IRQ - SET_IRQ1(m_byCTLA); + switch (addr) { + case 0: // PIA_DDRA + if (mc6821[dnr].cra & 0x04) + tmp = mc6821_read_pra(dnr); + else + tmp = mc6821[dnr].ddra; + break; + case 1: // PIA_CTLA + tmp = mc6821[dnr].cra; + break; + case 2: // PIA_DDRB + if (mc6821[dnr].crb & 0x04) + tmp = mc6821_read_prb(dnr); + else + tmp = mc6821[dnr].ddrb; + break; + case 3: // PIA_CTLB + tmp = mc6821[dnr].crb; + break; + } - // update externals - UpdateInterrupts(); +#ifdef MC_DEBUG + log_debug("MC READ ADDR: %i DATA:%02x CLK:%i", + addr, tmp, drive_clk[dnr]); +#endif - // CA2 is configured as output and in read strobe mode and cleared by a CA1 transition - if ( C2_OUTPUT( m_byCTLA ) && C2_STROBE_MODE( m_byCTLA ) && STROBE_C1_RESET( m_byCTLA ) ) - { - // call the CA2 output function - if ( !m_byOCA2 ) - PIA_W_CALLBACK( m_stOutCA2, 1 ); - - // clear CA2 - m_byOCA2 = 1; - } - } - } - - // set the new value for CA1 - m_byCA1 = byData; + return tmp; } -void C6821::SetCA2(BYTE byData) +void C6821::mc6821_reset_internal(unsigned int dnr) { - byData = byData ? 1 : 0; - - // CA2 is in input mode - if ( C2_INPUT( m_byCTLA ) ) - { - // the new state has caused a transition - if ( m_byICA2 ^ byData ) - { - // handle the active transition - if ( ( byData && C2_LOW_TO_HIGH( m_byCTLA ) ) || - ( !byData && C2_HIGH_TO_LOW( m_byCTLA ) ) ) - { - // mark the IRQ - SET_IRQ2( m_byCTLA ); - - // update externals - UpdateInterrupts(); - } - } - } - - // set the new value for CA2 - m_byICA2 = byData; + mc6821[dnr].pra = 0; + mc6821[dnr].ddra = 0; + mc6821[dnr].cra = 0; + mc6821[dnr].prb = 0; + mc6821[dnr].ddrb = 0; + mc6821[dnr].crb = 0; } -void C6821::SetCB1(BYTE byData) +/*-----------------------------------------------------------------------*/ + +//static void REGPARM3 mc6821_store(drive_context_t *drv, WORD addr, BYTE byte) +//{ +// mc6821_store_internal((WORD)(addr & 3), byte, drv->mynumber); +//} +// +//static BYTE REGPARM2 mc6821_read(drive_context_t *drv, WORD addr) +//{ +// return mc6821_read_internal((WORD)(addr & 3), drv->mynumber); +//} + +/*-----------------------------------------------------------------------*/ + +/* MC6821 external interface. */ + +/* Functions using drive context. */ +void C6821::mc6821_init(/*drive_context_t *drv*/) { - byData = byData ? 1 : 0; - - // the new state has caused a transition - if ( m_byCB1 ^ byData ) - { - // handle the active transition - if ( ( byData && C1_LOW_TO_HIGH( m_byCTLB ) ) || - ( !byData && C1_HIGH_TO_LOW( m_byCTLB ) ) ) - { - // mark the IRQ - SET_IRQ1( m_byCTLB ); - - // update externals - UpdateInterrupts(); - - // CB2 is configured as output and in read strobe mode and cleared by a CA1 transition - if ( C2_OUTPUT( m_byCTLB ) && C2_STROBE_MODE( m_byCTLB ) && STROBE_C1_RESET( m_byCTLB ) ) - { - // the IRQ1 flag must have also been cleared - if ( !IRQ1( m_byCTLB ) ) - { - // call the CB2 output function - if ( !m_byOCB2 ) - PIA_W_CALLBACK( m_stOutCB2, 1 ); - - // clear CB2 - m_byOCB2 = 1; - } - } - } - } - - // set the new value for CA1 - m_byCB1 = byData; - + //mc6821[drv->mynumber].drive = drv->drive; } -void C6821::SetCB2(BYTE byData) +void C6821::mc6821_reset(/*drive_context_t *drv*/) { - byData = byData ? 1 : 0; - - // CA2 is in input mode - if ( C2_INPUT( m_byCTLB ) ) - { - // the new state has caused a transition - if ( m_byICB2 ^ byData ) - { - // handle the active transition - if ( ( byData && C2_LOW_TO_HIGH( m_byCTLB ) ) || - ( !byData && C2_HIGH_TO_LOW( m_byCTLB ) ) ) - { - // mark the IRQ - SET_IRQ2( m_byCTLB ); - - // update externals - UpdateInterrupts(); - } - } - } - - // set the new value for CA2 - m_byICB2 = byData; + mc6821_reset_internal(); } -void C6821::SetPA(BYTE byData) -{ - m_byIA = byData; -} - -void C6821::SetPB(BYTE byData) -{ - m_byIB = byData; -} - -BYTE C6821::GetPA() -{ - return m_byOA & m_byDDRA; -} - -BYTE C6821::GetPB() -{ - return m_byOB & m_byDDRB; -} +//void mc6821_mem_init(struct drive_context_s *drv, unsigned int type) +//{ +// drivecpud_context_t *cpud; +// +// cpud = drv->cpud; +// +// /* Setup parallel cable */ +// if (type == DRIVE_TYPE_1541 || type == DRIVE_TYPE_1541II +// || type == DRIVE_TYPE_1570 || type == DRIVE_TYPE_1571 +// || type == DRIVE_TYPE_1571CR) { +// if (drv->drive->parallel_cable == DRIVE_PC_DD3) { +// drivemem_set_func(cpud, 0x50, 0x60, mc6821_read, mc6821_store); +// } +// } +//} diff --git a/AppleWin/source/6821.h b/AppleWin/source/6821.h index 75187dd2..fb92378a 100644 --- a/AppleWin/source/6821.h +++ b/AppleWin/source/6821.h @@ -1,68 +1,125 @@ -// Motorola MC6821 PIA +/* + * mc6821.h - MC6821 emulation for the 1571 disk drives with DD3. + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ -typedef void (*mem_write_handler) (void* objFrom, void* objTo, int nAddr, BYTE byData); +typedef void (*mem_write_handler) (void* objTo, BYTE byData); -typedef struct _STWriteHandler +typedef struct { void* objTo; mem_write_handler func; } STWriteHandler; -// - -#define PIA_DDRA 0 -#define PIA_CTLA 1 -#define PIA_DDRB 2 -#define PIA_CTLB 3 - class C6821 { public: - C6821(); - virtual ~C6821(); + C6821() + { + mc6821_reset(); + m_stOutA.objTo = NULL; + m_stOutA.func = NULL; + m_stOutB.objTo = NULL; + m_stOutB.func = NULL; + }; - BYTE GetPB(); - BYTE GetPA(); - void SetPB(BYTE byData); - void SetPA(BYTE byData); - void SetCA1( BYTE byData ); - void SetCA2( BYTE byData ); - void SetCB1( BYTE byData ); - void SetCB2( BYTE byData ); - void Reset(); - BYTE Read( BYTE byRS ); - void Write( BYTE byRS, BYTE byData ); + ~C6821() {}; - void UpdateInterrupts(); + // AppleWin:TC + void SetPA(BYTE byData) { m_byIA = byData; } + void SetPB(BYTE byData) { m_byIB = byData; } + void Reset() { mc6821_reset(); } + BYTE Read( BYTE byRS ) { return mc6821_read_internal(byRS); } + void Write( BYTE byRS, BYTE byData ) { mc6821_store_internal(byRS, byData); } - void SetListenerA( void *objTo, mem_write_handler func ); - void SetListenerB( void *objTo, mem_write_handler func ); - void SetListenerCA2( void *objTo, mem_write_handler func ); - void SetListenerCB2( void *objTo, mem_write_handler func ); + void SetListenerA(void *objTo, mem_write_handler func) + { + m_stOutA.objTo = objTo; + m_stOutA.func = func; + } -protected: - BYTE m_byIA; - BYTE m_byCA1; - BYTE m_byICA2; - BYTE m_byOA; - BYTE m_byOCA2; - BYTE m_byDDRA; - BYTE m_byCTLA; - BYTE m_byIRQAState; + void SetListenerB(void *objTo, mem_write_handler func) + { + m_stOutB.objTo = objTo; + m_stOutB.func = func; + } + // AppleWin:TC END - BYTE m_byIB; - BYTE m_byCB1; - BYTE m_byICB2; - BYTE m_byOB; - BYTE m_byOCB2; - BYTE m_byDDRB; - BYTE m_byCTLB; - BYTE m_byIRQBState; +private: + /* Signal values (for signaling edges on the control lines) */ + #define MC6821_SIG_CA1 0 + #define MC6821_SIG_CA2 1 + #define MC6821_SIG_CB1 2 + #define MC6821_SIG_CB2 3 + //struct drive_s; + + struct mc6821_s { + /* MC6821 register. */ + BYTE pra; + BYTE ddra; + BYTE cra; + BYTE prb; + BYTE ddrb; + BYTE crb; + + /* Drive structure */ + // struct drive_s *drive; + }; + typedef struct mc6821_s mc6821_t; + + //struct drive_context_s; + void mc6821_init(/*struct drive_context_s *drv*/); + void mc6821_reset(/*struct drive_context_s *drv*/); + //extern void mc6821_mem_init(struct drive_context_s *drv, unsigned int type); + + void mc6821_set_signal(/*struct drive_context_s *drive_context,*/ int line); + +private: + // AppleWin:TC + void mc6821_write_pra(BYTE byte, unsigned int dnr=0); + void mc6821_write_ddra(BYTE byte, unsigned int dnr=0); + BYTE mc6821_read_pra(unsigned int dnr=0); + void mc6821_write_prb(BYTE byte, unsigned int dnr=0); + void mc6821_write_ddrb(BYTE byte, unsigned int dnr=0); + BYTE mc6821_read_prb(unsigned int dnr=0); + void mc6821_write_cra(BYTE byte, unsigned int dnr=0); + void mc6821_write_crb(BYTE byte, unsigned int dnr=0); + void mc6821_store_internal(WORD addr, BYTE byte, unsigned int dnr=0); + BYTE mc6821_read_internal(WORD addr, unsigned int dnr=0); + void mc6821_reset_internal(unsigned int dnr=0); + // AppleWin:TC END + +private: + // AppleWin:TC STWriteHandler m_stOutA; STWriteHandler m_stOutB; - STWriteHandler m_stOutCA2; - STWriteHandler m_stOutCB2; - STWriteHandler m_stOutIRQA; - STWriteHandler m_stOutIRQB; + BYTE m_byIA; // InputA from 285 + BYTE m_byIB; // InputB from 285 + // AppleWin:TC END + + /* mc6821 structure. */ + #define DRIVE_NUM 1 // AppleWin:TC + mc6821_t mc6821[DRIVE_NUM]; }; diff --git a/AppleWin/source/AY8910.cpp b/AppleWin/source/AY8910.cpp index a6e5b0aa..363cd595 100644 --- a/AppleWin/source/AY8910.cpp +++ b/AppleWin/source/AY8910.cpp @@ -1,790 +1,1005 @@ -/*************************************************************************** +/* sound.c: Sound support + Copyright (c) 2000-2007 Russell Marks, Matan Ziv-Av, Philip Kendall, + Fredrick Meunier - ay8910.c + $Id$ + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - Emulation of the AY-3-8910 / YM2149 sound chip. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - Based on various code snippets by Ville Hallik, Michael Cuddy, - Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ + Author contact information: -// -// From mame.txt (http://www.mame.net/readme.html) -// -// VI. Reuse of Source Code -// -------------------------- -// This chapter might not apply to specific portions of MAME (e.g. CPU -// emulators) which bear different copyright notices. -// The source code cannot be used in a commercial product without the written -// authorization of the authors. Use in non-commercial products is allowed, and -// indeed encouraged. If you use portions of the MAME source code in your -// program, however, you must make the full source code freely available as -// well. -// Usage of the _information_ contained in the source code is free for any use. -// However, given the amount of time and energy it took to collect this -// information, if you find new information we would appreciate if you made it -// freely available as well. -// + E-mail: philip-fuse@shadowmagic.org.uk +*/ + +// [AppleWin-TC] From FUSE's sound.c module #include #include #include -#include "ay8910.h" +#include "AY8910.h" #include "Common.h" #include "Structs.h" #include "Applewin.h" // For g_fh #include "Mockingboard.h" // For g_uTimer1IrqCount -/////////////////////////////////////////////////////////// -// typedefs & dummy funcs to allow MAME code to compile: +/* The AY white noise RNG algorithm is based on info from MAME's ay8910.c - + * MAME's licence explicitly permits free use of info (even encourages it). + */ -typedef UINT8 (*mem_read_handler)(UINT32); -typedef void (*mem_write_handler)(UINT32, UINT8); +/* NB: I know some of this stuff looks fairly CPU-hogging. + * For example, the AY code tracks changes with sub-frame timing + * in a rather hairy way, and there's subsampling here and there. + * But if you measure the CPU use, it doesn't actually seem + * very high at all. And I speak as a Cyrix owner. :-) + */ -static void logerror(char* psz, ...) +libspectrum_signed_word** g_ppSoundBuffers; // Used to pass param to sound_ay_overlay() + +/* configuration */ +//int sound_enabled = 0; /* Are we currently using the sound card */ +//int sound_enabled_ever = 0; /* if it's *ever* been in use; see +// sound_ay_write() and sound_ay_reset() */ +//int sound_stereo = 0; /* true for stereo *output sample* (only) */ +//int sound_stereo_ay_abc = 0; /* (AY stereo) true for ABC stereo, else ACB */ +//int sound_stereo_ay_narrow = 0; /* (AY stereo) true for narrow AY st. sep. */ + +//int sound_stereo_ay = 0; /* local copy of settings_current.stereo_ay */ +//int sound_stereo_beeper = 0; /* and settings_current.stereo_beeper */ + + +/* assume all three tone channels together match the beeper volume (ish). + * Must be <=127 for all channels; 50+2+(24*3) = 124. + * (Now scaled up for 16-bit.) + */ +//#define AMPL_BEEPER ( 50 * 256) +//#define AMPL_TAPE ( 2 * 256 ) +//#define AMPL_AY_TONE ( 24 * 256 ) /* three of these */ +#define AMPL_AY_TONE ( 42 * 256 ) // 42*3 = 126 + +/* max. number of sub-frame AY port writes allowed; + * given the number of port writes theoretically possible in a + * 50th I think this should be plenty. + */ +//#define AY_CHANGE_MAX 8000 // [TC] Moved into AY8910.h + +///* frequency to generate sound at for hifi sound */ +//#define HIFI_FREQ 88200 + +#ifdef HAVE_SAMPLERATE +static SRC_STATE *src_state; +#endif /* #ifdef HAVE_SAMPLERATE */ + +int sound_generator_framesiz; +int sound_framesiz; + +static int sound_generator_freq; + +static int sound_channels; + +static unsigned int ay_tone_levels[16]; + +//static libspectrum_signed_word *sound_buf, *tape_buf; +//static float *convert_input_buffer, *convert_output_buffer; + +#if 0 +/* beeper stuff */ +static int sound_oldpos[2], sound_fillpos[2]; +static int sound_oldval[2], sound_oldval_orig[2]; +#endif + +#if 0 +#define STEREO_BUF_SIZE 4096 + +static int pstereobuf[ STEREO_BUF_SIZE ]; +static int pstereobufsiz, pstereopos; +static int psgap = 250; +static int rstereobuf_l[ STEREO_BUF_SIZE ], rstereobuf_r[ STEREO_BUF_SIZE ]; +static int rstereopos, rchan1pos, rchan2pos, rchan3pos; +#endif + + +// Statics: +double CAY8910::m_fCurrentCLK_AY8910 = 0.0; + + +CAY8910::CAY8910() : + // Init the statics that were in sound_ay_overlay() + rng(1), + noise_toggle(0), + env_first(1), env_rev(0), env_counter(15) { -} - -static unsigned short activecpu_get_pc() -{ - return 0; -} - -// -/////////////////////////////////////////////////////////// - -#define MAX_OUTPUT 0x7fff - -// See AY8910_set_clock() for definition of STEP -#define STEP 0x8000 - - -static int num = 0, ym_num = 0; - -struct AY8910 -{ - int Channel; - int SampleRate; - mem_read_handler PortAread; - mem_read_handler PortBread; - mem_write_handler PortAwrite; - mem_write_handler PortBwrite; - int register_latch; - unsigned char Regs[16]; - int lastEnable; - unsigned int UpdateStep; - int PeriodA,PeriodB,PeriodC,PeriodN,PeriodE; - int CountA,CountB,CountC,CountN,CountE; - unsigned int VolA,VolB,VolC,VolE; - unsigned char EnvelopeA,EnvelopeB,EnvelopeC; - unsigned char OutputA,OutputB,OutputC,OutputN; - signed char CountEnv; - unsigned char Hold,Alternate,Attack,Holding; - int RNG; - unsigned int VolTable[32]; + m_fCurrentCLK_AY8910 = g_fCurrentCLK6502; }; -/* register id's */ -#define AY_AFINE (0) -#define AY_ACOARSE (1) -#define AY_BFINE (2) -#define AY_BCOARSE (3) -#define AY_CFINE (4) -#define AY_CCOARSE (5) -#define AY_NOISEPER (6) -#define AY_ENABLE (7) -#define AY_AVOL (8) -#define AY_BVOL (9) -#define AY_CVOL (10) -#define AY_EFINE (11) -#define AY_ECOARSE (12) -#define AY_ESHAPE (13) -#define AY_PORTA (14) -#define AY_PORTB (15) - - -static struct AY8910 AYPSG[MAX_8910]; /* array of PSG's */ - -static bool g_bAYReset = false; // Doing AY8910_reset() - -//----------------------------------------------------------------------------- - -//#define LOG_AY8910 -#ifdef LOG_AY8910 -static void LogAY8910(int n, int r, UINT uFreq) +void CAY8910::sound_ay_init( void ) { - // TO DO: Determine freq from 6522 timer + /* AY output doesn't match the claimed levels; these levels are based + * on the measurements posted to comp.sys.sinclair in Dec 2001 by + * Matthew Westcott, adjusted as I described in a followup to his post, + * then scaled to 0..0xffff. + */ + static const int levels[16] = { + 0x0000, 0x0385, 0x053D, 0x0770, + 0x0AD7, 0x0FD5, 0x15B0, 0x230C, + 0x2B4C, 0x43C1, 0x5A4B, 0x732F, + 0x9204, 0xAFF1, 0xD921, 0xFFFF + }; + int f; - if ((g_fh == NULL) || g_bAYReset) - return; + /* scale the values down to fit */ + for( f = 0; f < 16; f++ ) + ay_tone_levels[f] = ( levels[f] * AMPL_AY_TONE + 0x8000 ) / 0xffff; - static UINT nCnt = 0; - const UINT nNumAYs = 4; // 1..4 - if((r == 0)) - { - if(nCnt == 0) - { - fprintf(g_fh, "Time : "); - for(UINT i=0; iRegs[r] = v; - -#ifdef LOG_AY8910 - LogAY8910(n, r, 60); -#endif - - /* A note about the period of tones, noise and envelope: for speed reasons,*/ - /* we count down from the period to 0, but careful studies of the chip */ - /* output prove that it instead counts up from 0 until the counter becomes */ - /* greater or equal to the period. This is an important difference when the*/ - /* program is rapidly changing the period to modulate the sound. */ - /* To compensate for the difference, when the period is changed we adjust */ - /* our internal counter. */ - /* Also, note that period = 0 is the same as period = 1. This is mentioned */ - /* in the YM2203 data sheets. However, this does NOT apply to the Envelope */ - /* period. In that case, period = 0 is half as period = 1. */ - switch( r ) - { - case AY_AFINE: - case AY_ACOARSE: - PSG->Regs[AY_ACOARSE] &= 0x0f; - old = PSG->PeriodA; - PSG->PeriodA = (PSG->Regs[AY_AFINE] + 256 * PSG->Regs[AY_ACOARSE]) * PSG->UpdateStep; - if (PSG->PeriodA == 0) PSG->PeriodA = PSG->UpdateStep; - PSG->CountA += PSG->PeriodA - old; - if (PSG->CountA <= 0) PSG->CountA = 1; - break; - case AY_BFINE: - case AY_BCOARSE: - PSG->Regs[AY_BCOARSE] &= 0x0f; - old = PSG->PeriodB; - PSG->PeriodB = (PSG->Regs[AY_BFINE] + 256 * PSG->Regs[AY_BCOARSE]) * PSG->UpdateStep; - if (PSG->PeriodB == 0) PSG->PeriodB = PSG->UpdateStep; - PSG->CountB += PSG->PeriodB - old; - if (PSG->CountB <= 0) PSG->CountB = 1; - break; - case AY_CFINE: - case AY_CCOARSE: - PSG->Regs[AY_CCOARSE] &= 0x0f; - old = PSG->PeriodC; - PSG->PeriodC = (PSG->Regs[AY_CFINE] + 256 * PSG->Regs[AY_CCOARSE]) * PSG->UpdateStep; - if (PSG->PeriodC == 0) PSG->PeriodC = PSG->UpdateStep; - PSG->CountC += PSG->PeriodC - old; - if (PSG->CountC <= 0) PSG->CountC = 1; - break; - case AY_NOISEPER: - PSG->Regs[AY_NOISEPER] &= 0x1f; - old = PSG->PeriodN; - PSG->PeriodN = PSG->Regs[AY_NOISEPER] * PSG->UpdateStep; - if (PSG->PeriodN == 0) PSG->PeriodN = PSG->UpdateStep; - PSG->CountN += PSG->PeriodN - old; - if (PSG->CountN <= 0) PSG->CountN = 1; - break; - case AY_ENABLE: - if ((PSG->lastEnable == -1) || - ((PSG->lastEnable & 0x40) != (PSG->Regs[AY_ENABLE] & 0x40))) - { - /* write out 0xff if port set to input */ - if (PSG->PortAwrite) - (*PSG->PortAwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x40) ? PSG->Regs[AY_PORTA] : 0xff)); // [TC: UINT8 cast] - } - - if ((PSG->lastEnable == -1) || - ((PSG->lastEnable & 0x80) != (PSG->Regs[AY_ENABLE] & 0x80))) - { - /* write out 0xff if port set to input */ - if (PSG->PortBwrite) - (*PSG->PortBwrite)(0, (UINT8) ((PSG->Regs[AY_ENABLE] & 0x80) ? PSG->Regs[AY_PORTB] : 0xff)); // [TC: UINT8 cast] - } - - PSG->lastEnable = PSG->Regs[AY_ENABLE]; - break; - case AY_AVOL: - PSG->Regs[AY_AVOL] &= 0x1f; - PSG->EnvelopeA = PSG->Regs[AY_AVOL] & 0x10; - PSG->VolA = PSG->EnvelopeA ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_AVOL] ? PSG->Regs[AY_AVOL]*2+1 : 0]; - break; - case AY_BVOL: - PSG->Regs[AY_BVOL] &= 0x1f; - PSG->EnvelopeB = PSG->Regs[AY_BVOL] & 0x10; - PSG->VolB = PSG->EnvelopeB ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_BVOL] ? PSG->Regs[AY_BVOL]*2+1 : 0]; - break; - case AY_CVOL: - PSG->Regs[AY_CVOL] &= 0x1f; - PSG->EnvelopeC = PSG->Regs[AY_CVOL] & 0x10; - PSG->VolC = PSG->EnvelopeC ? PSG->VolE : PSG->VolTable[PSG->Regs[AY_CVOL] ? PSG->Regs[AY_CVOL]*2+1 : 0]; - break; - case AY_EFINE: - case AY_ECOARSE: -// _ASSERT((PSG->Regs[AY_EFINE] == 0) && (PSG->Regs[AY_ECOARSE] == 0)); - old = PSG->PeriodE; - PSG->PeriodE = ((PSG->Regs[AY_EFINE] + 256 * PSG->Regs[AY_ECOARSE])) * PSG->UpdateStep; - if (PSG->PeriodE == 0) PSG->PeriodE = PSG->UpdateStep / 2; - PSG->CountE += PSG->PeriodE - old; - if (PSG->CountE <= 0) PSG->CountE = 1; - break; - case AY_ESHAPE: -// _ASSERT(PSG->Regs[AY_ESHAPE] == 0); - /* envelope shapes: - C AtAlH - 0 0 x x \___ - - 0 1 x x /___ - - 1 0 0 0 \\\\ - - 1 0 0 1 \___ - - 1 0 1 0 \/\/ - ___ - 1 0 1 1 \ - - 1 1 0 0 //// - ___ - 1 1 0 1 / - - 1 1 1 0 /\/\ - - 1 1 1 1 /___ - - The envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it - has twice the steps, happening twice as fast. Since the end result is - just a smoother curve, we always use the YM2149 behaviour. - */ - PSG->Regs[AY_ESHAPE] &= 0x0f; - PSG->Attack = (PSG->Regs[AY_ESHAPE] & 0x04) ? 0x1f : 0x00; - if ((PSG->Regs[AY_ESHAPE] & 0x08) == 0) - { - /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */ - PSG->Hold = 1; - PSG->Alternate = PSG->Attack; - } - else - { - PSG->Hold = PSG->Regs[AY_ESHAPE] & 0x01; - PSG->Alternate = PSG->Regs[AY_ESHAPE] & 0x02; - } - PSG->CountE = PSG->PeriodE; - PSG->CountEnv = 0x1f; - PSG->Holding = 0; - PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack]; - if (PSG->EnvelopeA) PSG->VolA = PSG->VolE; - if (PSG->EnvelopeB) PSG->VolB = PSG->VolE; - if (PSG->EnvelopeC) PSG->VolC = PSG->VolE; - break; - case AY_PORTA: - if (PSG->Regs[AY_ENABLE] & 0x40) - { - if (PSG->PortAwrite) - (*PSG->PortAwrite)(0, PSG->Regs[AY_PORTA]); - else - logerror("PC %04x: warning - write %02x to 8910 #%d Port A\n",activecpu_get_pc(),PSG->Regs[AY_PORTA],n); - } - else - { - logerror("warning: write to 8910 #%d Port A set as input - ignored\n",n); - } - break; - case AY_PORTB: - if (PSG->Regs[AY_ENABLE] & 0x80) - { - if (PSG->PortBwrite) - (*PSG->PortBwrite)(0, PSG->Regs[AY_PORTB]); - else - logerror("PC %04x: warning - write %02x to 8910 #%d Port B\n",activecpu_get_pc(),PSG->Regs[AY_PORTB],n); - } - else - { - logerror("warning: write to 8910 #%d Port B set as input - ignored\n",n); - } - break; - } + ay_change_count = 0; } -// /length/ is the number of samples we require -// NB. This should be called at twice the 6522 IRQ rate or (eg) 60Hz if no IRQ. -void AY8910Update(int chip,INT16 **buffer,int length) // [TC: Removed static] +void CAY8910::sound_init( const char *device ) { - struct AY8910 *PSG = &AYPSG[chip]; - INT16 *buf1,*buf2,*buf3; - int outn; +// static int first_init = 1; +// int f, ret; + float hz; +#ifdef HAVE_SAMPLERATE + int error; +#endif /* #ifdef HAVE_SAMPLERATE */ - buf1 = buffer[0]; - buf2 = buffer[1]; - buf3 = buffer[2]; - - - /* The 8910 has three outputs, each output is the mix of one of the three */ - /* tone generators and of the (single) noise generator. The two are mixed */ - /* BEFORE going into the DAC. The formula to mix each channel is: */ - /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */ - /* Note that this means that if both tone and noise are disabled, the output */ - /* is 1, not 0, and can be modulated changing the volume. */ - - - /* If the channels are disabled, set their output to 1, and increase the */ - /* counter, if necessary, so they will not be inverted during this update. */ - /* Setting the output to 1 is necessary because a disabled channel is locked */ - /* into the ON state (see above); and it has no effect if the volume is 0. */ - /* If the volume is 0, increase the counter, but don't touch the output. */ - if (PSG->Regs[AY_ENABLE] & 0x01) - { - if (PSG->CountA <= length*STEP) PSG->CountA += length*STEP; - PSG->OutputA = 1; - } - else if (PSG->Regs[AY_AVOL] == 0) - { - /* note that I do count += length, NOT count = length + 1. You might think */ - /* it's the same since the volume is 0, but doing the latter could cause */ - /* interferencies when the program is rapidly modulating the volume. */ - if (PSG->CountA <= length*STEP) PSG->CountA += length*STEP; - } - if (PSG->Regs[AY_ENABLE] & 0x02) - { - if (PSG->CountB <= length*STEP) PSG->CountB += length*STEP; - PSG->OutputB = 1; - } - else if (PSG->Regs[AY_BVOL] == 0) - { - if (PSG->CountB <= length*STEP) PSG->CountB += length*STEP; - } - if (PSG->Regs[AY_ENABLE] & 0x04) - { - if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP; - PSG->OutputC = 1; - } - else if (PSG->Regs[AY_CVOL] == 0) - { - if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP; - } - - /* for the noise channel we must not touch OutputN - it's also not necessary */ - /* since we use outn. */ - if ((PSG->Regs[AY_ENABLE] & 0x38) == 0x38) /* all off */ - if (PSG->CountN <= length*STEP) PSG->CountN += length*STEP; - - outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]); - - - /* buffering loop */ - while (length) - { - int vola,volb,volc; - int left; - - - /* vola, volb and volc keep track of how long each square wave stays */ - /* in the 1 position during the sample period. */ - vola = volb = volc = 0; - - left = STEP; - do - { - int nextevent; - - - if (PSG->CountN < left) nextevent = PSG->CountN; - else nextevent = left; - - if (outn & 0x08) - { - if (PSG->OutputA) vola += PSG->CountA; - PSG->CountA -= nextevent; - /* PeriodA is the half period of the square wave. Here, in each */ - /* loop I add PeriodA twice, so that at the end of the loop the */ - /* square wave is in the same status (0 or 1) it was at the start. */ - /* vola is also incremented by PeriodA, since the wave has been 1 */ - /* exactly half of the time, regardless of the initial position. */ - /* If we exit the loop in the middle, OutputA has to be inverted */ - /* and vola incremented only if the exit status of the square */ - /* wave is 1. */ - while (PSG->CountA <= 0) - { - PSG->CountA += PSG->PeriodA; - if (PSG->CountA > 0) - { - PSG->OutputA ^= 1; - if (PSG->OutputA) vola += PSG->PeriodA; - break; - } - PSG->CountA += PSG->PeriodA; - vola += PSG->PeriodA; - } - if (PSG->OutputA) vola -= PSG->CountA; - } - else - { - PSG->CountA -= nextevent; - while (PSG->CountA <= 0) - { - PSG->CountA += PSG->PeriodA; - if (PSG->CountA > 0) - { - PSG->OutputA ^= 1; - break; - } - PSG->CountA += PSG->PeriodA; - } - } - - if (outn & 0x10) - { - if (PSG->OutputB) volb += PSG->CountB; - PSG->CountB -= nextevent; - while (PSG->CountB <= 0) - { - PSG->CountB += PSG->PeriodB; - if (PSG->CountB > 0) - { - PSG->OutputB ^= 1; - if (PSG->OutputB) volb += PSG->PeriodB; - break; - } - PSG->CountB += PSG->PeriodB; - volb += PSG->PeriodB; - } - if (PSG->OutputB) volb -= PSG->CountB; - } - else - { - PSG->CountB -= nextevent; - while (PSG->CountB <= 0) - { - PSG->CountB += PSG->PeriodB; - if (PSG->CountB > 0) - { - PSG->OutputB ^= 1; - break; - } - PSG->CountB += PSG->PeriodB; - } - } - - if (outn & 0x20) - { - if (PSG->OutputC) volc += PSG->CountC; - PSG->CountC -= nextevent; - while (PSG->CountC <= 0) - { - PSG->CountC += PSG->PeriodC; - if (PSG->CountC > 0) - { - PSG->OutputC ^= 1; - if (PSG->OutputC) volc += PSG->PeriodC; - break; - } - PSG->CountC += PSG->PeriodC; - volc += PSG->PeriodC; - } - if (PSG->OutputC) volc -= PSG->CountC; - } - else - { - PSG->CountC -= nextevent; - while (PSG->CountC <= 0) - { - PSG->CountC += PSG->PeriodC; - if (PSG->CountC > 0) - { - PSG->OutputC ^= 1; - break; - } - PSG->CountC += PSG->PeriodC; - } - } - - PSG->CountN -= nextevent; - if (PSG->CountN <= 0) - { - /* Is noise output going to change? */ - if ((PSG->RNG + 1) & 2) /* (bit0^bit1)? */ - { - PSG->OutputN = ~PSG->OutputN; - outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]); - } - - /* The Random Number Generator of the 8910 is a 17-bit shift */ - /* register. The input to the shift register is bit0 XOR bit3 */ - /* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */ - - /* The following is a fast way to compute bit17 = bit0^bit3. */ - /* Instead of doing all the logic operations, we only check */ - /* bit0, relying on the fact that after three shifts of the */ - /* register, what now is bit3 will become bit0, and will */ - /* invert, if necessary, bit14, which previously was bit17. */ - if (PSG->RNG & 1) PSG->RNG ^= 0x24000; /* This version is called the "Galois configuration". */ - PSG->RNG >>= 1; - PSG->CountN += PSG->PeriodN; - } - - left -= nextevent; - } while (left > 0); - - /* update envelope */ - if (PSG->Holding == 0) - { - PSG->CountE -= STEP; - if (PSG->CountE <= 0) - { - do - { - PSG->CountEnv--; - PSG->CountE += PSG->PeriodE; - } while (PSG->CountE <= 0); - - /* check envelope current position */ - if (PSG->CountEnv < 0) - { - if (PSG->Hold) - { - if (PSG->Alternate) - PSG->Attack ^= 0x1f; - PSG->Holding = 1; - PSG->CountEnv = 0; - } - else - { - /* if CountEnv has looped an odd number of times (usually 1), */ - /* invert the output. */ - if (PSG->Alternate && (PSG->CountEnv & 0x20)) - PSG->Attack ^= 0x1f; - - PSG->CountEnv &= 0x1f; - } - } - - PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack]; - /* reload volume */ - if (PSG->EnvelopeA) PSG->VolA = PSG->VolE; - if (PSG->EnvelopeB) PSG->VolB = PSG->VolE; - if (PSG->EnvelopeC) PSG->VolC = PSG->VolE; - } - } +/* if we don't have any sound I/O code compiled in, don't do sound */ +#ifdef NO_SOUND + return; +#endif #if 0 - *(buf1++) = (vola * PSG->VolA) / STEP; - *(buf2++) = (volb * PSG->VolB) / STEP; - *(buf3++) = (volc * PSG->VolC) / STEP; -#else - // Output PCM wave [-32768...32767] instead of MAME's voltage level [0...32767] - // - This allows for better s/w mixing + if( !( !sound_enabled && settings_current.sound && + settings_current.emulation_speed == 100 ) ) + return; - if(PSG->VolA) - { - if(vola) - *(buf1++) = (vola * PSG->VolA) / STEP; - else - *(buf1++) = - (int) PSG->VolA; - } - else - { - *(buf1++) = 0; - } + sound_stereo_ay = settings_current.stereo_ay; + sound_stereo_beeper = settings_current.stereo_beeper; - // - - if(PSG->VolB) - { - if(volb) - *(buf2++) = (volb * PSG->VolB) / STEP; - else - *(buf2++) = - (int) PSG->VolB; - } - else - { - *(buf2++) = 0; - } - - // - - if(PSG->VolC) - { - if(volc) - *(buf3++) = (volc * PSG->VolC) / STEP; - else - *(buf3++) = - (int) PSG->VolC; - } - else - { - *(buf3++) = 0; - } +/* only try for stereo if we need it */ + if( sound_stereo_ay || sound_stereo_beeper ) + sound_stereo = 1; + ret = + sound_lowlevel_init( device, &settings_current.sound_freq, + &sound_stereo ); + if( ret ) + return; #endif - length--; - } -} +#if 0 +/* important to override these settings if not using stereo + * (it would probably be confusing to mess with the stereo + * settings in settings_current though, which is why we make copies + * rather than using the real ones). + */ + if( !sound_stereo ) { + sound_stereo_ay = 0; + sound_stereo_beeper = 0; + } + sound_enabled = sound_enabled_ever = 1; -static void AY8910_set_clock(int chip,int clock) -{ - struct AY8910 *PSG = &AYPSG[chip]; + sound_channels = ( sound_stereo ? 2 : 1 ); +#endif + sound_channels = 3; // 3 mono channels: ABC - /* the step clock for the tone and noise generators is the chip clock */ - /* divided by 8; for the envelope generator of the AY-3-8910, it is half */ - /* that much (clock/16), but the envelope of the YM2149 goes twice as */ - /* fast, therefore again clock/8. */ - /* Here we calculate the number of steps which happen during one sample */ - /* at the given sample rate. No. of events = sample rate / (clock/8). */ - /* STEP is a multiplier used to turn the fraction into a fixed point */ - /* number. */ - PSG->UpdateStep = (unsigned int) (((double)STEP * PSG->SampleRate * 8 + clock/2) / clock); // [TC: unsigned int cast] -} +// hz = ( float ) machine_current->timings.processor_speed / +// machine_current->timings.tstates_per_frame; + hz = 50; +// sound_generator_freq = +// settings_current.sound_hifi ? HIFI_FREQ : settings_current.sound_freq; + sound_generator_freq = SPKR_SAMPLE_RATE; + sound_generator_framesiz = sound_generator_freq / (int)hz; -static void build_mixer_table(int chip) -{ - struct AY8910 *PSG = &AYPSG[chip]; - int i; - double out; +#if 0 + if( ( sound_buf = (libspectrum_signed_word*) malloc( sizeof( libspectrum_signed_word ) * + sound_generator_framesiz * sound_channels ) ) == + NULL + || ( tape_buf = + malloc( sizeof( libspectrum_signed_word ) * + sound_generator_framesiz ) ) == NULL ) { + if( sound_buf ) { + free( sound_buf ); + sound_buf = NULL; + } + sound_end(); + return; + } +#endif +// sound_framesiz = ( float ) settings_current.sound_freq / hz; + sound_framesiz = sound_generator_freq / (int)hz; - /* calculate the volume->voltage conversion table */ - /* The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step) */ - /* The YM2149 still has 16 levels for the tone generators, but 32 for */ - /* the envelope generator (1.5dB per step). */ - out = MAX_OUTPUT; - for (i = 31;i > 0;i--) - { - PSG->VolTable[i] = (unsigned int) (out + 0.5); /* round to nearest */ // [TC: unsigned int cast] +#ifdef HAVE_SAMPLERATE + if( settings_current.sound_hifi ) { + if( ( convert_input_buffer = malloc( sizeof( float ) * + sound_generator_framesiz * + sound_channels ) ) == NULL + || ( convert_output_buffer = + malloc( sizeof( float ) * sound_framesiz * sound_channels ) ) == + NULL ) { + if( convert_input_buffer ) { + free( convert_input_buffer ); + convert_input_buffer = NULL; + } + sound_end(); + return; + } + } - out /= 1.188502227; /* = 10 ^ (1.5/20) = 1.5dB */ - } - PSG->VolTable[0] = 0; + src_state = src_new( SRC_SINC_MEDIUM_QUALITY, sound_channels, &error ); + if( error ) { + ui_error( UI_ERROR_ERROR, + "error initialising sample rate converter %s", + src_strerror( error ) ); + sound_end(); + return; + } +#endif /* #ifdef HAVE_SAMPLERATE */ + +/* if we're resuming, we need to be careful about what + * gets reset. The minimum we can do is the beeper + * buffer positions, so that's here. + */ +#if 0 + sound_oldpos[0] = sound_oldpos[1] = -1; + sound_fillpos[0] = sound_fillpos[1] = 0; +#endif + +/* this stuff should only happen on the initial call. + * (We currently assume the new sample rate will be the + * same as the previous one, hence no need to recalculate + * things dependent on that.) + */ +#if 0 + if( first_init ) { + first_init = 0; + + for( f = 0; f < 2; f++ ) + sound_oldval[f] = sound_oldval_orig[f] = 0; + } +#endif + +#if 0 + if( sound_stereo_beeper ) { + for( f = 0; f < STEREO_BUF_SIZE; f++ ) + pstereobuf[f] = 0; + pstereopos = 0; + pstereobufsiz = ( sound_generator_freq * psgap ) / 22000; + } + + if( sound_stereo_ay ) { + int pos = + ( sound_stereo_ay_narrow ? 3 : 6 ) * sound_generator_freq / 8000; + + for( f = 0; f < STEREO_BUF_SIZE; f++ ) + rstereobuf_l[f] = rstereobuf_r[f] = 0; + rstereopos = 0; + + /* the actual ACB/ABC bit :-) */ + rchan1pos = -pos; + if( sound_stereo_ay_abc ) + rchan2pos = 0, rchan3pos = pos; + else + rchan2pos = pos, rchan3pos = 0; + } +#endif + +#if 0 + ay_tick_incr = ( int ) ( 65536. * + libspectrum_timings_ay_speed( machine_current-> + machine ) / + sound_generator_freq ); +#endif + ay_tick_incr = ( int ) ( 65536. * m_fCurrentCLK_AY8910 / sound_generator_freq ); // [TC] } #if 0 -void ay8910_write_ym(int chip, int addr, int data) +void +sound_pause( void ) { - struct AY8910 *PSG = &AYPSG[chip]; + if( sound_enabled ) + sound_end(); +} -// if (addr & 1) -// { /* Data port */ -// int r = PSG->register_latch; - int r = addr; - if (r > 15) return; - if (r < 14) - { - if (r == AY_ESHAPE || PSG->Regs[r] != data) - { - /* update the output buffer before changing the register */ -// stream_update(PSG->Channel,0); - AY8910Update(chip, INT16 **buffer, int length) - } - } +void +sound_unpause( void ) +{ +/* No sound if fastloading in progress */ + if( settings_current.fastload && tape_is_playing() ) + return; - _AYWriteReg(PSG,r,data); - } -// else -// { /* Register port */ -// PSG->register_latch = data & 0x0f; -// } + sound_init( settings_current.sound_device ); } #endif +void CAY8910::sound_end( void ) +{ +#if 0 + if( sound_enabled ) { + if( sound_buf ) { + free( sound_buf ); + sound_buf = NULL; + free( tape_buf ); + tape_buf = NULL; + } + if( convert_input_buffer ) { + free( convert_input_buffer ); + convert_input_buffer = NULL; + } + if( convert_output_buffer ) { + free( convert_output_buffer ); + convert_output_buffer = NULL; + } +#ifdef HAVE_SAMPLERATE + if( src_state ) + src_state = src_delete( src_state ); +#endif /* #ifdef HAVE_SAMPLERATE */ + sound_lowlevel_end(); + sound_enabled = 0; + } +#endif + +#if 0 + if( sound_buf ) { + free( sound_buf ); + sound_buf = NULL; + } +#endif +} + + +#if 0 +/* write sample to buffer as pseudo-stereo */ +static void +sound_write_buf_pstereo( libspectrum_signed_word * out, int c ) +{ + int bl = ( c - pstereobuf[ pstereopos ] ) / 2; + int br = ( c + pstereobuf[ pstereopos ] ) / 2; + + if( bl < -AMPL_BEEPER ) + bl = -AMPL_BEEPER; + if( br < -AMPL_BEEPER ) + br = -AMPL_BEEPER; + if( bl > AMPL_BEEPER ) + bl = AMPL_BEEPER; + if( br > AMPL_BEEPER ) + br = AMPL_BEEPER; + + *out = bl; + out[1] = br; + + pstereobuf[ pstereopos ] = c; + pstereopos++; + if( pstereopos >= pstereobufsiz ) + pstereopos = 0; +} +#endif + + + +/* not great having this as a macro to inline it, but it's only + * a fairly short routine, and it saves messing about. + * (XXX ummm, possibly not so true any more :-)) + */ +#define AY_GET_SUBVAL( chan ) \ + ( level * 2 * ay_tone_tick[ chan ] / tone_count ) + +#define AY_DO_TONE( var, chan ) \ + ( var ) = 0; \ + is_low = 0; \ + if( level ) { \ + if( ay_tone_high[ chan ] ) \ + ( var ) = ( level ); \ + else { \ + ( var ) = -( level ); \ + is_low = 1; \ + } \ + } \ + \ + ay_tone_tick[ chan ] += tone_count; \ + count = 0; \ + while( ay_tone_tick[ chan ] >= ay_tone_period[ chan ] ) { \ + count++; \ + ay_tone_tick[ chan ] -= ay_tone_period[ chan ]; \ + ay_tone_high[ chan ] = !ay_tone_high[ chan ]; \ + \ + /* has to be here, unfortunately... */ \ + if( count == 1 && level && ay_tone_tick[ chan ] < tone_count ) { \ + if( is_low ) \ + ( var ) += AY_GET_SUBVAL( chan ); \ + else \ + ( var ) -= AY_GET_SUBVAL( chan ); \ + } \ + } \ + \ + /* if it's changed more than once during the sample, we can't */ \ + /* represent it faithfully. So, just hope it's a sample. */ \ + /* (That said, this should also help avoid aliasing noise.) */ \ + if( count > 1 ) \ + ( var ) = -( level ) + + +#if 0 +/* add val, correctly delayed on either left or right buffer, + * to add the AY stereo positioning. This doesn't actually put + * anything directly in sound_buf, though. + */ +#define GEN_STEREO( pos, val ) \ + if( ( pos ) < 0 ) { \ + rstereobuf_l[ rstereopos ] += ( val ); \ + rstereobuf_r[ ( rstereopos - pos ) % STEREO_BUF_SIZE ] += ( val ); \ + } else { \ + rstereobuf_l[ ( rstereopos + pos ) % STEREO_BUF_SIZE ] += ( val ); \ + rstereobuf_r[ rstereopos ] += ( val ); \ + } +#endif + + +/* bitmasks for envelope */ +#define AY_ENV_CONT 8 +#define AY_ENV_ATTACK 4 +#define AY_ENV_ALT 2 +#define AY_ENV_HOLD 1 + +#define HZ_COMMON_DENOMINATOR 50 + +void CAY8910::sound_ay_overlay( void ) +{ + int tone_level[3]; + int mixer, envshape; + int f, g, level, count; +// libspectrum_signed_word *ptr; + struct ay_change_tag *change_ptr = ay_change; + int changes_left = ay_change_count; + int reg, r; + int is_low; + int chan1, chan2, chan3; + unsigned int tone_count, noise_count; + libspectrum_dword sfreq, cpufreq; + +///* If no AY chip, don't produce any AY sound (!) */ +// if( !machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_AY ) +// return; + +/* convert change times to sample offsets, use common denominator of 50 to + avoid overflowing a dword */ + sfreq = sound_generator_freq / HZ_COMMON_DENOMINATOR; +// cpufreq = machine_current->timings.processor_speed / HZ_COMMON_DENOMINATOR; + cpufreq = (libspectrum_dword) (m_fCurrentCLK_AY8910 / HZ_COMMON_DENOMINATOR); // [TC] + for( f = 0; f < ay_change_count; f++ ) + ay_change[f].ofs = (USHORT) (( ay_change[f].tstates * sfreq ) / cpufreq); // [TC] Added cast + + libspectrum_signed_word* pBuf1 = g_ppSoundBuffers[0]; + libspectrum_signed_word* pBuf2 = g_ppSoundBuffers[1]; + libspectrum_signed_word* pBuf3 = g_ppSoundBuffers[2]; + +// for( f = 0, ptr = sound_buf; f < sound_generator_framesiz; f++ ) { + for( f = 0; f < sound_generator_framesiz; f++ ) { + /* update ay registers. All this sub-frame change stuff + * is pretty hairy, but how else would you handle the + * samples in Robocop? :-) It also clears up some other + * glitches. + */ + while( changes_left && f >= change_ptr->ofs ) { + sound_ay_registers[ reg = change_ptr->reg ] = change_ptr->val; + change_ptr++; + changes_left--; + + /* fix things as needed for some register changes */ + switch ( reg ) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + r = reg >> 1; + /* a zero-len period is the same as 1 */ + ay_tone_period[r] = ( sound_ay_registers[ reg & ~1 ] | + ( sound_ay_registers[ reg | 1 ] & 15 ) << 8 ); + if( !ay_tone_period[r] ) + ay_tone_period[r]++; + + /* important to get this right, otherwise e.g. Ghouls 'n' Ghosts + * has really scratchy, horrible-sounding vibrato. + */ + if( ay_tone_tick[r] >= ay_tone_period[r] * 2 ) + ay_tone_tick[r] %= ay_tone_period[r] * 2; + break; + case 6: + ay_noise_tick = 0; + ay_noise_period = ( sound_ay_registers[ reg ] & 31 ); + break; + case 11: + case 12: + /* this one *isn't* fixed-point */ + ay_env_period = + sound_ay_registers[11] | ( sound_ay_registers[12] << 8 ); + break; + case 13: + ay_env_internal_tick = ay_env_tick = ay_env_subcycles = 0; + env_first = 1; + env_rev = 0; + env_counter = ( sound_ay_registers[13] & AY_ENV_ATTACK ) ? 0 : 15; + break; + } + } + + /* the tone level if no enveloping is being used */ + for( g = 0; g < 3; g++ ) + tone_level[g] = ay_tone_levels[ sound_ay_registers[ 8 + g ] & 15 ]; + + /* envelope */ + envshape = sound_ay_registers[13]; + level = ay_tone_levels[ env_counter ]; + + for( g = 0; g < 3; g++ ) + if( sound_ay_registers[ 8 + g ] & 16 ) + tone_level[g] = level; + + /* envelope output counter gets incr'd every 16 AY cycles. + * Has to be a while, as this is sub-output-sample res. + */ + ay_env_subcycles += ay_tick_incr; + noise_count = 0; + while( ay_env_subcycles >= ( 16 << 16 ) ) { + ay_env_subcycles -= ( 16 << 16 ); + noise_count++; + ay_env_tick++; + while( ay_env_tick >= ay_env_period ) { + ay_env_tick -= ay_env_period; + + /* do a 1/16th-of-period incr/decr if needed */ + if( env_first || + ( ( envshape & AY_ENV_CONT ) && !( envshape & AY_ENV_HOLD ) ) ) { + if( env_rev ) + env_counter -= ( envshape & AY_ENV_ATTACK ) ? 1 : -1; + else + env_counter += ( envshape & AY_ENV_ATTACK ) ? 1 : -1; + if( env_counter < 0 ) + env_counter = 0; + if( env_counter > 15 ) + env_counter = 15; + } + + ay_env_internal_tick++; + while( ay_env_internal_tick >= 16 ) { + ay_env_internal_tick -= 16; + + /* end of cycle */ + if( !( envshape & AY_ENV_CONT ) ) + env_counter = 0; + else { + if( envshape & AY_ENV_HOLD ) { + if( env_first && ( envshape & AY_ENV_ALT ) ) + env_counter = ( env_counter ? 0 : 15 ); + } else { + /* non-hold */ + if( envshape & AY_ENV_ALT ) + env_rev = !env_rev; + else + env_counter = ( envshape & AY_ENV_ATTACK ) ? 0 : 15; + } + } + + env_first = 0; + } + + /* don't keep trying if period is zero */ + if( !ay_env_period ) + break; + } + } + + /* generate tone+noise... or neither. + * (if no tone/noise is selected, the chip just shoves the + * level out unmodified. This is used by some sample-playing + * stuff.) + */ + chan1 = tone_level[0]; + chan2 = tone_level[1]; + chan3 = tone_level[2]; + mixer = sound_ay_registers[7]; + + ay_tone_subcycles += ay_tick_incr; + tone_count = ay_tone_subcycles >> ( 3 + 16 ); + ay_tone_subcycles &= ( 8 << 16 ) - 1; + + if( ( mixer & 1 ) == 0 ) { + level = chan1; + AY_DO_TONE( chan1, 0 ); + } + if( ( mixer & 0x08 ) == 0 && noise_toggle ) + chan1 = 0; + + if( ( mixer & 2 ) == 0 ) { + level = chan2; + AY_DO_TONE( chan2, 1 ); + } + if( ( mixer & 0x10 ) == 0 && noise_toggle ) + chan2 = 0; + + if( ( mixer & 4 ) == 0 ) { + level = chan3; + AY_DO_TONE( chan3, 2 ); + } + if( ( mixer & 0x20 ) == 0 && noise_toggle ) + chan3 = 0; + + /* write the sample(s) */ + *pBuf1++ = chan1; // [TC] + *pBuf2++ = chan2; // [TC] + *pBuf3++ = chan3; // [TC] +#if 0 + if( !sound_stereo ) { + /* mono */ + ( *ptr++ ) += chan1 + chan2 + chan3; + } else { + if( !sound_stereo_ay ) { + /* stereo output, but mono AY sound; still, + * incr separately in case of beeper pseudostereo. + */ + ( *ptr++ ) += chan1 + chan2 + chan3; + ( *ptr++ ) += chan1 + chan2 + chan3; + } else { + /* stereo with ACB/ABC AY positioning. + * Here we use real stereo positions for the channels. + * Just because, y'know, it's cool and stuff. No, really. :-) + * This is a little tricky, as it works by delaying sounds + * on the left or right channels to model the delay you get + * in the real world when sounds originate at different places. + */ + GEN_STEREO( rchan1pos, chan1 ); + GEN_STEREO( rchan2pos, chan2 ); + GEN_STEREO( rchan3pos, chan3 ); + ( *ptr++ ) += rstereobuf_l[ rstereopos ]; + ( *ptr++ ) += rstereobuf_r[ rstereopos ]; + rstereobuf_l[ rstereopos ] = rstereobuf_r[ rstereopos ] = 0; + rstereopos++; + if( rstereopos >= STEREO_BUF_SIZE ) + rstereopos = 0; + } + } +#endif + + /* update noise RNG/filter */ + ay_noise_tick += noise_count; + while( ay_noise_tick >= ay_noise_period ) { + ay_noise_tick -= ay_noise_period; + + if( ( rng & 1 ) ^ ( ( rng & 2 ) ? 1 : 0 ) ) + noise_toggle = !noise_toggle; + + /* rng is 17-bit shift reg, bit 0 is output. + * input is bit 0 xor bit 2. + */ + rng |= ( ( rng & 1 ) ^ ( ( rng & 4 ) ? 1 : 0 ) ) ? 0x20000 : 0; + rng >>= 1; + + /* don't keep trying if period is zero */ + if( !ay_noise_period ) + break; + } + } +} + +// AppleWin:TC Holding down ScrollLock will result in lots of AY changes /ay_change_count/ +// - since sound_ay_overlay() is called to consume them. + +/* don't make the change immediately; record it for later, + * to be made by sound_frame() (via sound_ay_overlay()). + */ +void CAY8910::sound_ay_write( int reg, int val, libspectrum_dword now ) +{ + if( ay_change_count < AY_CHANGE_MAX ) { + ay_change[ ay_change_count ].tstates = now; + ay_change[ ay_change_count ].reg = ( reg & 15 ); + ay_change[ ay_change_count ].val = val; + ay_change_count++; + } +} + + +/* no need to call this initially, but should be called + * on reset otherwise. + */ +void CAY8910::sound_ay_reset( void ) +{ + int f; + +/* recalculate timings based on new machines ay clock */ + sound_ay_init(); + + ay_change_count = 0; + for( f = 0; f < 16; f++ ) + sound_ay_write( f, 0, 0 ); + for( f = 0; f < 3; f++ ) + ay_tone_high[f] = 0; + ay_tone_subcycles = ay_env_subcycles = 0; +} + + +#if 0 +/* write stereo or mono beeper sample, and incr ptr */ +#define SOUND_WRITE_BUF_BEEPER( ptr, val ) \ + do { \ + if( sound_stereo_beeper ) { \ + sound_write_buf_pstereo( ( ptr ), ( val ) ); \ + ( ptr ) += 2; \ + } else { \ + *( ptr )++ = ( val ); \ + if( sound_stereo ) \ + *( ptr )++ = ( val ); \ + } \ + } while(0) + +/* the tape version works by writing to a separate mono buffer, + * which gets added after being generated. + */ +#define SOUND_WRITE_BUF( is_tape, ptr, val ) \ + if( is_tape ) \ + *( ptr )++ = ( val ); \ + else \ + SOUND_WRITE_BUF_BEEPER( ptr, val ) +#endif + +#ifdef HAVE_SAMPLERATE +static void +sound_resample( void ) +{ + int error; + SRC_DATA data; + + data.data_in = convert_input_buffer; + data.input_frames = sound_generator_framesiz; + data.data_out = convert_output_buffer; + data.output_frames = sound_framesiz; + data.src_ratio = + ( double ) settings_current.sound_freq / sound_generator_freq; + data.end_of_input = 0; + + src_short_to_float_array( ( const short * ) sound_buf, convert_input_buffer, + sound_generator_framesiz * sound_channels ); + + while( data.input_frames ) { + error = src_process( src_state, &data ); + if( error ) { + ui_error( UI_ERROR_ERROR, "hifi sound downsample error %s", + src_strerror( error ) ); + sound_end(); + return; + } + + src_float_to_short_array( convert_output_buffer, ( short * ) sound_buf, + data.output_frames_gen * sound_channels ); + + sound_lowlevel_frame( sound_buf, + data.output_frames_gen * sound_channels ); + + data.data_in += data.input_frames_used * sound_channels; + data.input_frames -= data.input_frames_used; + } +} +#endif /* #ifdef HAVE_SAMPLERATE */ + +void CAY8910::sound_frame( void ) +{ +#if 0 + libspectrum_signed_word *ptr, *tptr; + int f, bchan; + int ampl = AMPL_BEEPER; + + if( !sound_enabled ) + return; + +/* fill in remaining beeper/tape sound */ + ptr = + sound_buf + ( sound_stereo ? sound_fillpos[0] * 2 : sound_fillpos[0] ); + for( bchan = 0; bchan < 2; bchan++ ) { + for( f = sound_fillpos[ bchan ]; f < sound_generator_framesiz; f++ ) + SOUND_WRITE_BUF( bchan, ptr, sound_oldval[ bchan ] ); + + ptr = tape_buf + sound_fillpos[1]; + ampl = AMPL_TAPE; + } + +/* overlay tape sound */ + ptr = sound_buf; + tptr = tape_buf; + for( f = 0; f < sound_generator_framesiz; f++, tptr++ ) { + ( *ptr++ ) += *tptr; + if( sound_stereo ) + ( *ptr++ ) += *tptr; + } +#endif + +/* overlay AY sound */ + sound_ay_overlay(); + +#ifdef HAVE_SAMPLERATE +/* resample from generated frequency down to output frequency if required */ + if( settings_current.sound_hifi ) + sound_resample(); + else +#endif /* #ifdef HAVE_SAMPLERATE */ +#if 0 + sound_lowlevel_frame( sound_buf, + sound_generator_framesiz * sound_channels ); +#endif + +#if 0 + sound_oldpos[0] = sound_oldpos[1] = -1; + sound_fillpos[0] = sound_fillpos[1] = 0; +#endif + + ay_change_count = 0; +} + +#if 0 +/* two beepers are supported - the real beeper (call with is_tape==0) + * and a `fake' beeper which lets you hear when a tape is being played. + */ +void +sound_beeper( int is_tape, int on ) +{ + libspectrum_signed_word *ptr; + int newpos, subpos; + int val, subval; + int f; + int bchan = ( is_tape ? 1 : 0 ); + int ampl = ( is_tape ? AMPL_TAPE : AMPL_BEEPER ); + int vol = ampl * 2; + + if( !sound_enabled ) + return; + + val = ( on ? -ampl : ampl ); + + if( val == sound_oldval_orig[ bchan ] ) + return; + +/* XXX a lookup table might help here, but would need to regenerate it + * whenever cycles_per_frame were changed (i.e. when machine type changed). + */ + newpos = + ( tstates * sound_generator_framesiz ) / + machine_current->timings.tstates_per_frame; + subpos = + ( ( ( libspectrum_signed_qword ) tstates ) * sound_generator_framesiz * + vol ) / ( machine_current->timings.tstates_per_frame ) - vol * newpos; + +/* if we already wrote here, adjust the level. + */ + if( newpos == sound_oldpos[ bchan ] ) { + /* adjust it as if the rest of the sample period were all in + * the new state. (Often it will be, but if not, we'll fix + * it later by doing this again.) + */ + if( on ) + beeper_last_subpos[ bchan ] += vol - subpos; + else + beeper_last_subpos[ bchan ] -= vol - subpos; + } else + beeper_last_subpos[ bchan ] = ( on ? vol - subpos : subpos ); + + subval = ampl - beeper_last_subpos[ bchan ]; + + if( newpos >= 0 ) { + /* fill gap from previous position */ + if( is_tape ) + ptr = tape_buf + sound_fillpos[1]; + else + ptr = + sound_buf + + ( sound_stereo ? sound_fillpos[0] * 2 : sound_fillpos[0] ); + + for( f = sound_fillpos[ bchan ]; + f < newpos && f < sound_generator_framesiz; + f++ ) + SOUND_WRITE_BUF( bchan, ptr, sound_oldval[ bchan ] ); + + if( newpos < sound_generator_framesiz ) { + /* newpos may be less than sound_fillpos, so... */ + if( is_tape ) + ptr = tape_buf + newpos; + else + ptr = sound_buf + ( sound_stereo ? newpos * 2 : newpos ); + + /* write subsample value */ + SOUND_WRITE_BUF( bchan, ptr, subval ); + } + } + + sound_oldpos[ bchan ] = newpos; + sound_fillpos[ bchan ] = newpos + 1; + sound_oldval[ bchan ] = sound_oldval_orig[ bchan ] = val; +} +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// AY8910 interface + +#include "CPU.h" // For g_nCumulativeCycles + +static CAY8910 g_AY8910[MAX_8910]; +static unsigned __int64 g_uLastCumulativeCycles = 0; + + +void _AYWriteReg(int chip, int r, int v) +{ + libspectrum_dword uOffset = (libspectrum_dword) (g_nCumulativeCycles - g_uLastCumulativeCycles); + g_AY8910[chip].sound_ay_write(r, v, uOffset); +} + void AY8910_reset(int chip) { - g_bAYReset = true; - - int i; - struct AY8910 *PSG = &AYPSG[chip]; - - PSG->register_latch = 0; - PSG->RNG = 1; - PSG->OutputA = 0; - PSG->OutputB = 0; - PSG->OutputC = 0; - PSG->OutputN = 0xff; - PSG->lastEnable = -1; /* force a write */ - for (i = 0;i < AY_PORTA;i++) - _AYWriteReg(chip,i,0); /* AYWriteReg() uses the timer system; we cannot */ - /* call it at this time because the timer system */ - /* has not been initialized. */ - - g_bAYReset = false; + // Don't reset the AY CLK, as this is a property of the card (MB/Phasor), not the AY chip + g_AY8910[chip].sound_ay_reset(); // Calls: sound_ay_init(); } -//------------------------------------- +void AY8910UpdateSetCycles() +{ + g_uLastCumulativeCycles = g_nCumulativeCycles; +} + +void AY8910Update(int chip, INT16** buffer, int nNumSamples) +{ + AY8910UpdateSetCycles(); + + sound_generator_framesiz = nNumSamples; + g_ppSoundBuffers = buffer; + g_AY8910[chip].sound_frame(); +} void AY8910_InitAll(int nClock, int nSampleRate) { - for(int nChip=0; nChipSampleRate = nSampleRate; - - PSG->PortAread = NULL; - PSG->PortBread = NULL; - PSG->PortAwrite = NULL; - PSG->PortBwrite = NULL; - - AY8910_set_clock(nChip, nClock); - - build_mixer_table(nChip); + g_AY8910[i].sound_init(NULL); // Inits mainly static members (except ay_tick_incr) + g_AY8910[i].sound_ay_init(); } } -//------------------------------------- - void AY8910_InitClock(int nClock) { - for(int nChip=0; nChip= MAX_8910) + if(uChip >= MAX_8910) return NULL; - return &AYPSG[nAyNum].Regs[0]; + return g_AY8910[uChip].GetAYRegsPtr(); } diff --git a/AppleWin/source/AY8910.h b/AppleWin/source/AY8910.h index 96b0cc03..59a53359 100644 --- a/AppleWin/source/AY8910.h +++ b/AppleWin/source/AY8910.h @@ -3,13 +3,83 @@ #define MAX_8910 4 -void _AYWriteReg(int n, int r, int v); -void AY8910_write_ym(int chip, int addr, int data); +//------------------------------------- +// MAME interface + +void _AYWriteReg(int chip, int r, int v); +//void AY8910_write_ym(int chip, int addr, int data); void AY8910_reset(int chip); -void AY8910Update(int chip,INT16 **buffer,int length); +void AY8910Update(int chip, INT16** buffer, int nNumSamples); void AY8910_InitAll(int nClock, int nSampleRate); void AY8910_InitClock(int nClock); -BYTE* AY8910_GetRegsPtr(UINT nAyNum); +BYTE* AY8910_GetRegsPtr(UINT uChip); + +void AY8910UpdateSetCycles(); + +//------------------------------------- +// FUSE stuff + +typedef ULONG libspectrum_dword; +typedef UCHAR libspectrum_byte; +typedef SHORT libspectrum_signed_word; + +/* max. number of sub-frame AY port writes allowed; + * given the number of port writes theoretically possible in a + * 50th I think this should be plenty. + */ +#define AY_CHANGE_MAX 8000 + +class CAY8910 +{ +public: + CAY8910(); + virtual ~CAY8910() {}; + + void sound_ay_init( void ); + void sound_init( const char *device ); + void sound_ay_write( int reg, int val, libspectrum_dword now ); + void sound_ay_reset( void ); + void sound_frame( void ); + BYTE* GetAYRegsPtr( void ) { return &sound_ay_registers[0]; } + static void SetCLK( double CLK ) { m_fCurrentCLK_AY8910 = CLK; } + +private: + void sound_end( void ); + void sound_ay_overlay( void ); + +private: + /* foo_subcycles are fixed-point with low 16 bits as fractional part. + * The other bits count as the chip does. + */ + unsigned int ay_tone_tick[3], ay_tone_high[3], ay_noise_tick; + unsigned int ay_tone_subcycles, ay_env_subcycles; + unsigned int ay_env_internal_tick, ay_env_tick; + unsigned int ay_tick_incr; + unsigned int ay_tone_period[3], ay_noise_period, ay_env_period; + + //static int beeper_last_subpos[2] = { 0, 0 }; + + /* Local copy of the AY registers */ + libspectrum_byte sound_ay_registers[16]; + + struct ay_change_tag + { + libspectrum_dword tstates; + unsigned short ofs; + unsigned char reg, val; + }; + + struct ay_change_tag ay_change[ AY_CHANGE_MAX ]; + int ay_change_count; + + // statics from sound_ay_overlay() + int rng; + int noise_toggle; + int env_first, env_rev, env_counter; + + // Vars shared between all AY's + static double m_fCurrentCLK_AY8910; +}; #endif diff --git a/AppleWin/source/Applewin.cpp b/AppleWin/source/Applewin.cpp index cabb6a94..3b5becfb 100644 --- a/AppleWin/source/Applewin.cpp +++ b/AppleWin/source/Applewin.cpp @@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #pragma hdrstop #include #include "MouseInterface.h" -#include "z80\z80.h" char VERSIONSTRING[16] = "xx.yy.zz.ww"; @@ -376,9 +375,9 @@ void LoadConfiguration () { DWORD dwComputerType; - if (LOAD(TEXT(REGVALUE_APPLE2_TYPE),&dwComputerType)) + if (REGLOAD(TEXT(REGVALUE_APPLE2_TYPE),&dwComputerType)) { - LOAD(TEXT(REGVALUE_CLONETYPE),&g_uCloneType); + REGLOAD(TEXT(REGVALUE_CLONETYPE),&g_uCloneType); if ((dwComputerType >= A2TYPE_MAX) || (dwComputerType >= A2TYPE_UNDEFINED && dwComputerType < A2TYPE_CLONE)) dwComputerType = A2TYPE_APPLE2EEHANCED; @@ -399,7 +398,7 @@ void LoadConfiguration () } else // Support older AppleWin registry entries { - LOAD(TEXT("Computer Emulation"),&dwComputerType); + REGLOAD(TEXT("Computer Emulation"),&dwComputerType); switch (dwComputerType) { // NB. No A2TYPE_APPLE2E (this is correct) @@ -422,19 +421,19 @@ void LoadConfiguration () } - LOAD(TEXT("Joystick 0 Emulation"),&joytype[0]); - LOAD(TEXT("Joystick 1 Emulation"),&joytype[1]); - LOAD(TEXT("Sound Emulation") ,&soundtype); + REGLOAD(TEXT("Joystick 0 Emulation"),&joytype[0]); + REGLOAD(TEXT("Joystick 1 Emulation"),&joytype[1]); + REGLOAD(TEXT("Sound Emulation") ,&soundtype); DWORD dwSerialPort; - if (LOAD(TEXT("Serial Port"),&dwSerialPort)) + if (REGLOAD(TEXT("Serial Port"),&dwSerialPort)) sg_SSC.SetSerialPort(dwSerialPort); - LOAD(TEXT("Emulation Speed") ,&g_dwSpeed); - LOAD(TEXT("Enhance Disk Speed"),(DWORD *)&enhancedisk); - LOAD(TEXT("Video Emulation") ,&videotype); - LOAD(TEXT("Monochrome Color") ,&monochrome); - LOAD(TEXT("Uthernet Active") ,(DWORD *)&tfe_enabled); + REGLOAD(TEXT("Emulation Speed") ,&g_dwSpeed); + REGLOAD(TEXT("Enhance Disk Speed"),(DWORD *)&enhancedisk); + REGLOAD(TEXT("Video Emulation") ,&videotype); + REGLOAD(TEXT("Monochrome Color") ,&monochrome); + REGLOAD(TEXT("Uthernet Active") ,(DWORD *)&tfe_enabled); SetCurrentCLK6502(); @@ -442,36 +441,36 @@ void LoadConfiguration () DWORD dwTmp; - if(LOAD(TEXT(REGVALUE_THE_FREEZES_F8_ROM), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_THE_FREEZES_F8_ROM), &dwTmp)) g_uTheFreezesF8Rom = dwTmp; - if(LOAD(TEXT(REGVALUE_SPKR_VOLUME), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_SPKR_VOLUME), &dwTmp)) SpkrSetVolume(dwTmp, PSP_GetVolumeMax()); - if(LOAD(TEXT(REGVALUE_MB_VOLUME), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_MB_VOLUME), &dwTmp)) MB_SetVolume(dwTmp, PSP_GetVolumeMax()); - if(LOAD(TEXT(REGVALUE_SOUNDCARD_TYPE), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_SOUNDCARD_TYPE), &dwTmp)) MB_SetSoundcardType((eSOUNDCARDTYPE)dwTmp); - if(LOAD(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), &dwTmp)) g_bSaveStateOnExit = dwTmp ? true : false; - if(LOAD(TEXT(REGVALUE_DUMP_TO_PRINTER), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_DUMP_TO_PRINTER), &dwTmp)) g_bDumpToPrinter = dwTmp ? true : false; - if(LOAD(TEXT(REGVALUE_CONVERT_ENCODING), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_CONVERT_ENCODING), &dwTmp)) g_bConvertEncoding = dwTmp ? true : false; - if(LOAD(TEXT(REGVALUE_FILTER_UNPRINTABLE), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_FILTER_UNPRINTABLE), &dwTmp)) g_bFilterUnprintable = dwTmp ? true : false; - if(LOAD(TEXT(REGVALUE_PRINTER_APPEND), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_PRINTER_APPEND), &dwTmp)) g_bPrinterAppend = dwTmp ? true : false; - if(LOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp)) HD_SetEnabled(dwTmp ? true : false); char szHDFilename[MAX_PATH] = {0}; @@ -480,23 +479,23 @@ void LoadConfiguration () if(RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_HDD_IMAGE2), 1, szHDFilename, sizeof(szHDFilename))) HD_InsertDisk2(1, szHDFilename); - if(LOAD(TEXT(REGVALUE_PDL_XTRIM), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_PDL_XTRIM), &dwTmp)) JoySetTrim((short)dwTmp, true); - if(LOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp)) JoySetTrim((short)dwTmp, false); - if(LOAD(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), &dwTmp)) g_uScrollLockToggle = dwTmp; - if(LOAD(TEXT(REGVALUE_MOUSE_IN_SLOT4), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_MOUSE_IN_SLOT4), &dwTmp)) g_uMouseInSlot4 = dwTmp; - if(LOAD(TEXT(REGVALUE_MOUSE_CROSSHAIR), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_MOUSE_CROSSHAIR), &dwTmp)) g_uMouseShowCrosshair = dwTmp; - if(LOAD(TEXT(REGVALUE_MOUSE_RESTRICT_TO_WINDOW), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_MOUSE_RESTRICT_TO_WINDOW), &dwTmp)) g_uMouseRestrictToWindow = dwTmp; #ifdef SUPPORT_CPM - if(LOAD(TEXT(REGVALUE_Z80_IN_SLOT5), &dwTmp)) + if(REGLOAD(TEXT(REGVALUE_Z80_IN_SLOT5), &dwTmp)) g_uZ80InSlot5 = dwTmp; if (g_uZ80InSlot5) @@ -527,7 +526,7 @@ void LoadConfiguration () Disk_LoadLastDiskImage(1); dwTmp = 10; - LOAD(TEXT(REGVALUE_PRINTER_IDLE_LIMIT), &dwTmp); + REGLOAD(TEXT(REGVALUE_PRINTER_IDLE_LIMIT), &dwTmp); Printer_SetIdleLimit(dwTmp); char szUthernetInt[MAX_PATH] = {0}; diff --git a/AppleWin/source/CPU.cpp b/AppleWin/source/CPU.cpp index a7119bd7..9ebca005 100644 --- a/AppleWin/source/CPU.cpp +++ b/AppleWin/source/CPU.cpp @@ -89,9 +89,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "MouseInterface.h" #ifdef SUPPORT_CPM -#include "z80\z80.h" -#include "z80\z80emu.h" -#include "z80\z80io.h" +#include "z80emu.h" +#include "Z80VICE\z80.h" +#include "Z80VICE\z80mem.h" #endif #define AF_SIGN 0x80 @@ -932,7 +932,7 @@ static DWORD Cpu65C02 (DWORD uTotalCycles) #ifdef SUPPORT_CPM if (g_ActiveCPU == CPU_Z80) { - const UINT uZ80Cycles = InternalZ80Execute(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles) + const UINT uZ80Cycles = z80_mainloop(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles) } else #endif @@ -1240,7 +1240,7 @@ static DWORD Cpu6502 (DWORD uTotalCycles) #ifdef SUPPORT_CPM if (g_ActiveCPU == CPU_Z80) { - const UINT uZ80Cycles = InternalZ80Execute(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles) + const UINT uZ80Cycles = z80_mainloop(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles) } else #endif @@ -1630,9 +1630,8 @@ void CpuInitialize () CpuNmiReset(); #ifdef SUPPORT_CPM - // Z80 - InitTables(); - Z80_Reset(); + z80mem_initialize(); + z80_reset(); #endif } @@ -1738,7 +1737,7 @@ void CpuReset() #ifdef SUPPORT_CPM g_ActiveCPU = CPU_6502; - Z80_Reset(); + z80_reset(); #endif } diff --git a/AppleWin/source/Common.h b/AppleWin/source/Common.h index cea6812c..db05439a 100644 --- a/AppleWin/source/Common.h +++ b/AppleWin/source/Common.h @@ -66,8 +66,8 @@ enum AppMode_e #define TITLE_PAUSED TEXT(" Paused ") #define TITLE_STEPPING TEXT("Stepping") -#define LOAD(a,b) RegLoadValue(TEXT("Configuration"),a,1,b) -#define SAVE(a,b) RegSaveValue(TEXT("Configuration"),a,1,b) +#define REGLOAD(a,b) RegLoadValue(TEXT("Configuration"),a,1,b) +#define REGSAVE(a,b) RegSaveValue(TEXT("Configuration"),a,1,b) // Configuration #define REG_CONFIG "Configuration" diff --git a/AppleWin/source/CommonVICE/6510core.h b/AppleWin/source/CommonVICE/6510core.h new file mode 100644 index 00000000..9a704f80 --- /dev/null +++ b/AppleWin/source/CommonVICE/6510core.h @@ -0,0 +1,87 @@ +/* + * 6510core.h - Core definitions for the MOS 6510 CPU emulation. + * + * Written by + * Ettore Perazzoli + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _6510CORE_H +#define _6510CORE_H + +/* Masks to extract information. */ +#define OPINFO_DELAYS_INTERRUPT_MSK (1 << 8) +#define OPINFO_DISABLES_IRQ_MSK (1 << 9) +#define OPINFO_ENABLES_IRQ_MSK (1 << 10) + +/* Return nonzero if `opinfo' causes a 1-cycle interrupt delay. */ +#define OPINFO_DELAYS_INTERRUPT(opinfo) \ + ((opinfo) & OPINFO_DELAYS_INTERRUPT_MSK) + +/* Return nonzero if `opinfo' has changed the I flag from 0 to 1, so that an + IRQ that happened 2 or more cycles before the end of the opcode should be + allowed. */ +#define OPINFO_DISABLES_IRQ(opinfo) \ + ((opinfo) & OPINFO_DISABLES_IRQ_MSK) + +/* Return nonzero if `opinfo' has changed the I flag from 1 to 0, so that an + IRQ that happened 2 or more cycles before the end of the opcode should not + be allowed. */ +#define OPINFO_ENABLES_IRQ(opinfo) \ + ((opinfo) & OPINFO_ENABLES_IRQ_MSK) + +/* Set the information for `opinfo'. `number' is the opcode number, + `delays_interrupt' must be non-zero if it causes a 1-cycle interrupt + delay, `disables_interrupts' must be non-zero if it disabled IRQs. */ +#define OPINFO_SET(opinfo, \ + number, delays_interrupt, disables_irq, enables_irq) \ + ((opinfo) = ((number) \ + | ((delays_interrupt) ? OPINFO_DELAYS_INTERRUPT_MSK : 0) \ + | ((disables_irq) ? OPINFO_DISABLES_IRQ_MSK : 0) \ + | ((enables_irq) ? OPINFO_ENABLES_IRQ_MSK : 0))) + +/* Set whether the opcode causes the 1-cycle interrupt delay according to + `delay'. */ +#define OPINFO_SET_DELAYS_INTERRUPT(opinfo, delay) \ + do { \ + if ((delay)) \ + (opinfo) |= OPINFO_DELAYS_INTERRUPT_MSK; \ + } while (0) + +/* Set whether the opcode disables previously enabled IRQs according to + `disable'. */ +#define OPINFO_SET_DISABLES_IRQ(opinfo, disable) \ + do { \ + if ((disable)) \ + (opinfo) |= OPINFO_DISABLES_IRQ_MSK; \ + } while (0) + +/* Set whether the opcode enables previously disabled IRQs according to + `enable'. */ +#define OPINFO_SET_ENABLES_IRQ(opinfo, enable) \ + do { \ + if ((enable)) \ + (opinfo) |= OPINFO_ENABLES_IRQ_MSK; \ + } while (0) + +#endif + diff --git a/AppleWin/source/CommonVICE/alarm.h b/AppleWin/source/CommonVICE/alarm.h new file mode 100644 index 00000000..ea166f2b --- /dev/null +++ b/AppleWin/source/CommonVICE/alarm.h @@ -0,0 +1,191 @@ +/* + * alarm.h - Alarm handling. + * + * Written by + * Ettore Perazzoli + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _ALARM_H +#define _ALARM_H + +#include "..\CommonVICE\types.h" + +#define ALARM_CONTEXT_MAX_PENDING_ALARMS 0x100 + +typedef void (*alarm_callback_t)(CLOCK offset, void *data); + +/* An alarm. */ +struct alarm_s { + /* Descriptive name of the alarm. */ + char *name; + + /* Alarm context this alarm is in. */ + struct alarm_context_s *context; + + /* Callback to be called when the alarm is dispatched. */ + alarm_callback_t callback; + + /* Index into the pending alarm list. If < 0, the alarm is not + pending. */ + int pending_idx; + + /* Call data */ + void *data; + + /* Link to the next and previous alarms in the list. */ + struct alarm_s *next, *prev; +}; +typedef struct alarm_s alarm_t; + +struct pending_alarms_s { + /* The alarm. */ + struct alarm_s *alarm; + + /* Clock tick at which this alarm should be activated. */ + CLOCK clk; +}; +typedef struct pending_alarms_s pending_alarms_t; + +/* An alarm context. */ +struct alarm_context_s { + /* Descriptive name of the alarm context. */ + char *name; + + /* Alarm list. */ + struct alarm_s *alarms; + + /* Pending alarm array. Statically allocated because it's slightly + faster this way. */ + pending_alarms_t pending_alarms[ALARM_CONTEXT_MAX_PENDING_ALARMS]; + unsigned int num_pending_alarms; + + /* Clock tick for the next pending alarm. */ + CLOCK next_pending_alarm_clk; + + /* Pending alarm number. */ + int next_pending_alarm_idx; +}; +typedef struct alarm_context_s alarm_context_t; + +/* ------------------------------------------------------------------------ */ + +extern alarm_context_t *alarm_context_new(const char *name); +extern void alarm_context_init(alarm_context_t *context, const char *name); +extern void alarm_context_destroy(alarm_context_t *context); +extern void alarm_context_time_warp(alarm_context_t *context, CLOCK warp_amount, + int warp_direction); +extern alarm_t *alarm_new(alarm_context_t *context, const char *name, + alarm_callback_t callback, void *data); +extern void alarm_destroy(alarm_t *alarm); +extern void alarm_unset(alarm_t *alarm); +extern void alarm_log_too_many_alarms(void); + +/* ------------------------------------------------------------------------- */ + +#if 1 //TC +/* Inline functions. */ + +/*inline*/ static CLOCK alarm_context_next_pending_clk(alarm_context_t *context) +{ + return context->next_pending_alarm_clk; +} + +/*inline*/ static void alarm_context_update_next_pending(alarm_context_t *context) +{ + CLOCK next_pending_alarm_clk = (CLOCK)~0L; + unsigned int next_pending_alarm_idx; + unsigned int i; + + next_pending_alarm_idx = context->next_pending_alarm_idx; + + for (i = 0; i < context->num_pending_alarms; i++) { + CLOCK pending_clk = context->pending_alarms[i].clk; + + if (pending_clk <= next_pending_alarm_clk) { + next_pending_alarm_clk = pending_clk; + next_pending_alarm_idx = i; + } + } + + context->next_pending_alarm_clk = next_pending_alarm_clk; + context->next_pending_alarm_idx = next_pending_alarm_idx; +} + +/*inline*/ static void alarm_context_dispatch(alarm_context_t *context, + CLOCK cpu_clk) +{ + CLOCK offset; + unsigned int idx; + alarm_t *alarm; + + offset = (CLOCK)(cpu_clk - context->next_pending_alarm_clk); + + idx = context->next_pending_alarm_idx; + alarm = context->pending_alarms[idx].alarm; + + (alarm->callback)(offset, alarm->data); +} + +/*inline*/ static void alarm_set(alarm_t *alarm, CLOCK cpu_clk) +{ + alarm_context_t *context; + int idx; + + context = alarm->context; + idx = alarm->pending_idx; + + if (idx < 0) { + unsigned int new_idx; + + /* Not pending yet: add. */ + + new_idx = context->num_pending_alarms; + if (new_idx >= ALARM_CONTEXT_MAX_PENDING_ALARMS) { + alarm_log_too_many_alarms(); + return; + } + + context->pending_alarms[new_idx].alarm = alarm; + context->pending_alarms[new_idx].clk = cpu_clk; + + context->num_pending_alarms++; + + if (cpu_clk < context->next_pending_alarm_clk) { + context->next_pending_alarm_clk = cpu_clk; + context->next_pending_alarm_idx = new_idx; + } + + alarm->pending_idx = new_idx; + } else { + /* Already pending: modify. */ + + context->pending_alarms[idx].clk = cpu_clk; + if (context->next_pending_alarm_clk > cpu_clk + || idx == context->next_pending_alarm_idx) + alarm_context_update_next_pending(context); + } +} +#endif // TC + +#endif + diff --git a/AppleWin/source/CommonVICE/interrupt.h b/AppleWin/source/CommonVICE/interrupt.h new file mode 100644 index 00000000..2961a0b5 --- /dev/null +++ b/AppleWin/source/CommonVICE/interrupt.h @@ -0,0 +1,314 @@ +/* + * interrupt.h - Implementation of 6510 interrupts and alarms. + * + * Written by + * Ettore Perazzoli + * André Fachat + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _INTERRUPT_H +#define _INTERRUPT_H + +#include + +#include "..\CommonVICE\types.h" + +/* Define the number of cycles needed by the CPU to detect the NMI or IRQ. */ +#define INTERRUPT_DELAY 2 + +#define INTRRUPT_MAX_DMA_PER_OPCODE (7+10000) + +/* These are the available types of interrupt lines. */ +enum cpu_int { + IK_NONE = 0, + IK_NMI = 1 << 0, + IK_IRQ = 1 << 1, + IK_RESET = 1 << 2, + IK_TRAP = 1 << 3, + IK_MONITOR = 1 << 4, + IK_DMA = 1 << 5, + IK_IRQPEND = 1 << 6 +}; + +struct interrupt_cpu_status_s { + /* Number of interrupt lines. */ + unsigned int num_ints; + + /* Define, for each interrupt source, whether it has a pending interrupt + (IK_IRQ, IK_NMI, IK_RESET and IK_TRAP) or not (IK_NONE). */ + unsigned int *pending_int; + + /* Name for each interrupt source */ + char **int_name; + + /* Number of active IRQ lines. */ + int nirq; + + /* Tick when the IRQ was triggered. */ + CLOCK irq_clk; + + /* Number of active NMI lines. */ + int nnmi; + + /* Tick when the NMI was triggered. */ + CLOCK nmi_clk; + + /* If an opcode is intercepted by a DMA, save the number of cycles + left at the start of this particular DMA (needed by *_set_irq() to + calculate irq_clk). */ + unsigned int num_dma_per_opcode; + unsigned int num_cycles_left[INTRRUPT_MAX_DMA_PER_OPCODE]; + CLOCK dma_start_clk[INTRRUPT_MAX_DMA_PER_OPCODE]; + + /* If 1, do a RESET. */ + int reset; + + /* If 1, call the trapping function. */ + int trap; + + /* Debugging function. */ + void (*trap_func)(WORD, void *data); + + /* Data to pass to the debugging function when called. */ + void *trap_data; + + /* Pointer to the last executed opcode information. */ + unsigned int *last_opcode_info_ptr; + + /* Number of cycles we have stolen to the processor last time. */ + int num_last_stolen_cycles; + + /* Clock tick at which these cycles have been stolen. */ + CLOCK last_stolen_cycles_clk; + + unsigned int global_pending_int; + + void (*nmi_trap_func)(void); + + void (*reset_trap_func)(void); + + /* flag for interrupt_restore to handle CPU snapshots before 1.1 */ + int needs_global_restore; +}; +typedef struct interrupt_cpu_status_s interrupt_cpu_status_t; + +/* ------------------------------------------------------------------------- */ + +extern void interrupt_log_wrong_nirq(void); +extern void interrupt_log_wrong_nnmi(void); + +extern void interrupt_trigger_dma(interrupt_cpu_status_t *cs, CLOCK cpu_clk); +extern void interrupt_ack_dma(interrupt_cpu_status_t *cs); +extern void interrupt_fixup_int_clk(interrupt_cpu_status_t *cs, CLOCK cpu_clk, + CLOCK *int_clk); + +#if 0 // TC + +/* Set the IRQ line state. */ +inline static void interrupt_set_irq(interrupt_cpu_status_t *cs, + unsigned int int_num, + int value, CLOCK cpu_clk) +{ + if (cs == NULL || int_num >= cs->num_ints) + return; + + if (value) { /* Trigger the IRQ. */ + if (!(cs->pending_int[int_num] & IK_IRQ)) { + cs->nirq++; + cs->global_pending_int = (cs->global_pending_int + | (unsigned int)(IK_IRQ | IK_IRQPEND)); + cs->pending_int[int_num] = (cs->pending_int[int_num] + | (unsigned int)IK_IRQ); + + /* This makes sure that IRQ delay is correctly emulated when + cycles are stolen from the CPU. */ + + /*log_debug("ICLK %i", cpu_clk);*/ + + if (cs->last_stolen_cycles_clk <= cpu_clk) + cs->irq_clk = cpu_clk; + else + interrupt_fixup_int_clk(cs, cpu_clk, &(cs->irq_clk)); + } + } else { /* Remove the IRQ condition. */ + if (cs->pending_int[int_num] & IK_IRQ) { + if (cs->nirq > 0) { + cs->pending_int[int_num] = + (cs->pending_int[int_num] & (unsigned int)~IK_IRQ); + if (--cs->nirq == 0) + cs->global_pending_int = + (cs->global_pending_int & (unsigned int)~IK_IRQ); + } else { + interrupt_log_wrong_nirq(); + } + } + } +} + +/* Set the NMI line state. */ +inline static void interrupt_set_nmi(interrupt_cpu_status_t *cs, + unsigned int int_num, + int value, CLOCK cpu_clk) +{ + if (cs == NULL || int_num >= cs->num_ints) + return; + + if (value) { /* Trigger the NMI. */ + if (!(cs->pending_int[int_num] & IK_NMI)) { + if (cs->nnmi == 0 && !(cs->global_pending_int & IK_NMI)) { + cs->global_pending_int = (cs->global_pending_int | IK_NMI); + + /* This makes sure that NMI delay is correctly emulated when + cycles are stolen from the CPU. */ + if (cs->last_stolen_cycles_clk <= cpu_clk) + cs->nmi_clk = cpu_clk; + else + interrupt_fixup_int_clk(cs, cpu_clk, &(cs->nmi_clk)); + } + cs->nnmi++; + cs->pending_int[int_num] = (cs->pending_int[int_num] | IK_NMI); + } + } else { /* Remove the NMI condition. */ + if (cs->pending_int[int_num] & IK_NMI) { + if (cs->nnmi > 0) { + cs->nnmi--; + cs->pending_int[int_num] = + (cs->pending_int[int_num] & ~IK_NMI); +#if 0 + /* It should not be possible to remove the NMI condition, + only interrupt_ack_nmi() should clear it. */ + if (cpu_clk == cs->nmi_clk) + cs->global_pending_int = (enum cpu_int) + (cs->global_pending_int & ~IK_NMI); +#endif + } else { + interrupt_log_wrong_nnmi(); + } + } + } +} + +/* Change the interrupt line state: this can be used to change both NMI + and IRQ lines. It is slower than `interrupt_set_nmi()' and + `interrupt_set_irq()', but is left for backward compatibility (it works + like the old `setirq()'). */ +inline static void interrupt_set_int(interrupt_cpu_status_t *cs, int int_num, + enum cpu_int value, CLOCK cpu_clk) +{ + interrupt_set_nmi(cs, int_num, (int)(value & IK_NMI), cpu_clk); + interrupt_set_irq(cs, int_num, (int)(value & IK_IRQ), cpu_clk); +} + +/* ------------------------------------------------------------------------- */ + +/* This function must be called by the CPU emulator when a pending NMI/IRQ + request is served. */ +inline static void interrupt_ack_nmi(interrupt_cpu_status_t *cs) +{ + cs->global_pending_int = + (cs->global_pending_int & ~IK_NMI); + + if (cs->nmi_trap_func) + cs->nmi_trap_func(); +} + +inline static void interrupt_ack_irq(interrupt_cpu_status_t *cs) +{ + cs->global_pending_int = + (cs->global_pending_int & ~IK_IRQPEND); +} + +#endif + +/* ------------------------------------------------------------------------- */ + +/* Extern functions. These are defined in `interrupt.c'. */ + +struct snapshot_module_s; + +extern interrupt_cpu_status_t *interrupt_cpu_status_new(void); +extern void interrupt_cpu_status_destroy(interrupt_cpu_status_t *cs); +extern void interrupt_cpu_status_init(interrupt_cpu_status_t *cs, + unsigned int *last_opcode_info_ptr); +extern void interrupt_cpu_status_reset(interrupt_cpu_status_t *cs); + +extern void interrupt_trigger_reset(interrupt_cpu_status_t *cs, CLOCK cpu_clk); +extern unsigned int interrupt_cpu_status_int_new(interrupt_cpu_status_t *cs, + const char *name); +extern void interrupt_ack_reset(interrupt_cpu_status_t *cs); +extern void interrupt_set_reset_trap_func(interrupt_cpu_status_t *cs, + void (*reset_trap_func)(void)); +extern void interrupt_maincpu_trigger_trap(void (*trap_func)(WORD, + void *data), void *data); +extern void interrupt_do_trap(interrupt_cpu_status_t *cs, WORD address); + +extern void interrupt_monitor_trap_on(interrupt_cpu_status_t *cs); +extern void interrupt_monitor_trap_off(interrupt_cpu_status_t *cs); + +extern void interrupt_cpu_status_time_warp(interrupt_cpu_status_t *cs, + CLOCK warp_amount, + int warp_direction); + +extern int interrupt_read_snapshot(interrupt_cpu_status_t *cs, + struct snapshot_module_s *m); +extern int interrupt_read_new_snapshot(interrupt_cpu_status_t *cs, + struct snapshot_module_s *m); +extern int interrupt_write_snapshot(interrupt_cpu_status_t *cs, + struct snapshot_module_s *m); +extern int interrupt_write_new_snapshot(interrupt_cpu_status_t *cs, + struct snapshot_module_s *m); + +extern void interrupt_restore_irq(interrupt_cpu_status_t *cs, int int_num, + int value); +extern void interrupt_restore_nmi(interrupt_cpu_status_t *cs, int int_num, + int value); +extern int interrupt_get_irq(interrupt_cpu_status_t *cs, int int_num); +extern int interrupt_get_nmi(interrupt_cpu_status_t *cs, int int_num); +extern void interrupt_set_nmi_trap_func(interrupt_cpu_status_t *cs, + void (*nmi_trap_func)(void)); + +/* ------------------------------------------------------------------------- */ + +extern interrupt_cpu_status_t *maincpu_int_status; +extern CLOCK maincpu_clk; +extern CLOCK drive_clk[2]; + +/* For convenience... */ + +#define maincpu_set_irq(int_num, value) \ + interrupt_set_irq(maincpu_int_status, (int_num), (value), maincpu_clk) +#define maincpu_set_irq_clk(int_num, value, clk) \ + interrupt_set_irq(maincpu_int_status, (int_num), (value), (clk)) +#define maincpu_set_nmi(int_num, value) \ + interrupt_set_nmi(maincpu_int_status, (int_num), (value), maincpu_clk) +#define maincpu_set_nmi_clk(int_num, value, clk) \ + interrupt_set_nmi(maincpu_int_status, (int_num), (value), (clk)) +#define maincpu_set_int(int_num, value) \ + interrupt_set_int(maincpu_int_status, (int_num), (value), maincpu_clk) +#define maincpu_set_int_clk(int_num, value, clk) \ + interrupt_set_int(maincpu_int_status, (int_num), (value), (clk)) +#define maincpu_trigger_reset() \ + interrupt_trigger_reset(maincpu_int_status, maincpu_clk) + +#endif + diff --git a/AppleWin/source/CommonVICE/mem.h b/AppleWin/source/CommonVICE/mem.h new file mode 100644 index 00000000..26f1a4b9 --- /dev/null +++ b/AppleWin/source/CommonVICE/mem.h @@ -0,0 +1,95 @@ +/* + * mem.h - Memory interface. + * + * Written by + * André Fachat + * Ettore Perazzoli + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _MEM_H_ +#define _MEM_H_ + +#include "..\CommonVICE\types.h" + +typedef BYTE REGPARM1 read_func_t(WORD addr); +typedef read_func_t *read_func_ptr_t; +typedef void REGPARM2 store_func_t(WORD addr, BYTE value); +typedef store_func_t *store_func_ptr_t; + +extern read_func_ptr_t *_mem_read_tab_ptr; +extern store_func_ptr_t *_mem_write_tab_ptr; +extern BYTE **_mem_read_base_tab_ptr; +extern int *mem_read_limit_tab_ptr; + +extern BYTE mem_ram[]; +extern BYTE *mem_page_zero; +extern BYTE *mem_page_one; +extern BYTE *mem_color_ram_cpu; +extern BYTE *mem_color_ram_vicii; + +extern unsigned int mem_old_reg_pc; +extern BYTE *mem_chargen_rom_ptr; + +extern void mem_initialize_memory(void); +extern void mem_powerup(void); +extern int mem_load(void); +extern void mem_get_basic_text(WORD *start, WORD *end); +extern void mem_set_basic_text(WORD start, WORD end); +extern void mem_toggle_watchpoints(int flag, void *context); +extern int mem_rom_trap_allowed(WORD addr); +extern void mem_set_bank_pointer(BYTE **base, int *limit); +extern void mem_color_ram_to_snapshot(BYTE *color_ram); +extern void mem_color_ram_from_snapshot(BYTE *color_ram); + +extern read_func_t rom_read, rom_trap_read, zero_read; +extern store_func_t rom_store, rom_trap_store, zero_store; + +extern read_func_t mem_read; +extern store_func_t mem_store; + +/* ------------------------------------------------------------------------- */ + +/* Memory access functions for the monitor. */ +extern const char **mem_bank_list(void); +extern int mem_bank_from_name(const char *name); +extern BYTE mem_bank_read(int bank, WORD addr, void *context); +extern BYTE mem_bank_peek(int bank, WORD addr, void *context); +extern void mem_bank_write(int bank, WORD addr, BYTE byte, void *context); +extern void mem_get_screen_parameter(WORD *base, BYTE *rows, BYTE *columns, int *bank); + +typedef struct mem_ioreg_list_s { + const char *name; + WORD start; + WORD end; + unsigned int next; +} mem_ioreg_list_t; + +extern mem_ioreg_list_t *mem_ioreg_list_get(void *context); + +/* Snapshots. */ +struct snapshot_s; +extern int mem_write_snapshot_module(struct snapshot_s *s, int save_roms); +extern int mem_read_snapshot_module(struct snapshot_s *s); + +#endif + diff --git a/AppleWin/source/Tfe/Types.h b/AppleWin/source/CommonVICE/types.h similarity index 100% rename from AppleWin/source/Tfe/Types.h rename to AppleWin/source/CommonVICE/types.h diff --git a/AppleWin/source/Frame.cpp b/AppleWin/source/Frame.cpp index ee092a00..f80e79ee 100644 --- a/AppleWin/source/Frame.cpp +++ b/AppleWin/source/Frame.cpp @@ -772,7 +772,7 @@ LRESULT CALLBACK FrameWndProc ( VideoRedrawScreen(); g_bDebuggerViewingAppleOutput = true; // +PATCH } - SAVE(TEXT("Video Emulation"),videotype); + REGSAVE(TEXT("Video Emulation"),videotype); } else if ((wparam == VK_F11) && (GetKeyState(VK_CONTROL) >= 0)) // Save state (F11) diff --git a/AppleWin/source/Memory.cpp b/AppleWin/source/Memory.cpp index 0bcd6f07..fa901a90 100644 --- a/AppleWin/source/Memory.cpp +++ b/AppleWin/source/Memory.cpp @@ -30,8 +30,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #pragma hdrstop #include "MouseInterface.h" #ifdef SUPPORT_CPM -#include "z80\z80emu.h" -#include "z80\z80.h" +#include "z80emu.h" +#include "Z80VICE\z80.h" +#include "Z80VICE\z80mem.h" #endif #include "..\resource\resource.h" @@ -1060,7 +1061,7 @@ void MemInitialize() if (g_Slot4 == CT_MouseInterface) sg_Mouse.Initialize(pCxRomPeripheral, 4); // $C400 : Mouse f/w #ifdef SUPPORT_CPM - ConfigureSoftcard(pCxRomPeripheral, 5, g_uZ80InSlot5); // $C500 ; Z80 card + ConfigureSoftcard(pCxRomPeripheral, 5, g_uZ80InSlot5); // $C500 : Z80 card #endif DiskLoadRom(pCxRomPeripheral, 6); // $C600 : Disk][ f/w HD_Load_Rom(pCxRomPeripheral, 7); // $C700 : HDD f/w @@ -1115,7 +1116,7 @@ void MemReset () //Sets Caps Lock = false (Pravets 8A/C only) #ifdef SUPPORT_CPM - Z80_Reset(); + z80_reset(); #endif } diff --git a/AppleWin/source/Memory.h b/AppleWin/source/Memory.h index e26047c8..7fe46849 100644 --- a/AppleWin/source/Memory.h +++ b/AppleWin/source/Memory.h @@ -2,7 +2,7 @@ enum { - // Note: Alll are in bytes! + // Note: All are in bytes! APPLE_SLOT_SIZE = 0x0100, // 1 page = $Cx00 .. $CxFF (slot 1 .. 7) APPLE_SLOT_BEGIN = 0xC100, // each slot has 1 page reserved for it APPLE_SLOT_END = 0xC7FF, // diff --git a/AppleWin/source/Mockingboard.cpp b/AppleWin/source/Mockingboard.cpp index b5f87d20..a52848e1 100644 --- a/AppleWin/source/Mockingboard.cpp +++ b/AppleWin/source/Mockingboard.cpp @@ -81,7 +81,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #pragma hdrstop #include -#include "ay8910.h" +#include "AY8910.h" #include "SSI263Phonemes.h" @@ -144,7 +144,8 @@ static SY6522_AY8910 g_MB[NUM_AY8910]; // Timer vars static ULONG g_n6522TimerPeriod = 0; -static USHORT g_nMBTimerDevice = 0; // SY6522 device# which is generating timer IRQ +static const UINT TIMERDEVICE_INVALID = -1; +static UINT g_nMBTimerDevice = TIMERDEVICE_INVALID; // SY6522 device# which is generating timer IRQ static UINT64 g_uLastCumulativeCycles = 0; // SSI263 vars: @@ -159,7 +160,7 @@ static short* ppAYVoiceBuffer[NUM_VOICES] = {0}; static unsigned __int64 g_nMB_InActiveCycleCount = 0; static bool g_bMB_RegAccessedFlag = false; -static bool g_bMB_Active = true; +static bool g_bMB_Active = false; static HANDLE g_hThread = NULL; @@ -197,7 +198,9 @@ static const double g_f6522TimerPeriod_NoIRQ = CLK_6502 / 60.0; // Constant wha // External global vars: bool g_bMBTimerIrqActive = false; +#ifdef _DEBUG UINT32 g_uTimer1IrqCount = 0; // DEBUG +#endif //--------------------------------------------------------------------------- @@ -235,7 +238,7 @@ static void StopTimer(SY6522_AY8910* pMB) { pMB->nTimerStatus = 0; g_bMBTimerIrqActive = false; - g_nMBTimerDevice = 0; + g_nMBTimerDevice = TIMERDEVICE_INVALID; } //----------------------------------------------------------------------------- @@ -254,6 +257,7 @@ static void ResetSY6522(SY6522_AY8910* pMB) static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) { + g_bMB_RegAccessedFlag = true; SY6522_AY8910* pMB = &g_MB[nDevice]; if((nValue & 4) == 0) @@ -323,7 +327,6 @@ static void UpdateIFR(SY6522_AY8910* pMB) static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) { - g_bMB_RegAccessedFlag = true; g_bMB_Active = true; SY6522_AY8910* pMB = &g_MB[nDevice]; @@ -432,8 +435,6 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) if(pMB->nTimerStatus == 0) break; - pMB->nTimerStatus = 0; - // Stop timer StopTimer(pMB); } @@ -455,7 +456,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) { - g_bMB_RegAccessedFlag = true; +// g_bMB_RegAccessedFlag = true; g_bMB_Active = true; SY6522_AY8910* pMB = &g_MB[nDevice]; @@ -509,7 +510,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) nValue = pMB->sy6522.IFR; break; case 0x0e: // IER - nValue = 0x80; + nValue = 0x80; // Datasheet says this is 0x80|IER break; case 0x0f: // ORA_NO_HS nValue = pMB->sy6522.ORA; @@ -727,12 +728,28 @@ static void Votrax_Write(BYTE nDevice, BYTE nValue) static void MB_Update() { - if(!MockingboardVoice.bActive) + if (!MockingboardVoice.bActive) return; + if (g_bFullSpeed) + { + // Keep AY reg writes relative to the current 'frame' + // - Required for Ultima3: + // . Tune ends + // . g_bFullSpeed:=true (disk-spinning) for ~50 frames + // . U3 sets AY_ENABLE:=0xFF (as a side-effect, this sets g_bFullSpeed:=false) + // o Without this, the write to AY_ENABLE gets ignored (since AY8910's /g_uLastCumulativeCycles/ was last set 50 frame ago) + AY8910UpdateSetCycles(); + + // TODO: + // If any AY regs have changed then push them out to the AY chip + + return; + } + // - if(!g_bMB_RegAccessedFlag) + if (!g_bMB_RegAccessedFlag) { if(!g_nMB_InActiveCycleCount) { @@ -756,13 +773,11 @@ static void MB_Update() static DWORD dwByteOffset = (DWORD)-1; static int nNumSamplesError = 0; + const double n6522TimerPeriod = MB_GetFramePeriod(); - int nNumSamples; - double n6522TimerPeriod = MB_GetFramePeriod(); - - double nIrqFreq = g_fCurrentCLK6502 / n6522TimerPeriod + 0.5; // Round-up - int nNumSamplesPerPeriod = (int) ((double)SAMPLE_RATE / nIrqFreq); // Eg. For 60Hz this is 735 - nNumSamples = nNumSamplesPerPeriod + nNumSamplesError; // Apply correction + const double nIrqFreq = g_fCurrentCLK6502 / n6522TimerPeriod + 0.5; // Round-up + const int nNumSamplesPerPeriod = (int) ((double)SAMPLE_RATE / nIrqFreq); // Eg. For 60Hz this is 735 + int nNumSamples = nNumSamplesPerPeriod + nNumSamplesError; // Apply correction if(nNumSamples <= 0) nNumSamples = 0; if(nNumSamples > 2*nNumSamplesPerPeriod) @@ -823,7 +838,7 @@ static void MB_Update() // - double fAttenuation = g_bPhasorEnable ? 2.0/3.0 : 1.0; + const double fAttenuation = g_bPhasorEnable ? 2.0/3.0 : 1.0; for(int i=0; iUnlock((void*)pDSLockedBuffer0, dwDSLockedBufferSize0, - (void*)pDSLockedBuffer1, dwDSLockedBufferSize1); + (void*)pDSLockedBuffer1, dwDSLockedBufferSize1); dwByteOffset = (dwByteOffset + (DWORD)nNumSamples*sizeof(short)*g_nMB_NumChannels) % g_dwDSBufferSize; @@ -1361,6 +1376,7 @@ void MB_Reset() AY8910_reset(i); } + g_bMB_Active = (g_SoundcardType != SC_NONE); g_nPhasorMode = 0; MB_Reinitialize(); // Reset CLK for AY8910s } @@ -1529,15 +1545,13 @@ void MB_EndOfVideoFrame() if(g_SoundcardType == SC_NONE) return; - if(!g_bFullSpeed && !g_bMBTimerIrqActive && !(g_MB[0].sy6522.IFR & IxR_TIMER1)) + if(!g_bMBTimerIrqActive) MB_Update(); } //----------------------------------------------------------------------------- -// Called by InternalCpuExecute() after every N opcodes -// OLD: Called by InternalCpuExecute() after every opcode -// OLD: void MB_UpdateCycles(USHORT nClocks) +// Called by CpuExecute() after every N opcodes (N = ~1000 @ 1MHz) void MB_UpdateCycles(ULONG uExecutedCycles) { if(g_SoundcardType == SC_NONE) @@ -1565,7 +1579,9 @@ void MB_UpdateCycles(ULONG uExecutedCycles) if( bTimer1Underflow && (g_nMBTimerDevice == i) && g_bMBTimerIrqActive ) { +#ifdef _DEBUG g_uTimer1IrqCount++; // DEBUG +#endif pMB->sy6522.IFR |= IxR_TIMER1; UpdateIFR(pMB); @@ -1573,7 +1589,9 @@ void MB_UpdateCycles(ULONG uExecutedCycles) if((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) { // One-shot mode - StopTimer(pMB); // Phasor's playback code uses one-shot mode + // - Phasor's playback code uses one-shot mode + // - Willy Byte sets to one-shot to stop the timer IRQ + StopTimer(pMB); } else { @@ -1583,8 +1601,17 @@ void MB_UpdateCycles(ULONG uExecutedCycles) StartTimer(pMB); } - if(!g_bFullSpeed) - MB_Update(); + MB_Update(); + } + else if ( bTimer1Underflow + && !g_bMBTimerIrqActive // StopTimer() has been called + && (pMB->sy6522.IFR & IxR_TIMER1) // IRQ + && ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode + { + // Fix for Willy Byte - need to confirm that 6522 really does this! + // . It never accesses IER/IFR/TIMER1 regs to clear IRQ + pMB->sy6522.IFR &= ~IxR_TIMER1; // Deassert the TIMER IRQ + UpdateIFR(pMB); } } } diff --git a/AppleWin/source/Mockingboard.h b/AppleWin/source/Mockingboard.h index e1ff429a..d7377b17 100644 --- a/AppleWin/source/Mockingboard.h +++ b/AppleWin/source/Mockingboard.h @@ -1,7 +1,9 @@ #pragma once extern bool g_bMBTimerIrqActive; +#ifdef _DEBUG extern UINT32 g_uTimer1IrqCount; // DEBUG +#endif void MB_Initialize(); void MB_Reinitialize(); diff --git a/AppleWin/source/MouseInterface.cpp b/AppleWin/source/MouseInterface.cpp index a92e18a8..44bfec22 100644 --- a/AppleWin/source/MouseInterface.cpp +++ b/AppleWin/source/MouseInterface.cpp @@ -108,22 +108,18 @@ Etc. #define MODE_INT_ALL STAT_INT_ALL +//=========================================================================== -WRITE_HANDLER( M6821_Listener_B ) +void M6821_Listener_B( void* objTo, BYTE byData ) { ((CMouseInterface*)objTo)->On6821_B( byData ); } -WRITE_HANDLER( M6821_Listener_A ) +void M6821_Listener_A( void* objTo, BYTE byData ) { ((CMouseInterface*)objTo)->On6821_A( byData ); } -//CALLBACK_HANDLER( MouseHandler ) -//{ -// ((CMouseInterface*)objTo)->OnMouseEvent(); -//} - //=========================================================================== CMouseInterface::CMouseInterface() : @@ -131,7 +127,6 @@ CMouseInterface::CMouseInterface() : { m_6821.SetListenerB( this, M6821_Listener_B ); m_6821.SetListenerA( this, M6821_Listener_A ); -// g_cDIMouse.SetMouseListener( this, MouseHandler ); Uninitialize(); Reset(); diff --git a/AppleWin/source/MouseInterface.h b/AppleWin/source/MouseInterface.h index c5f8baa1..6c13a4f2 100644 --- a/AppleWin/source/MouseInterface.h +++ b/AppleWin/source/MouseInterface.h @@ -1,9 +1,6 @@ #include "6821.h" #include "Common.h" -#define WRITE_HANDLER(func) void func( void* objFrom, void* objTo, int nAddr, BYTE byData ) -#define CALLBACK_HANDLER(func) void func( void* objFrom, void* objTo, LPARAM lParam ) - extern class CMouseInterface sg_Mouse; class CMouseInterface @@ -49,9 +46,8 @@ protected: void OnMouseEvent(bool bEventVBL=false); void Clear(); - friend WRITE_HANDLER( M6821_Listener_A ); - friend WRITE_HANDLER( M6821_Listener_B ); - //friend CALLBACK_HANDLER( MouseHandler ); + friend void M6821_Listener_A( void* objTo, BYTE byData ); + friend void M6821_Listener_B( void* objTo, BYTE byData ); void SetPositionAbs(int x, int y); int ClampX(); diff --git a/AppleWin/source/PropertySheetPage.cpp b/AppleWin/source/PropertySheetPage.cpp index 0c6bd466..f38220c1 100644 --- a/AppleWin/source/PropertySheetPage.cpp +++ b/AppleWin/source/PropertySheetPage.cpp @@ -307,14 +307,14 @@ static void ConfigDlg_OK(HWND window, UINT afterclose) NewCloneType = NewApple2Type - A2TYPE_CLONE; if ((NewApple2Type == A2TYPE_PRAVETS82) || (NewApple2Type == A2TYPE_PRAVETS8A) || (NewApple2Type == A2TYPE_PRAVETS8M)) - SAVE(TEXT(REGVALUE_APPLE2_TYPE),A2TYPE_CLONE ); + REGSAVE(TEXT(REGVALUE_APPLE2_TYPE),A2TYPE_CLONE ); else - SAVE(TEXT(REGVALUE_APPLE2_TYPE),NewApple2Type ); + REGSAVE(TEXT(REGVALUE_APPLE2_TYPE),NewApple2Type ); - SAVE(TEXT("Serial Port") ,sg_SSC.GetSerialPort()); - SAVE(TEXT("Custom Speed") ,IsDlgButtonChecked(window,IDC_CUSTOM_SPEED)); - SAVE(TEXT("Emulation Speed") ,g_dwSpeed); - SAVE(TEXT("Video Emulation") ,videotype); + REGSAVE(TEXT("Serial Port") ,sg_SSC.GetSerialPort()); + REGSAVE(TEXT("Custom Speed") ,IsDlgButtonChecked(window,IDC_CUSTOM_SPEED)); + REGSAVE(TEXT("Emulation Speed") ,g_dwSpeed); + REGSAVE(TEXT("Video Emulation") ,videotype); // @@ -450,7 +450,7 @@ static BOOL CALLBACK ConfigDlgProc (HWND window, if (g_dwSpeed == SPEED_NORMAL) { custom = 0; - LOAD(TEXT("Custom Speed"),(DWORD *)&custom); + REGLOAD(TEXT("Custom Speed"),(DWORD *)&custom); } CheckRadioButton(window, IDC_AUTHENTIC_SPEED, IDC_CUSTOM_SPEED, custom ? IDC_CUSTOM_SPEED : IDC_AUTHENTIC_SPEED); SetFocus(GetDlgItem(window, custom ? IDC_SLIDER_CPU_SPEED : IDC_AUTHENTIC_SPEED)); @@ -512,15 +512,15 @@ static void InputDlg_OK(HWND window, UINT afterclose) g_uMouseShowCrosshair = IsDlgButtonChecked(window, IDC_MOUSE_CROSSHAIR) ? 1 : 0; g_uMouseRestrictToWindow = IsDlgButtonChecked(window, IDC_MOUSE_RESTRICT_TO_WINDOW) ? 1 : 0; - SAVE(TEXT("Joystick 0 Emulation"),joytype[0]); - SAVE(TEXT("Joystick 1 Emulation"),joytype[1]); - SAVE(TEXT(REGVALUE_PDL_XTRIM),JoyGetTrim(true)); - SAVE(TEXT(REGVALUE_PDL_YTRIM),JoyGetTrim(false)); - SAVE(TEXT(REGVALUE_SCROLLLOCK_TOGGLE),g_uScrollLockToggle); - SAVE(TEXT(REGVALUE_MOUSE_IN_SLOT4),g_uMouseInSlot4); - SAVE(TEXT(REGVALUE_MOUSE_CROSSHAIR),g_uMouseShowCrosshair); - SAVE(TEXT(REGVALUE_MOUSE_RESTRICT_TO_WINDOW),g_uMouseRestrictToWindow); - SAVE(TEXT(REGVALUE_Z80_IN_SLOT5),g_uZ80InSlot5); + REGSAVE(TEXT("Joystick 0 Emulation"),joytype[0]); + REGSAVE(TEXT("Joystick 1 Emulation"),joytype[1]); + REGSAVE(TEXT(REGVALUE_PDL_XTRIM),JoyGetTrim(true)); + REGSAVE(TEXT(REGVALUE_PDL_YTRIM),JoyGetTrim(false)); + REGSAVE(TEXT(REGVALUE_SCROLLLOCK_TOGGLE),g_uScrollLockToggle); + REGSAVE(TEXT(REGVALUE_MOUSE_IN_SLOT4),g_uMouseInSlot4); + REGSAVE(TEXT(REGVALUE_MOUSE_CROSSHAIR),g_uMouseShowCrosshair); + REGSAVE(TEXT(REGVALUE_MOUSE_RESTRICT_TO_WINDOW),g_uMouseRestrictToWindow); + REGSAVE(TEXT(REGVALUE_Z80_IN_SLOT5),g_uZ80InSlot5); // @@ -729,10 +729,10 @@ static void SoundDlg_OK(HWND window, UINT afterclose, UINT uNewSoundcardType) MB_SetSoundcardType((eSOUNDCARDTYPE)uNewSoundcardType); - SAVE(TEXT("Sound Emulation") ,soundtype); - SAVE(TEXT(REGVALUE_SPKR_VOLUME),SpkrGetVolume()); - SAVE(TEXT(REGVALUE_MB_VOLUME),MB_GetVolume()); - SAVE(TEXT(REGVALUE_SOUNDCARD_TYPE),(DWORD)MB_GetSoundcardType()); + REGSAVE(TEXT("Sound Emulation") ,soundtype); + REGSAVE(TEXT(REGVALUE_SPKR_VOLUME),SpkrGetVolume()); + REGSAVE(TEXT(REGVALUE_MB_VOLUME),MB_GetVolume()); + REGSAVE(TEXT(REGVALUE_SOUNDCARD_TYPE),(DWORD)MB_GetSoundcardType()); // @@ -879,8 +879,8 @@ static void DiskDlg_OK(HWND window, UINT afterclose) bool bHDDIsEnabled = IsDlgButtonChecked(window, IDC_HDD_ENABLE) ? true : false; HD_SetEnabled(bHDDIsEnabled); - SAVE(TEXT("Enhance Disk Speed"),newdisktype); - SAVE(TEXT(REGVALUE_HDD_ENABLED), bHDDIsEnabled ? 1 : 0); + REGSAVE(TEXT("Enhance Disk Speed"),newdisktype); + REGSAVE(TEXT(REGVALUE_HDD_ENABLED), bHDDIsEnabled ? 1 : 0); RegSaveString(TEXT("Configuration"), TEXT(REGVALUE_HDD_IMAGE1), 1, HD_GetFullName(0)); RegSaveString(TEXT("Configuration"), TEXT(REGVALUE_HDD_IMAGE2), 1, HD_GetFullName(1)); @@ -1115,27 +1115,29 @@ static void AdvancedDlg_OK(HWND window, UINT afterclose) // PrinterStateUpdate(); g_bSaveStateOnExit = IsDlgButtonChecked(window, IDC_SAVESTATE_ON_EXIT) ? true : false; + REGSAVE(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), g_bSaveStateOnExit ? 1 : 0); - SAVE(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), g_bSaveStateOnExit ? 1 : 0); g_bDumpToPrinter = IsDlgButtonChecked(window, IDC_DUMPTOPRINTER ) ? true : false; - SAVE(TEXT(REGVALUE_DUMP_TO_PRINTER), g_bDumpToPrinter ? 1 : 0); + REGSAVE(TEXT(REGVALUE_DUMP_TO_PRINTER), g_bDumpToPrinter ? 1 : 0); + g_bConvertEncoding = IsDlgButtonChecked(window, IDC_PRINTER_CONVERT_ENCODING ) ? true : false; - SAVE(TEXT(REGVALUE_CONVERT_ENCODING), g_bConvertEncoding ? 1 : 0); + REGSAVE(TEXT(REGVALUE_CONVERT_ENCODING), g_bConvertEncoding ? 1 : 0); g_bFilterUnprintable = IsDlgButtonChecked(window, IDC_PRINTER_FILTER_UNPRINTABLE ) ? true : false; - SAVE(TEXT(REGVALUE_FILTER_UNPRINTABLE), g_bFilterUnprintable ? 1 : 0); + REGSAVE(TEXT(REGVALUE_FILTER_UNPRINTABLE), g_bFilterUnprintable ? 1 : 0); g_bPrinterAppend = IsDlgButtonChecked(window, IDC_PRINTER_APPEND) ? true : false; - SAVE(TEXT(REGVALUE_PRINTER_APPEND), g_bPrinterAppend ? 1 : 0); + REGSAVE(TEXT(REGVALUE_PRINTER_APPEND), g_bPrinterAppend ? 1 : 0); + // DWORD NewCloneType = (DWORD)SendDlgItemMessage(window, IDC_CLONETYPE, CB_GETCURSEL, 0, 0); - SAVE(TEXT(REGVALUE_CLONETYPE), NewCloneType); - SAVE(TEXT(REGVALUE_THE_FREEZES_F8_ROM),g_uTheFreezesF8Rom); // NB. Can also be disabled on Config page (when Apple2Type changes) + REGSAVE(TEXT(REGVALUE_CLONETYPE), NewCloneType); + REGSAVE(TEXT(REGVALUE_THE_FREEZES_F8_ROM),g_uTheFreezesF8Rom); // NB. Can also be disabled on Config page (when Apple2Type changes) Printer_SetIdleLimit((short)SendDlgItemMessage(window, IDC_SPIN_PRINTER_IDLE , UDM_GETPOS, 0, 0)); - SAVE(TEXT(REGVALUE_PRINTER_IDLE_LIMIT),Printer_GetIdleLimit()); + REGSAVE(TEXT(REGVALUE_PRINTER_IDLE_LIMIT),Printer_GetIdleLimit()); eApple2Type NewApple2Clone = GetApple2Type(4, NewCloneType); @@ -1341,7 +1343,7 @@ static int gray_ungray_items(HWND hwnd) int disabled = 0; //resources_get_value("ETHERNET_DISABLED", (void *)&disabled); - LOAD(TEXT("Uthernet Disabled") ,(DWORD *)&disabled); + REGLOAD(TEXT("Uthernet Disabled") ,(DWORD *)&disabled); get_disabled_state(&disabled); if (disabled) { @@ -1496,9 +1498,9 @@ static void save_tfe_dialog(HWND hwnd) CB_GETCURSEL, 0, 0); tfe_enabled = active_value >= 1 ? 1 : 0; - SAVE(TEXT("Uthernet Active") ,tfe_enabled); + REGSAVE(TEXT("Uthernet Active") ,tfe_enabled); } else { - SAVE(TEXT("Uthernet Active") ,0); + REGSAVE(TEXT("Uthernet Active") ,0); } diff --git a/AppleWin/source/StdAfx.h b/AppleWin/source/StdAfx.h index e6670fc2..87c60b99 100644 --- a/AppleWin/source/StdAfx.h +++ b/AppleWin/source/StdAfx.h @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/AppleWin/source/Tfe/Tfe.h b/AppleWin/source/Tfe/Tfe.h index e3f408e6..923cd0ce 100644 --- a/AppleWin/source/Tfe/Tfe.h +++ b/AppleWin/source/Tfe/Tfe.h @@ -27,7 +27,7 @@ #ifndef _TFE_H #define _TFE_H -#include "types.h" +#include "..\CommonVICE\types.h" #include /* define this only if VICE should write each and every frame received diff --git a/AppleWin/source/Tfe/Tfearch.h b/AppleWin/source/Tfe/Tfearch.h index 13e625ab..a852f1aa 100644 --- a/AppleWin/source/Tfe/Tfearch.h +++ b/AppleWin/source/Tfe/Tfearch.h @@ -28,7 +28,7 @@ #ifndef _TFEARCH_H #define _TFEARCH_H -#include "types.h" +#include "..\CommonVICE\types.h" extern int tfe_arch_init(void); extern void tfe_arch_pre_reset(void); diff --git a/AppleWin/source/Video.cpp b/AppleWin/source/Video.cpp index ca8d7a57..8afaa3c9 100644 --- a/AppleWin/source/Video.cpp +++ b/AppleWin/source/Video.cpp @@ -1780,7 +1780,7 @@ void VideoChooseColor () { VideoReinitialize(); if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG)) VideoRedrawScreen(); - SAVE(TEXT("Monochrome Color"),monochrome); + REGSAVE(TEXT("Monochrome Color"),monochrome); } } diff --git a/AppleWin/source/Z80/README.txt b/AppleWin/source/Z80/README.txt deleted file mode 100644 index 0a7894cd..00000000 --- a/AppleWin/source/Z80/README.txt +++ /dev/null @@ -1,35 +0,0 @@ - ******* Z80Em ******* - Portable Zilog Z80 Emulator - Version 1.2 (04-09-1997) - - Copyright (C) Marcel de Kogel 1996,1997 - - -This package contains a portable Z80 emulator. It includes two engines: One -written in pure C, which can be used on just about every 32+ bit system, and -one optimised for GCC/x86 (DJGPP, Linux, FreeBSD). It can be used to emulate -systems with multiple Z80s and systems with several different CPUs -You can use in your own applications, as long as proper credit is given, -no profit is made and I am notified. If you want to use this code for -commercial purposes, e.g. using it in commercial projects, selling it, etc., -please contact me - -To use the code, check the system dependent part of Z80.h, write your own -memory and I/O functions, which are declared in Z80IO.h, write your own -Interrupt(), Z80_Patch(), Z80_Reti() and Z80_Retn() functions, initialise -the Z80_IPeriod and Z80_IRQ variables, call Z80_Reset() to reset all registers -to their initial values or call Z80_SetRegs() to set all of them to pre-loaded -ones, and finally call Z80() or repeatedly call Z80_Execute(), the latter -option should be used in multi-processor emulations - -For updates and examples on how to use this engine, check my homepage at -http://www.komkon.org/~dekogel/ - -History -------- -1.2 04-09-97 Fixed some more bugs -1.1 13-02-97 Fixed several bugs and compatibility problems -1.0 31-01-97 Initial release - -Please send your comments and bug reports to -m.dekogel@student.utwente.nl diff --git a/AppleWin/source/Z80/z80.cpp b/AppleWin/source/Z80/z80.cpp deleted file mode 100644 index 42e0d552..00000000 --- a/AppleWin/source/Z80/z80.cpp +++ /dev/null @@ -1,2691 +0,0 @@ -/*** Z80Em: Portable Z80 emulator *******************************************/ -/*** ***/ -/*** Z80.c ***/ -/*** ***/ -/*** This file contains the emulation code ***/ -/*** ***/ -/*** Copyright (C) Marcel de Kogel 1996,1997 ***/ -/*** You are not allowed to distribute this software commercially ***/ -/*** Please, notify me, if you make any changes to this file ***/ -/****************************************************************************/ - -#include "..\stdafx.h" -#include "Z80.h" - -#define M_RDMEM(A) Z80_RDMEM(A) -#define M_WRMEM(A,V) Z80_WRMEM(A,V) -#define M_RDOP(A) Z80_RDOP(A) -#define M_RDOP_ARG(A) Z80_RDOP_ARG(A) -#define M_RDSTACK(A) Z80_RDSTACK(A) -#define M_WRSTACK(A,V) Z80_WRSTACK(A,V) - -#define DoIn(lo,hi) Z80_In((lo)+(((unsigned)(hi))<<8)) -#define DoOut(lo,hi,v) Z80_Out((lo)+(((unsigned)(hi))<<8),v) - -static void Interrupt(int j); -static void ei(void); - -#define S_FLAG 0x80 -#define Z_FLAG 0x40 -#define H_FLAG 0x10 -#define V_FLAG 0x04 -#define N_FLAG 0x02 -#define C_FLAG 0x01 - -#define M_SKIP_CALL R.PC.W.l+=2 -#define M_SKIP_JP R.PC.W.l+=2 -#define M_SKIP_JR R.PC.W.l+=1 -#define M_SKIP_RET - -static Z80_Regs R; -//int Z80_Running=1; // [AppleWin] Not used -//int Z80_IPeriod=50000; // [AppleWin] Not used -int Z80_ICount=0; // [AppleWin] Modified from 50000 to 0 -#ifdef DEBUG -int Z80_Trace=0; -int Z80_Trap=-1; -#endif -#ifdef TRACE -static unsigned pc_trace[256]; -static unsigned pc_count=0; -#endif - -static byte PTable[512]; -static byte ZSTable[512]; -static byte ZSPTable[512]; -#include "Z80DAA.h" - -typedef void (*opcode_fn) (void); - -#define M_C (R.AF.B.l&C_FLAG) -#define M_NC (!M_C) -#define M_Z (R.AF.B.l&Z_FLAG) -#define M_NZ (!M_Z) -#define M_M (R.AF.B.l&S_FLAG) -#define M_P (!M_M) -#define M_PE (R.AF.B.l&V_FLAG) -#define M_PO (!M_PE) - -/* Get next opcode argument and increment program counter */ -INLINE unsigned M_RDMEM_OPCODE (void) -{ - unsigned retval; - retval=M_RDOP_ARG(R.PC.D); - R.PC.W.l++; - return retval; -} - -INLINE unsigned M_RDMEM_WORD (dword A) -{ - int i; - i=M_RDMEM(A); - i+=M_RDMEM(((A)+1)&0xFFFF)<<8; - return i; -} - -INLINE void M_WRMEM_WORD (dword A,word V) -{ - M_WRMEM (A,V&255); - M_WRMEM (((A)+1)&0xFFFF,V>>8); -} - -INLINE unsigned M_RDMEM_OPCODE_WORD (void) -{ - int i; - i=M_RDMEM_OPCODE(); - i+=M_RDMEM_OPCODE()<<8; - return i; -} - -#define M_XIX ((R.IX.D+(offset)M_RDMEM_OPCODE())&0xFFFF) -#define M_XIY ((R.IY.D+(offset)M_RDMEM_OPCODE())&0xFFFF) -#define M_RD_XHL M_RDMEM(R.HL.D) -INLINE unsigned M_RD_XIX(void) -{ - int i; - i=M_XIX; - return M_RDMEM(i); -} -INLINE unsigned M_RD_XIY(void) -{ - int i; - i=M_XIY; - return M_RDMEM(i); -} -INLINE void M_WR_XIX(byte a) -{ - int i; - i=M_XIX; - M_WRMEM(i,a); -} -INLINE void M_WR_XIY(byte a) -{ - int i; - i=M_XIY; - M_WRMEM(i,a); -} - -#ifdef X86_ASM -#include "Z80CDx86.h" -#else -#include "Z80Codes.h" -#endif - -static void adc_a_xhl(void) { byte i=M_RD_XHL; M_ADC(i); } -static void adc_a_xix(void) { byte i=M_RD_XIX(); M_ADC(i); } -static void adc_a_xiy(void) { byte i=M_RD_XIY(); M_ADC(i); } -static void adc_a_a(void) { M_ADC(R.AF.B.h); } -static void adc_a_b(void) { M_ADC(R.BC.B.h); } -static void adc_a_c(void) { M_ADC(R.BC.B.l); } -static void adc_a_d(void) { M_ADC(R.DE.B.h); } -static void adc_a_e(void) { M_ADC(R.DE.B.l); } -static void adc_a_h(void) { M_ADC(R.HL.B.h); } -static void adc_a_l(void) { M_ADC(R.HL.B.l); } -static void adc_a_ixl(void) { M_ADC(R.IX.B.l); } -static void adc_a_ixh(void) { M_ADC(R.IX.B.h); } -static void adc_a_iyl(void) { M_ADC(R.IY.B.l); } -static void adc_a_iyh(void) { M_ADC(R.IY.B.h); } -static void adc_a_byte(void) { byte i=M_RDMEM_OPCODE(); M_ADC(i); } - -static void adc_hl_bc(void) { M_ADCW(BC); } -static void adc_hl_de(void) { M_ADCW(DE); } -static void adc_hl_hl(void) { M_ADCW(HL); } -static void adc_hl_sp(void) { M_ADCW(SP); } - -static void add_a_xhl(void) { byte i=M_RD_XHL; M_ADD(i); } -static void add_a_xix(void) { byte i=M_RD_XIX(); M_ADD(i); } -static void add_a_xiy(void) { byte i=M_RD_XIY(); M_ADD(i); } -static void add_a_a(void) { M_ADD(R.AF.B.h); } -static void add_a_b(void) { M_ADD(R.BC.B.h); } -static void add_a_c(void) { M_ADD(R.BC.B.l); } -static void add_a_d(void) { M_ADD(R.DE.B.h); } -static void add_a_e(void) { M_ADD(R.DE.B.l); } -static void add_a_h(void) { M_ADD(R.HL.B.h); } -static void add_a_l(void) { M_ADD(R.HL.B.l); } -static void add_a_ixl(void) { M_ADD(R.IX.B.l); } -static void add_a_ixh(void) { M_ADD(R.IX.B.h); } -static void add_a_iyl(void) { M_ADD(R.IY.B.l); } -static void add_a_iyh(void) { M_ADD(R.IY.B.h); } -static void add_a_byte(void) { byte i=M_RDMEM_OPCODE(); M_ADD(i); } - -static void add_hl_bc(void) { M_ADDW(HL,BC); } -static void add_hl_de(void) { M_ADDW(HL,DE); } -static void add_hl_hl(void) { M_ADDW(HL,HL); } -static void add_hl_sp(void) { M_ADDW(HL,SP); } -static void add_ix_bc(void) { M_ADDW(IX,BC); } -static void add_ix_de(void) { M_ADDW(IX,DE); } -static void add_ix_ix(void) { M_ADDW(IX,IX); } -static void add_ix_sp(void) { M_ADDW(IX,SP); } -static void add_iy_bc(void) { M_ADDW(IY,BC); } -static void add_iy_de(void) { M_ADDW(IY,DE); } -static void add_iy_iy(void) { M_ADDW(IY,IY); } -static void add_iy_sp(void) { M_ADDW(IY,SP); } - -static void and_xhl(void) { byte i=M_RD_XHL; M_AND(i); } -static void and_xix(void) { byte i=M_RD_XIX(); M_AND(i); } -static void and_xiy(void) { byte i=M_RD_XIY(); M_AND(i); } -static void and_a(void) { R.AF.B.l=ZSPTable[R.AF.B.h]|H_FLAG; } -static void and_b(void) { M_AND(R.BC.B.h); } -static void and_c(void) { M_AND(R.BC.B.l); } -static void and_d(void) { M_AND(R.DE.B.h); } -static void and_e(void) { M_AND(R.DE.B.l); } -static void and_h(void) { M_AND(R.HL.B.h); } -static void and_l(void) { M_AND(R.HL.B.l); } -static void and_ixh(void) { M_AND(R.IX.B.h); } -static void and_ixl(void) { M_AND(R.IX.B.l); } -static void and_iyh(void) { M_AND(R.IY.B.h); } -static void and_iyl(void) { M_AND(R.IY.B.l); } -static void and_byte(void) { byte i=M_RDMEM_OPCODE(); M_AND(i); } - -static void bit_0_xhl(void) { byte i=M_RD_XHL; M_BIT(0,i); } -static void bit_0_xix(void) { byte i=M_RD_XIX(); M_BIT(0,i); } -static void bit_0_xiy(void) { byte i=M_RD_XIY(); M_BIT(0,i); } -static void bit_0_a(void) { M_BIT(0,R.AF.B.h); } -static void bit_0_b(void) { M_BIT(0,R.BC.B.h); } -static void bit_0_c(void) { M_BIT(0,R.BC.B.l); } -static void bit_0_d(void) { M_BIT(0,R.DE.B.h); } -static void bit_0_e(void) { M_BIT(0,R.DE.B.l); } -static void bit_0_h(void) { M_BIT(0,R.HL.B.h); } -static void bit_0_l(void) { M_BIT(0,R.HL.B.l); } - -static void bit_1_xhl(void) { byte i=M_RD_XHL; M_BIT(1,i); } -static void bit_1_xix(void) { byte i=M_RD_XIX(); M_BIT(1,i); } -static void bit_1_xiy(void) { byte i=M_RD_XIY(); M_BIT(1,i); } -static void bit_1_a(void) { M_BIT(1,R.AF.B.h); } -static void bit_1_b(void) { M_BIT(1,R.BC.B.h); } -static void bit_1_c(void) { M_BIT(1,R.BC.B.l); } -static void bit_1_d(void) { M_BIT(1,R.DE.B.h); } -static void bit_1_e(void) { M_BIT(1,R.DE.B.l); } -static void bit_1_h(void) { M_BIT(1,R.HL.B.h); } -static void bit_1_l(void) { M_BIT(1,R.HL.B.l); } - -static void bit_2_xhl(void) { byte i=M_RD_XHL; M_BIT(2,i); } -static void bit_2_xix(void) { byte i=M_RD_XIX(); M_BIT(2,i); } -static void bit_2_xiy(void) { byte i=M_RD_XIY(); M_BIT(2,i); } -static void bit_2_a(void) { M_BIT(2,R.AF.B.h); } -static void bit_2_b(void) { M_BIT(2,R.BC.B.h); } -static void bit_2_c(void) { M_BIT(2,R.BC.B.l); } -static void bit_2_d(void) { M_BIT(2,R.DE.B.h); } -static void bit_2_e(void) { M_BIT(2,R.DE.B.l); } -static void bit_2_h(void) { M_BIT(2,R.HL.B.h); } -static void bit_2_l(void) { M_BIT(2,R.HL.B.l); } - -static void bit_3_xhl(void) { byte i=M_RD_XHL; M_BIT(3,i); } -static void bit_3_xix(void) { byte i=M_RD_XIX(); M_BIT(3,i); } -static void bit_3_xiy(void) { byte i=M_RD_XIY(); M_BIT(3,i); } -static void bit_3_a(void) { M_BIT(3,R.AF.B.h); } -static void bit_3_b(void) { M_BIT(3,R.BC.B.h); } -static void bit_3_c(void) { M_BIT(3,R.BC.B.l); } -static void bit_3_d(void) { M_BIT(3,R.DE.B.h); } -static void bit_3_e(void) { M_BIT(3,R.DE.B.l); } -static void bit_3_h(void) { M_BIT(3,R.HL.B.h); } -static void bit_3_l(void) { M_BIT(3,R.HL.B.l); } - -static void bit_4_xhl(void) { byte i=M_RD_XHL; M_BIT(4,i); } -static void bit_4_xix(void) { byte i=M_RD_XIX(); M_BIT(4,i); } -static void bit_4_xiy(void) { byte i=M_RD_XIY(); M_BIT(4,i); } -static void bit_4_a(void) { M_BIT(4,R.AF.B.h); } -static void bit_4_b(void) { M_BIT(4,R.BC.B.h); } -static void bit_4_c(void) { M_BIT(4,R.BC.B.l); } -static void bit_4_d(void) { M_BIT(4,R.DE.B.h); } -static void bit_4_e(void) { M_BIT(4,R.DE.B.l); } -static void bit_4_h(void) { M_BIT(4,R.HL.B.h); } -static void bit_4_l(void) { M_BIT(4,R.HL.B.l); } - -static void bit_5_xhl(void) { byte i=M_RD_XHL; M_BIT(5,i); } -static void bit_5_xix(void) { byte i=M_RD_XIX(); M_BIT(5,i); } -static void bit_5_xiy(void) { byte i=M_RD_XIY(); M_BIT(5,i); } -static void bit_5_a(void) { M_BIT(5,R.AF.B.h); } -static void bit_5_b(void) { M_BIT(5,R.BC.B.h); } -static void bit_5_c(void) { M_BIT(5,R.BC.B.l); } -static void bit_5_d(void) { M_BIT(5,R.DE.B.h); } -static void bit_5_e(void) { M_BIT(5,R.DE.B.l); } -static void bit_5_h(void) { M_BIT(5,R.HL.B.h); } -static void bit_5_l(void) { M_BIT(5,R.HL.B.l); } - -static void bit_6_xhl(void) { byte i=M_RD_XHL; M_BIT(6,i); } -static void bit_6_xix(void) { byte i=M_RD_XIX(); M_BIT(6,i); } -static void bit_6_xiy(void) { byte i=M_RD_XIY(); M_BIT(6,i); } -static void bit_6_a(void) { M_BIT(6,R.AF.B.h); } -static void bit_6_b(void) { M_BIT(6,R.BC.B.h); } -static void bit_6_c(void) { M_BIT(6,R.BC.B.l); } -static void bit_6_d(void) { M_BIT(6,R.DE.B.h); } -static void bit_6_e(void) { M_BIT(6,R.DE.B.l); } -static void bit_6_h(void) { M_BIT(6,R.HL.B.h); } -static void bit_6_l(void) { M_BIT(6,R.HL.B.l); } - -static void bit_7_xhl(void) { byte i=M_RD_XHL; M_BIT(7,i); } -static void bit_7_xix(void) { byte i=M_RD_XIX(); M_BIT(7,i); } -static void bit_7_xiy(void) { byte i=M_RD_XIY(); M_BIT(7,i); } -static void bit_7_a(void) { M_BIT(7,R.AF.B.h); } -static void bit_7_b(void) { M_BIT(7,R.BC.B.h); } -static void bit_7_c(void) { M_BIT(7,R.BC.B.l); } -static void bit_7_d(void) { M_BIT(7,R.DE.B.h); } -static void bit_7_e(void) { M_BIT(7,R.DE.B.l); } -static void bit_7_h(void) { M_BIT(7,R.HL.B.h); } -static void bit_7_l(void) { M_BIT(7,R.HL.B.l); } - -static void call_c(void) { if (M_C) { M_CALL; } else { M_SKIP_CALL; } } -static void call_m(void) { if (M_M) { M_CALL; } else { M_SKIP_CALL; } } -static void call_nc(void) { if (M_NC) { M_CALL; } else { M_SKIP_CALL; } } -static void call_nz(void) { if (M_NZ) { M_CALL; } else { M_SKIP_CALL; } } -static void call_p(void) { if (M_P) { M_CALL; } else { M_SKIP_CALL; } } -static void call_pe(void) { if (M_PE) { M_CALL; } else { M_SKIP_CALL; } } -static void call_po(void) { if (M_PO) { M_CALL; } else { M_SKIP_CALL; } } -static void call_z(void) { if (M_Z) { M_CALL; } else { M_SKIP_CALL; } } -static void call(void) { M_CALL; } - -static void ccf(void) { R.AF.B.l=((R.AF.B.l&0xED)|((R.AF.B.l&1)<<4))^1; } - -static void cp_xhl(void) { byte i=M_RD_XHL; M_CP(i); } -static void cp_xix(void) { byte i=M_RD_XIX(); M_CP(i); } -static void cp_xiy(void) { byte i=M_RD_XIY(); M_CP(i); } -static void cp_a(void) { M_CP(R.AF.B.h); } -static void cp_b(void) { M_CP(R.BC.B.h); } -static void cp_c(void) { M_CP(R.BC.B.l); } -static void cp_d(void) { M_CP(R.DE.B.h); } -static void cp_e(void) { M_CP(R.DE.B.l); } -static void cp_h(void) { M_CP(R.HL.B.h); } -static void cp_l(void) { M_CP(R.HL.B.l); } -static void cp_ixh(void) { M_CP(R.IX.B.h); } -static void cp_ixl(void) { M_CP(R.IX.B.l); } -static void cp_iyh(void) { M_CP(R.IY.B.h); } -static void cp_iyl(void) { M_CP(R.IY.B.l); } -static void cp_byte(void) { byte i=M_RDMEM_OPCODE(); M_CP(i); } - -static void cpd(void) -{ - byte i,j; - i=M_RDMEM(R.HL.D); - j=R.AF.B.h-i; - --R.HL.W.l; - --R.BC.W.l; - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSTable[j]| - ((R.AF.B.h^i^j)&H_FLAG)|(R.BC.D? V_FLAG:0)|N_FLAG; -} - -static void cpdr(void) -{ - cpd (); - if (R.BC.D && !(R.AF.B.l&Z_FLAG)) { Z80_ICount += 5; R.PC.W.l-=2; } -} - -static void cpi(void) -{ - byte i,j; - i=M_RDMEM(R.HL.D); - j=R.AF.B.h-i; - ++R.HL.W.l; - --R.BC.W.l; - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSTable[j]| - ((R.AF.B.h^i^j)&H_FLAG)|(R.BC.D? V_FLAG:0)|N_FLAG; -} - -static void cpir(void) -{ - cpi (); - if (R.BC.D && !(R.AF.B.l&Z_FLAG)) { Z80_ICount += 5; R.PC.W.l-=2; } -} - -static void cpl(void) { R.AF.B.h^=0xFF; R.AF.B.l|=(H_FLAG|N_FLAG); } - -static void daa(void) -{ - int i; - i=R.AF.B.h; - if (R.AF.B.l&C_FLAG) i|=256; - if (R.AF.B.l&H_FLAG) i|=512; - if (R.AF.B.l&N_FLAG) i|=1024; - R.AF.W.l=DAATable[i]; -}; - -static void dec_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_DEC(i); - M_WRMEM(R.HL.D,i); -} -static void dec_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_DEC(i); - M_WRMEM(j,i); -} -static void dec_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_DEC(i); - M_WRMEM(j,i); -} -static void dec_a(void) { M_DEC(R.AF.B.h); } -static void dec_b(void) { M_DEC(R.BC.B.h); } -static void dec_c(void) { M_DEC(R.BC.B.l); } -static void dec_d(void) { M_DEC(R.DE.B.h); } -static void dec_e(void) { M_DEC(R.DE.B.l); } -static void dec_h(void) { M_DEC(R.HL.B.h); } -static void dec_l(void) { M_DEC(R.HL.B.l); } -static void dec_ixh(void) { M_DEC(R.IX.B.h); } -static void dec_ixl(void) { M_DEC(R.IX.B.l); } -static void dec_iyh(void) { M_DEC(R.IY.B.h); } -static void dec_iyl(void) { M_DEC(R.IY.B.l); } - -static void dec_bc(void) { --R.BC.W.l; } -static void dec_de(void) { --R.DE.W.l; } -static void dec_hl(void) { --R.HL.W.l; } -static void dec_ix(void) { --R.IX.W.l; } -static void dec_iy(void) { --R.IY.W.l; } -static void dec_sp(void) { --R.SP.W.l; } - -static void di(void) { R.IFF1=R.IFF2=0; } - -static void djnz(void) { if (--R.BC.B.h) { M_JR; } else { M_SKIP_JR; } } - -static void ex_xsp_hl(void) -{ - int i; - i=M_RDMEM_WORD(R.SP.D); - M_WRMEM_WORD(R.SP.D,R.HL.D); - R.HL.D=i; -} - -static void ex_xsp_ix(void) -{ - int i; - i=M_RDMEM_WORD(R.SP.D); - M_WRMEM_WORD(R.SP.D,R.IX.D); - R.IX.D=i; -} - -static void ex_xsp_iy(void) -{ - int i; - i=M_RDMEM_WORD(R.SP.D); - M_WRMEM_WORD(R.SP.D,R.IY.D); - R.IY.D=i; -} - -static void ex_af_af(void) -{ - int i; - i=R.AF.D; - R.AF.D=R.AF2.D; - R.AF2.D=i; -} - -static void ex_de_hl(void) -{ - int i; - i=R.DE.D; - R.DE.D=R.HL.D; - R.HL.D=i; -} - -static void exx(void) -{ - int i; - i=R.BC.D; - R.BC.D=R.BC2.D; - R.BC2.D=i; - i=R.DE.D; - R.DE.D=R.DE2.D; - R.DE2.D=i; - i=R.HL.D; - R.HL.D=R.HL2.D; - R.HL2.D=i; -} - -static void halt(void) -{ - --R.PC.W.l; - R.HALT=1; - //if (Z80_ICount>0) Z80_ICount=0; // [AppleWin] Commented out -} - -static void im_0(void) { R.IM=0; } -static void im_1(void) { R.IM=1; } -static void im_2(void) { R.IM=2; } - -static void in_a_c(void) { M_IN(R.AF.B.h); } -static void in_b_c(void) { M_IN(R.BC.B.h); } -static void in_c_c(void) { M_IN(R.BC.B.l); } -static void in_d_c(void) { M_IN(R.DE.B.h); } -static void in_e_c(void) { M_IN(R.DE.B.l); } -static void in_h_c(void) { M_IN(R.HL.B.h); } -static void in_l_c(void) { M_IN(R.HL.B.l); } -static void in_0_c(void) { byte i; M_IN(i); } - -static void in_a_byte(void) -{ - byte i=M_RDMEM_OPCODE(); - R.AF.B.h=DoIn(i,R.AF.B.h); -} - -static void inc_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_INC(i); - M_WRMEM(R.HL.D,i); -} -static void inc_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_INC(i); - M_WRMEM(j,i); -} -static void inc_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_INC(i); - M_WRMEM(j,i); -} -static void inc_a(void) { M_INC(R.AF.B.h); } -static void inc_b(void) { M_INC(R.BC.B.h); } -static void inc_c(void) { M_INC(R.BC.B.l); } -static void inc_d(void) { M_INC(R.DE.B.h); } -static void inc_e(void) { M_INC(R.DE.B.l); } -static void inc_h(void) { M_INC(R.HL.B.h); } -static void inc_l(void) { M_INC(R.HL.B.l); } -static void inc_ixh(void) { M_INC(R.IX.B.h); } -static void inc_ixl(void) { M_INC(R.IX.B.l); } -static void inc_iyh(void) { M_INC(R.IY.B.h); } -static void inc_iyl(void) { M_INC(R.IY.B.l); } - -static void inc_bc(void) { ++R.BC.W.l; } -static void inc_de(void) { ++R.DE.W.l; } -static void inc_hl(void) { ++R.HL.W.l; } -static void inc_ix(void) { ++R.IX.W.l; } -static void inc_iy(void) { ++R.IY.W.l; } -static void inc_sp(void) { ++R.SP.W.l; } - -static void ind(void) -{ - --R.BC.B.h; - M_WRMEM(R.HL.D,DoIn(R.BC.B.l,R.BC.B.h)); - --R.HL.W.l; - R.AF.B.l=(R.BC.B.h)? N_FLAG:(N_FLAG|Z_FLAG); -} - -static void indr(void) -{ - ind (); - if (R.BC.B.h) { Z80_ICount += 5; R.PC.W.l-=2; } -} - -static void ini(void) -{ - --R.BC.B.h; - M_WRMEM(R.HL.D,DoIn(R.BC.B.l,R.BC.B.h)); - ++R.HL.W.l; - R.AF.B.l=(R.BC.B.h)? N_FLAG:(N_FLAG|Z_FLAG); -} - -static void inir(void) -{ - ini (); - if (R.BC.B.h) { Z80_ICount+=5; R.PC.W.l-=2; } -} - -static void jp(void) { M_JP; } -static void jp_hl(void) { R.PC.D=R.HL.D; } -static void jp_ix(void) { R.PC.D=R.IX.D; } -static void jp_iy(void) { R.PC.D=R.IY.D; } -static void jp_c(void) { if (M_C) { M_JP; } else { M_SKIP_JP; } } -static void jp_m(void) { if (M_M) { M_JP; } else { M_SKIP_JP; } } -static void jp_nc(void) { if (M_NC) { M_JP; } else { M_SKIP_JP; } } -static void jp_nz(void) { if (M_NZ) { M_JP; } else { M_SKIP_JP; } } -static void jp_p(void) { if (M_P) { M_JP; } else { M_SKIP_JP; } } -static void jp_pe(void) { if (M_PE) { M_JP; } else { M_SKIP_JP; } } -static void jp_po(void) { if (M_PO) { M_JP; } else { M_SKIP_JP; } } -static void jp_z(void) { if (M_Z) { M_JP; } else { M_SKIP_JP; } } - -static void jr(void) { M_JR; } -static void jr_c(void) { if (M_C) { M_JR; } else { M_SKIP_JR; } } -static void jr_nc(void) { if (M_NC) { M_JR; } else { M_SKIP_JR; } } -static void jr_nz(void) { if (M_NZ) { M_JR; } else { M_SKIP_JR; } } -static void jr_z(void) { if (M_Z) { M_JR; } else { M_SKIP_JR; } } - -static void ld_xbc_a(void) { M_WRMEM(R.BC.D,R.AF.B.h); } -static void ld_xde_a(void) { M_WRMEM(R.DE.D,R.AF.B.h); } -static void ld_xhl_a(void) { M_WRMEM(R.HL.D,R.AF.B.h); } -static void ld_xhl_b(void) { M_WRMEM(R.HL.D,R.BC.B.h); } -static void ld_xhl_c(void) { M_WRMEM(R.HL.D,R.BC.B.l); } -static void ld_xhl_d(void) { M_WRMEM(R.HL.D,R.DE.B.h); } -static void ld_xhl_e(void) { M_WRMEM(R.HL.D,R.DE.B.l); } -static void ld_xhl_h(void) { M_WRMEM(R.HL.D,R.HL.B.h); } -static void ld_xhl_l(void) { M_WRMEM(R.HL.D,R.HL.B.l); } -static void ld_xhl_byte(void) { byte i=M_RDMEM_OPCODE(); M_WRMEM(R.HL.D,i); } -static void ld_xix_a(void) { M_WR_XIX(R.AF.B.h); } -static void ld_xix_b(void) { M_WR_XIX(R.BC.B.h); } -static void ld_xix_c(void) { M_WR_XIX(R.BC.B.l); } -static void ld_xix_d(void) { M_WR_XIX(R.DE.B.h); } -static void ld_xix_e(void) { M_WR_XIX(R.DE.B.l); } -static void ld_xix_h(void) { M_WR_XIX(R.HL.B.h); } -static void ld_xix_l(void) { M_WR_XIX(R.HL.B.l); } -static void ld_xix_byte(void) -{ - int i,j; - i=M_XIX; - j=M_RDMEM_OPCODE(); - M_WRMEM(i,j); -} -static void ld_xiy_a(void) { M_WR_XIY(R.AF.B.h); } -static void ld_xiy_b(void) { M_WR_XIY(R.BC.B.h); } -static void ld_xiy_c(void) { M_WR_XIY(R.BC.B.l); } -static void ld_xiy_d(void) { M_WR_XIY(R.DE.B.h); } -static void ld_xiy_e(void) { M_WR_XIY(R.DE.B.l); } -static void ld_xiy_h(void) { M_WR_XIY(R.HL.B.h); } -static void ld_xiy_l(void) { M_WR_XIY(R.HL.B.l); } -static void ld_xiy_byte(void) -{ - int i,j; - i=M_XIY; - j=M_RDMEM_OPCODE(); - M_WRMEM(i,j); -} -static void ld_xbyte_a(void) -{ int i=M_RDMEM_OPCODE_WORD(); M_WRMEM(i,R.AF.B.h); } -static void ld_xword_bc(void) { M_WRMEM_WORD(M_RDMEM_OPCODE_WORD(),R.BC.D); } -static void ld_xword_de(void) { M_WRMEM_WORD(M_RDMEM_OPCODE_WORD(),R.DE.D); } -static void ld_xword_hl(void) { M_WRMEM_WORD(M_RDMEM_OPCODE_WORD(),R.HL.D); } -static void ld_xword_ix(void) { M_WRMEM_WORD(M_RDMEM_OPCODE_WORD(),R.IX.D); } -static void ld_xword_iy(void) { M_WRMEM_WORD(M_RDMEM_OPCODE_WORD(),R.IY.D); } -static void ld_xword_sp(void) { M_WRMEM_WORD(M_RDMEM_OPCODE_WORD(),R.SP.D); } -static void ld_a_xbc(void) { R.AF.B.h=M_RDMEM(R.BC.D); } -static void ld_a_xde(void) { R.AF.B.h=M_RDMEM(R.DE.D); } -static void ld_a_xhl(void) { R.AF.B.h=M_RD_XHL; } -static void ld_a_xix(void) { R.AF.B.h=M_RD_XIX(); } -static void ld_a_xiy(void) { R.AF.B.h=M_RD_XIY(); } -static void ld_a_xbyte(void) -{ int i=M_RDMEM_OPCODE_WORD(); R.AF.B.h=M_RDMEM(i); } - -static void ld_a_byte(void) { R.AF.B.h=M_RDMEM_OPCODE(); } -static void ld_b_byte(void) { R.BC.B.h=M_RDMEM_OPCODE(); } -static void ld_c_byte(void) { R.BC.B.l=M_RDMEM_OPCODE(); } -static void ld_d_byte(void) { R.DE.B.h=M_RDMEM_OPCODE(); } -static void ld_e_byte(void) { R.DE.B.l=M_RDMEM_OPCODE(); } -static void ld_h_byte(void) { R.HL.B.h=M_RDMEM_OPCODE(); } -static void ld_l_byte(void) { R.HL.B.l=M_RDMEM_OPCODE(); } -static void ld_ixh_byte(void) { R.IX.B.h=M_RDMEM_OPCODE(); } -static void ld_ixl_byte(void) { R.IX.B.l=M_RDMEM_OPCODE(); } -static void ld_iyh_byte(void) { R.IY.B.h=M_RDMEM_OPCODE(); } -static void ld_iyl_byte(void) { R.IY.B.l=M_RDMEM_OPCODE(); } - -static void ld_b_xhl(void) { R.BC.B.h=M_RD_XHL; } -static void ld_c_xhl(void) { R.BC.B.l=M_RD_XHL; } -static void ld_d_xhl(void) { R.DE.B.h=M_RD_XHL; } -static void ld_e_xhl(void) { R.DE.B.l=M_RD_XHL; } -static void ld_h_xhl(void) { R.HL.B.h=M_RD_XHL; } -static void ld_l_xhl(void) { R.HL.B.l=M_RD_XHL; } -static void ld_b_xix(void) { R.BC.B.h=M_RD_XIX(); } -static void ld_c_xix(void) { R.BC.B.l=M_RD_XIX(); } -static void ld_d_xix(void) { R.DE.B.h=M_RD_XIX(); } -static void ld_e_xix(void) { R.DE.B.l=M_RD_XIX(); } -static void ld_h_xix(void) { R.HL.B.h=M_RD_XIX(); } -static void ld_l_xix(void) { R.HL.B.l=M_RD_XIX(); } -static void ld_b_xiy(void) { R.BC.B.h=M_RD_XIY(); } -static void ld_c_xiy(void) { R.BC.B.l=M_RD_XIY(); } -static void ld_d_xiy(void) { R.DE.B.h=M_RD_XIY(); } -static void ld_e_xiy(void) { R.DE.B.l=M_RD_XIY(); } -static void ld_h_xiy(void) { R.HL.B.h=M_RD_XIY(); } -static void ld_l_xiy(void) { R.HL.B.l=M_RD_XIY(); } -static void ld_a_a(void) { } -static void ld_a_b(void) { R.AF.B.h=R.BC.B.h; } -static void ld_a_c(void) { R.AF.B.h=R.BC.B.l; } -static void ld_a_d(void) { R.AF.B.h=R.DE.B.h; } -static void ld_a_e(void) { R.AF.B.h=R.DE.B.l; } -static void ld_a_h(void) { R.AF.B.h=R.HL.B.h; } -static void ld_a_l(void) { R.AF.B.h=R.HL.B.l; } -static void ld_a_ixh(void) { R.AF.B.h=R.IX.B.h; } -static void ld_a_ixl(void) { R.AF.B.h=R.IX.B.l; } -static void ld_a_iyh(void) { R.AF.B.h=R.IY.B.h; } -static void ld_a_iyl(void) { R.AF.B.h=R.IY.B.l; } -static void ld_b_b(void) { } -static void ld_b_a(void) { R.BC.B.h=R.AF.B.h; } -static void ld_b_c(void) { R.BC.B.h=R.BC.B.l; } -static void ld_b_d(void) { R.BC.B.h=R.DE.B.h; } -static void ld_b_e(void) { R.BC.B.h=R.DE.B.l; } -static void ld_b_h(void) { R.BC.B.h=R.HL.B.h; } -static void ld_b_l(void) { R.BC.B.h=R.HL.B.l; } -static void ld_b_ixh(void) { R.BC.B.h=R.IX.B.h; } -static void ld_b_ixl(void) { R.BC.B.h=R.IX.B.l; } -static void ld_b_iyh(void) { R.BC.B.h=R.IY.B.h; } -static void ld_b_iyl(void) { R.BC.B.h=R.IY.B.l; } -static void ld_c_c(void) { } -static void ld_c_a(void) { R.BC.B.l=R.AF.B.h; } -static void ld_c_b(void) { R.BC.B.l=R.BC.B.h; } -static void ld_c_d(void) { R.BC.B.l=R.DE.B.h; } -static void ld_c_e(void) { R.BC.B.l=R.DE.B.l; } -static void ld_c_h(void) { R.BC.B.l=R.HL.B.h; } -static void ld_c_l(void) { R.BC.B.l=R.HL.B.l; } -static void ld_c_ixh(void) { R.BC.B.l=R.IX.B.h; } -static void ld_c_ixl(void) { R.BC.B.l=R.IX.B.l; } -static void ld_c_iyh(void) { R.BC.B.l=R.IY.B.h; } -static void ld_c_iyl(void) { R.BC.B.l=R.IY.B.l; } -static void ld_d_d(void) { } -static void ld_d_a(void) { R.DE.B.h=R.AF.B.h; } -static void ld_d_c(void) { R.DE.B.h=R.BC.B.l; } -static void ld_d_b(void) { R.DE.B.h=R.BC.B.h; } -static void ld_d_e(void) { R.DE.B.h=R.DE.B.l; } -static void ld_d_h(void) { R.DE.B.h=R.HL.B.h; } -static void ld_d_l(void) { R.DE.B.h=R.HL.B.l; } -static void ld_d_ixh(void) { R.DE.B.h=R.IX.B.h; } -static void ld_d_ixl(void) { R.DE.B.h=R.IX.B.l; } -static void ld_d_iyh(void) { R.DE.B.h=R.IY.B.h; } -static void ld_d_iyl(void) { R.DE.B.h=R.IY.B.l; } -static void ld_e_e(void) { } -static void ld_e_a(void) { R.DE.B.l=R.AF.B.h; } -static void ld_e_c(void) { R.DE.B.l=R.BC.B.l; } -static void ld_e_b(void) { R.DE.B.l=R.BC.B.h; } -static void ld_e_d(void) { R.DE.B.l=R.DE.B.h; } -static void ld_e_h(void) { R.DE.B.l=R.HL.B.h; } -static void ld_e_l(void) { R.DE.B.l=R.HL.B.l; } -static void ld_e_ixh(void) { R.DE.B.l=R.IX.B.h; } -static void ld_e_ixl(void) { R.DE.B.l=R.IX.B.l; } -static void ld_e_iyh(void) { R.DE.B.l=R.IY.B.h; } -static void ld_e_iyl(void) { R.DE.B.l=R.IY.B.l; } -static void ld_h_h(void) { } -static void ld_h_a(void) { R.HL.B.h=R.AF.B.h; } -static void ld_h_c(void) { R.HL.B.h=R.BC.B.l; } -static void ld_h_b(void) { R.HL.B.h=R.BC.B.h; } -static void ld_h_e(void) { R.HL.B.h=R.DE.B.l; } -static void ld_h_d(void) { R.HL.B.h=R.DE.B.h; } -static void ld_h_l(void) { R.HL.B.h=R.HL.B.l; } -static void ld_l_l(void) { } -static void ld_l_a(void) { R.HL.B.l=R.AF.B.h; } -static void ld_l_c(void) { R.HL.B.l=R.BC.B.l; } -static void ld_l_b(void) { R.HL.B.l=R.BC.B.h; } -static void ld_l_e(void) { R.HL.B.l=R.DE.B.l; } -static void ld_l_d(void) { R.HL.B.l=R.DE.B.h; } -static void ld_l_h(void) { R.HL.B.l=R.HL.B.h; } -static void ld_ixh_a(void) { R.IX.B.h=R.AF.B.h; } -static void ld_ixh_b(void) { R.IX.B.h=R.BC.B.h; } -static void ld_ixh_c(void) { R.IX.B.h=R.BC.B.l; } -static void ld_ixh_d(void) { R.IX.B.h=R.DE.B.h; } -static void ld_ixh_e(void) { R.IX.B.h=R.DE.B.l; } -static void ld_ixh_ixh(void) { } -static void ld_ixh_ixl(void) { R.IX.B.h=R.IX.B.l; } -static void ld_ixl_a(void) { R.IX.B.l=R.AF.B.h; } -static void ld_ixl_b(void) { R.IX.B.l=R.BC.B.h; } -static void ld_ixl_c(void) { R.IX.B.l=R.BC.B.l; } -static void ld_ixl_d(void) { R.IX.B.l=R.DE.B.h; } -static void ld_ixl_e(void) { R.IX.B.l=R.DE.B.l; } -static void ld_ixl_ixh(void) { R.IX.B.l=R.IX.B.h; } -static void ld_ixl_ixl(void) { } -static void ld_iyh_a(void) { R.IY.B.h=R.AF.B.h; } -static void ld_iyh_b(void) { R.IY.B.h=R.BC.B.h; } -static void ld_iyh_c(void) { R.IY.B.h=R.BC.B.l; } -static void ld_iyh_d(void) { R.IY.B.h=R.DE.B.h; } -static void ld_iyh_e(void) { R.IY.B.h=R.DE.B.l; } -static void ld_iyh_iyh(void) { } -static void ld_iyh_iyl(void) { R.IY.B.h=R.IY.B.l; } -static void ld_iyl_a(void) { R.IY.B.l=R.AF.B.h; } -static void ld_iyl_b(void) { R.IY.B.l=R.BC.B.h; } -static void ld_iyl_c(void) { R.IY.B.l=R.BC.B.l; } -static void ld_iyl_d(void) { R.IY.B.l=R.DE.B.h; } -static void ld_iyl_e(void) { R.IY.B.l=R.DE.B.l; } -static void ld_iyl_iyh(void) { R.IY.B.l=R.IY.B.h; } -static void ld_iyl_iyl(void) { } -static void ld_bc_xword(void) { R.BC.D=M_RDMEM_WORD(M_RDMEM_OPCODE_WORD()); } -static void ld_bc_word(void) { R.BC.D=M_RDMEM_OPCODE_WORD(); } -static void ld_de_xword(void) { R.DE.D=M_RDMEM_WORD(M_RDMEM_OPCODE_WORD()); } -static void ld_de_word(void) { R.DE.D=M_RDMEM_OPCODE_WORD(); } -static void ld_hl_xword(void) { R.HL.D=M_RDMEM_WORD(M_RDMEM_OPCODE_WORD()); } -static void ld_hl_word(void) { R.HL.D=M_RDMEM_OPCODE_WORD(); } -static void ld_ix_xword(void) { R.IX.D=M_RDMEM_WORD(M_RDMEM_OPCODE_WORD()); } -static void ld_ix_word(void) { R.IX.D=M_RDMEM_OPCODE_WORD(); } -static void ld_iy_xword(void) { R.IY.D=M_RDMEM_WORD(M_RDMEM_OPCODE_WORD()); } -static void ld_iy_word(void) { R.IY.D=M_RDMEM_OPCODE_WORD(); } -static void ld_sp_xword(void) { R.SP.D=M_RDMEM_WORD(M_RDMEM_OPCODE_WORD()); } -static void ld_sp_word(void) { R.SP.D=M_RDMEM_OPCODE_WORD(); } -static void ld_sp_hl(void) { R.SP.D=R.HL.D; } -static void ld_sp_ix(void) { R.SP.D=R.IX.D; } -static void ld_sp_iy(void) { R.SP.D=R.IY.D; } -static void ld_a_i(void) -{ - R.AF.B.h=R.I; - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSTable[R.I]|(R.IFF2<<2); -} -static void ld_i_a(void) { R.I=R.AF.B.h; } -static void ld_a_r(void) -{ - R.AF.B.h=(R.R&127)|(R.R2&128); - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSTable[R.AF.B.h]|(R.IFF2<<2); -} -static void ld_r_a(void) { R.R=R.R2=R.AF.B.h; } - -static void ldd(void) -{ - M_WRMEM(R.DE.D,M_RDMEM(R.HL.D)); - --R.DE.W.l; - --R.HL.W.l; - --R.BC.W.l; - R.AF.B.l=(R.AF.B.l&0xE9)|(R.BC.D? V_FLAG:0); -} -static void lddr(void) -{ - ldd (); - if (R.BC.D) { Z80_ICount+=5; R.PC.W.l-=2; } -} -static void ldi(void) -{ - M_WRMEM(R.DE.D,M_RDMEM(R.HL.D)); - ++R.DE.W.l; - ++R.HL.W.l; - --R.BC.W.l; - R.AF.B.l=(R.AF.B.l&0xE9)|(R.BC.D? V_FLAG:0); -} -static void ldir(void) -{ - ldi (); - if (R.BC.D) { Z80_ICount+=5; R.PC.W.l-=2; } -} - -static void neg(void) -{ - byte i; - i=R.AF.B.h; - R.AF.B.h=0; - M_SUB(i); -} - -static void nop(void) { }; - -static void or_xhl(void) { byte i=M_RD_XHL; M_OR(i); } -static void or_xix(void) { byte i=M_RD_XIX(); M_OR(i); } -static void or_xiy(void) { byte i=M_RD_XIY(); M_OR(i); } -static void or_a(void) { R.AF.B.l=ZSPTable[R.AF.B.h]; } -static void or_b(void) { M_OR(R.BC.B.h); } -static void or_c(void) { M_OR(R.BC.B.l); } -static void or_d(void) { M_OR(R.DE.B.h); } -static void or_e(void) { M_OR(R.DE.B.l); } -static void or_h(void) { M_OR(R.HL.B.h); } -static void or_l(void) { M_OR(R.HL.B.l); } -static void or_ixh(void) { M_OR(R.IX.B.h); } -static void or_ixl(void) { M_OR(R.IX.B.l); } -static void or_iyh(void) { M_OR(R.IY.B.h); } -static void or_iyl(void) { M_OR(R.IY.B.l); } -static void or_byte(void) { byte i=M_RDMEM_OPCODE(); M_OR(i); } - -static void outd(void) -{ - --R.BC.B.h; - DoOut (R.BC.B.l,R.BC.B.h,M_RDMEM(R.HL.D)); - --R.HL.W.l; - R.AF.B.l=(R.BC.B.h)? N_FLAG:(Z_FLAG|N_FLAG); -} -static void otdr(void) -{ - outd (); - if (R.BC.B.h) { Z80_ICount+=5; R.PC.W.l-=2; } -} -static void outi(void) -{ - --R.BC.B.h; - DoOut (R.BC.B.l,R.BC.B.h,M_RDMEM(R.HL.D)); - ++R.HL.W.l; - R.AF.B.l=(R.BC.B.h)? N_FLAG:(Z_FLAG|N_FLAG); -} -static void otir(void) -{ - outi (); - if (R.BC.B.h) { Z80_ICount+=5; R.PC.W.l-=2; } -} - -static void out_c_a(void) { DoOut(R.BC.B.l,R.BC.B.h,R.AF.B.h); } -static void out_c_b(void) { DoOut(R.BC.B.l,R.BC.B.h,R.BC.B.h); } -static void out_c_c(void) { DoOut(R.BC.B.l,R.BC.B.h,R.BC.B.l); } -static void out_c_d(void) { DoOut(R.BC.B.l,R.BC.B.h,R.DE.B.h); } -static void out_c_e(void) { DoOut(R.BC.B.l,R.BC.B.h,R.DE.B.l); } -static void out_c_h(void) { DoOut(R.BC.B.l,R.BC.B.h,R.HL.B.h); } -static void out_c_l(void) { DoOut(R.BC.B.l,R.BC.B.h,R.HL.B.l); } -static void out_c_0(void) { DoOut(R.BC.B.l,R.BC.B.h,0); } -static void out_byte_a(void) -{ - byte i=M_RDMEM_OPCODE(); - DoOut(i,R.AF.B.h,R.AF.B.h); -} - -static void pop_af(void) { M_POP(AF); } -static void pop_bc(void) { M_POP(BC); } -static void pop_de(void) { M_POP(DE); } -static void pop_hl(void) { M_POP(HL); } -static void pop_ix(void) { M_POP(IX); } -static void pop_iy(void) { M_POP(IY); } - -static void push_af(void) { M_PUSH(AF); } -static void push_bc(void) { M_PUSH(BC); } -static void push_de(void) { M_PUSH(DE); } -static void push_hl(void) { M_PUSH(HL); } -static void push_ix(void) { M_PUSH(IX); } -static void push_iy(void) { M_PUSH(IY); } - -static void res_0_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(0,i); - M_WRMEM(R.HL.D,i); -}; -static void res_0_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(0,i); - M_WRMEM(j,i); -}; -static void res_0_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(0,i); - M_WRMEM(j,i); -}; -static void res_0_a(void) { M_RES(0,R.AF.B.h); }; -static void res_0_b(void) { M_RES(0,R.BC.B.h); }; -static void res_0_c(void) { M_RES(0,R.BC.B.l); }; -static void res_0_d(void) { M_RES(0,R.DE.B.h); }; -static void res_0_e(void) { M_RES(0,R.DE.B.l); }; -static void res_0_h(void) { M_RES(0,R.HL.B.h); }; -static void res_0_l(void) { M_RES(0,R.HL.B.l); }; - -static void res_1_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(1,i); - M_WRMEM(R.HL.D,i); -}; -static void res_1_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(1,i); - M_WRMEM(j,i); -}; -static void res_1_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(1,i); - M_WRMEM(j,i); -}; -static void res_1_a(void) { M_RES(1,R.AF.B.h); }; -static void res_1_b(void) { M_RES(1,R.BC.B.h); }; -static void res_1_c(void) { M_RES(1,R.BC.B.l); }; -static void res_1_d(void) { M_RES(1,R.DE.B.h); }; -static void res_1_e(void) { M_RES(1,R.DE.B.l); }; -static void res_1_h(void) { M_RES(1,R.HL.B.h); }; -static void res_1_l(void) { M_RES(1,R.HL.B.l); }; - -static void res_2_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(2,i); - M_WRMEM(R.HL.D,i); -}; -static void res_2_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(2,i); - M_WRMEM(j,i); -}; -static void res_2_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(2,i); - M_WRMEM(j,i); -}; -static void res_2_a(void) { M_RES(2,R.AF.B.h); }; -static void res_2_b(void) { M_RES(2,R.BC.B.h); }; -static void res_2_c(void) { M_RES(2,R.BC.B.l); }; -static void res_2_d(void) { M_RES(2,R.DE.B.h); }; -static void res_2_e(void) { M_RES(2,R.DE.B.l); }; -static void res_2_h(void) { M_RES(2,R.HL.B.h); }; -static void res_2_l(void) { M_RES(2,R.HL.B.l); }; - -static void res_3_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(3,i); - M_WRMEM(R.HL.D,i); -}; -static void res_3_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(3,i); - M_WRMEM(j,i); -}; -static void res_3_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(3,i); - M_WRMEM(j,i); -}; -static void res_3_a(void) { M_RES(3,R.AF.B.h); }; -static void res_3_b(void) { M_RES(3,R.BC.B.h); }; -static void res_3_c(void) { M_RES(3,R.BC.B.l); }; -static void res_3_d(void) { M_RES(3,R.DE.B.h); }; -static void res_3_e(void) { M_RES(3,R.DE.B.l); }; -static void res_3_h(void) { M_RES(3,R.HL.B.h); }; -static void res_3_l(void) { M_RES(3,R.HL.B.l); }; - -static void res_4_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(4,i); - M_WRMEM(R.HL.D,i); -}; -static void res_4_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(4,i); - M_WRMEM(j,i); -}; -static void res_4_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(4,i); - M_WRMEM(j,i); -}; -static void res_4_a(void) { M_RES(4,R.AF.B.h); }; -static void res_4_b(void) { M_RES(4,R.BC.B.h); }; -static void res_4_c(void) { M_RES(4,R.BC.B.l); }; -static void res_4_d(void) { M_RES(4,R.DE.B.h); }; -static void res_4_e(void) { M_RES(4,R.DE.B.l); }; -static void res_4_h(void) { M_RES(4,R.HL.B.h); }; -static void res_4_l(void) { M_RES(4,R.HL.B.l); }; - -static void res_5_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(5,i); - M_WRMEM(R.HL.D,i); -}; -static void res_5_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(5,i); - M_WRMEM(j,i); -}; -static void res_5_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(5,i); - M_WRMEM(j,i); -}; -static void res_5_a(void) { M_RES(5,R.AF.B.h); }; -static void res_5_b(void) { M_RES(5,R.BC.B.h); }; -static void res_5_c(void) { M_RES(5,R.BC.B.l); }; -static void res_5_d(void) { M_RES(5,R.DE.B.h); }; -static void res_5_e(void) { M_RES(5,R.DE.B.l); }; -static void res_5_h(void) { M_RES(5,R.HL.B.h); }; -static void res_5_l(void) { M_RES(5,R.HL.B.l); }; - -static void res_6_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(6,i); - M_WRMEM(R.HL.D,i); -}; -static void res_6_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(6,i); - M_WRMEM(j,i); -}; -static void res_6_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(6,i); - M_WRMEM(j,i); -}; -static void res_6_a(void) { M_RES(6,R.AF.B.h); }; -static void res_6_b(void) { M_RES(6,R.BC.B.h); }; -static void res_6_c(void) { M_RES(6,R.BC.B.l); }; -static void res_6_d(void) { M_RES(6,R.DE.B.h); }; -static void res_6_e(void) { M_RES(6,R.DE.B.l); }; -static void res_6_h(void) { M_RES(6,R.HL.B.h); }; -static void res_6_l(void) { M_RES(6,R.HL.B.l); }; - -static void res_7_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RES(7,i); - M_WRMEM(R.HL.D,i); -}; -static void res_7_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RES(7,i); - M_WRMEM(j,i); -}; -static void res_7_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RES(7,i); - M_WRMEM(j,i); -}; -static void res_7_a(void) { M_RES(7,R.AF.B.h); }; -static void res_7_b(void) { M_RES(7,R.BC.B.h); }; -static void res_7_c(void) { M_RES(7,R.BC.B.l); }; -static void res_7_d(void) { M_RES(7,R.DE.B.h); }; -static void res_7_e(void) { M_RES(7,R.DE.B.l); }; -static void res_7_h(void) { M_RES(7,R.HL.B.h); }; -static void res_7_l(void) { M_RES(7,R.HL.B.l); }; - -static void ret(void) { M_RET; } -static void ret_c(void) { if (M_C) { M_RET; } else { M_SKIP_RET; } } -static void ret_m(void) { if (M_M) { M_RET; } else { M_SKIP_RET; } } -static void ret_nc(void) { if (M_NC) { M_RET; } else { M_SKIP_RET; } } -static void ret_nz(void) { if (M_NZ) { M_RET; } else { M_SKIP_RET; } } -static void ret_p(void) { if (M_P) { M_RET; } else { M_SKIP_RET; } } -static void ret_pe(void) { if (M_PE) { M_RET; } else { M_SKIP_RET; } } -static void ret_po(void) { if (M_PO) { M_RET; } else { M_SKIP_RET; } } -static void ret_z(void) { if (M_Z) { M_RET; } else { M_SKIP_RET; } } - -static void reti(void) { Z80_Reti(); M_RET; } -static void retn(void) { R.IFF1=R.IFF2; Z80_Retn(); M_RET; } - -static void rl_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RL(i); - M_WRMEM(R.HL.D,i); -} -static void rl_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RL(i); - M_WRMEM(j,i); -} -static void rl_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RL(i); - M_WRMEM(j,i); -} -static void rl_a(void) { M_RL(R.AF.B.h); } -static void rl_b(void) { M_RL(R.BC.B.h); } -static void rl_c(void) { M_RL(R.BC.B.l); } -static void rl_d(void) { M_RL(R.DE.B.h); } -static void rl_e(void) { M_RL(R.DE.B.l); } -static void rl_h(void) { M_RL(R.HL.B.h); } -static void rl_l(void) { M_RL(R.HL.B.l); } -static void rla(void) { M_RLA; } - -static void rlc_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RLC(i); - M_WRMEM(R.HL.D,i); -} -static void rlc_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RLC(i); - M_WRMEM(j,i); -} -static void rlc_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RLC(i); - M_WRMEM(j,i); -} -static void rlc_a(void) { M_RLC(R.AF.B.h); } -static void rlc_b(void) { M_RLC(R.BC.B.h); } -static void rlc_c(void) { M_RLC(R.BC.B.l); } -static void rlc_d(void) { M_RLC(R.DE.B.h); } -static void rlc_e(void) { M_RLC(R.DE.B.l); } -static void rlc_h(void) { M_RLC(R.HL.B.h); } -static void rlc_l(void) { M_RLC(R.HL.B.l); } -static void rlca(void) { M_RLCA; } - -static void rld(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_WRMEM(R.HL.D,(i<<4)|(R.AF.B.h&0x0F)); - R.AF.B.h=(R.AF.B.h&0xF0)|(i>>4); - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSPTable[R.AF.B.h]; -} - -static void rr_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RR(i); - M_WRMEM(R.HL.D,i); -} -static void rr_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RR(i); - M_WRMEM(j,i); -} -static void rr_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RR(i); - M_WRMEM(j,i); -} -static void rr_a(void) { M_RR(R.AF.B.h); } -static void rr_b(void) { M_RR(R.BC.B.h); } -static void rr_c(void) { M_RR(R.BC.B.l); } -static void rr_d(void) { M_RR(R.DE.B.h); } -static void rr_e(void) { M_RR(R.DE.B.l); } -static void rr_h(void) { M_RR(R.HL.B.h); } -static void rr_l(void) { M_RR(R.HL.B.l); } -static void rra(void) { M_RRA; } - -static void rrc_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_RRC(i); - M_WRMEM(R.HL.D,i); -} -static void rrc_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_RRC(i); - M_WRMEM(j,i); -} -static void rrc_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_RRC(i); - M_WRMEM(j,i); -} -static void rrc_a(void) { M_RRC(R.AF.B.h); } -static void rrc_b(void) { M_RRC(R.BC.B.h); } -static void rrc_c(void) { M_RRC(R.BC.B.l); } -static void rrc_d(void) { M_RRC(R.DE.B.h); } -static void rrc_e(void) { M_RRC(R.DE.B.l); } -static void rrc_h(void) { M_RRC(R.HL.B.h); } -static void rrc_l(void) { M_RRC(R.HL.B.l); } -static void rrca(void) { M_RRCA; } - -static void rrd(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_WRMEM(R.HL.D,(i>>4)|(R.AF.B.h<<4)); - R.AF.B.h=(R.AF.B.h&0xF0)|(i&0x0F); - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSPTable[R.AF.B.h]; -} - -static void rst_00(void) { M_RST(0x00); } -static void rst_08(void) { M_RST(0x08); } -static void rst_10(void) { M_RST(0x10); } -static void rst_18(void) { M_RST(0x18); } -static void rst_20(void) { M_RST(0x20); } -static void rst_28(void) { M_RST(0x28); } -static void rst_30(void) { M_RST(0x30); } -static void rst_38(void) { M_RST(0x38); } - -static void sbc_a_byte(void) { byte i=M_RDMEM_OPCODE(); M_SBC(i); } -static void sbc_a_xhl(void) { byte i=M_RD_XHL; M_SBC(i); } -static void sbc_a_xix(void) { byte i=M_RD_XIX(); M_SBC(i); } -static void sbc_a_xiy(void) { byte i=M_RD_XIY(); M_SBC(i); } -static void sbc_a_a(void) { M_SBC(R.AF.B.h); } -static void sbc_a_b(void) { M_SBC(R.BC.B.h); } -static void sbc_a_c(void) { M_SBC(R.BC.B.l); } -static void sbc_a_d(void) { M_SBC(R.DE.B.h); } -static void sbc_a_e(void) { M_SBC(R.DE.B.l); } -static void sbc_a_h(void) { M_SBC(R.HL.B.h); } -static void sbc_a_l(void) { M_SBC(R.HL.B.l); } -static void sbc_a_ixh(void) { M_SBC(R.IX.B.h); } -static void sbc_a_ixl(void) { M_SBC(R.IX.B.l); } -static void sbc_a_iyh(void) { M_SBC(R.IY.B.h); } -static void sbc_a_iyl(void) { M_SBC(R.IY.B.l); } - -static void sbc_hl_bc(void) { M_SBCW(BC); } -static void sbc_hl_de(void) { M_SBCW(DE); } -static void sbc_hl_hl(void) { M_SBCW(HL); } -static void sbc_hl_sp(void) { M_SBCW(SP); } - -static void scf(void) { R.AF.B.l=(R.AF.B.l&0xEC)|C_FLAG; } - -static void set_0_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(0,i); - M_WRMEM(R.HL.D,i); -}; -static void set_0_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(0,i); - M_WRMEM(j,i); -}; -static void set_0_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(0,i); - M_WRMEM(j,i); -}; -static void set_0_a(void) { M_SET(0,R.AF.B.h); }; -static void set_0_b(void) { M_SET(0,R.BC.B.h); }; -static void set_0_c(void) { M_SET(0,R.BC.B.l); }; -static void set_0_d(void) { M_SET(0,R.DE.B.h); }; -static void set_0_e(void) { M_SET(0,R.DE.B.l); }; -static void set_0_h(void) { M_SET(0,R.HL.B.h); }; -static void set_0_l(void) { M_SET(0,R.HL.B.l); }; - -static void set_1_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(1,i); - M_WRMEM(R.HL.D,i); -}; -static void set_1_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(1,i); - M_WRMEM(j,i); -}; -static void set_1_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(1,i); - M_WRMEM(j,i); -}; -static void set_1_a(void) { M_SET(1,R.AF.B.h); }; -static void set_1_b(void) { M_SET(1,R.BC.B.h); }; -static void set_1_c(void) { M_SET(1,R.BC.B.l); }; -static void set_1_d(void) { M_SET(1,R.DE.B.h); }; -static void set_1_e(void) { M_SET(1,R.DE.B.l); }; -static void set_1_h(void) { M_SET(1,R.HL.B.h); }; -static void set_1_l(void) { M_SET(1,R.HL.B.l); }; - -static void set_2_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(2,i); - M_WRMEM(R.HL.D,i); -}; -static void set_2_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(2,i); - M_WRMEM(j,i); -}; -static void set_2_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(2,i); - M_WRMEM(j,i); -}; -static void set_2_a(void) { M_SET(2,R.AF.B.h); }; -static void set_2_b(void) { M_SET(2,R.BC.B.h); }; -static void set_2_c(void) { M_SET(2,R.BC.B.l); }; -static void set_2_d(void) { M_SET(2,R.DE.B.h); }; -static void set_2_e(void) { M_SET(2,R.DE.B.l); }; -static void set_2_h(void) { M_SET(2,R.HL.B.h); }; -static void set_2_l(void) { M_SET(2,R.HL.B.l); }; - -static void set_3_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(3,i); - M_WRMEM(R.HL.D,i); -}; -static void set_3_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(3,i); - M_WRMEM(j,i); -}; -static void set_3_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(3,i); - M_WRMEM(j,i); -}; -static void set_3_a(void) { M_SET(3,R.AF.B.h); }; -static void set_3_b(void) { M_SET(3,R.BC.B.h); }; -static void set_3_c(void) { M_SET(3,R.BC.B.l); }; -static void set_3_d(void) { M_SET(3,R.DE.B.h); }; -static void set_3_e(void) { M_SET(3,R.DE.B.l); }; -static void set_3_h(void) { M_SET(3,R.HL.B.h); }; -static void set_3_l(void) { M_SET(3,R.HL.B.l); }; - -static void set_4_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(4,i); - M_WRMEM(R.HL.D,i); -}; -static void set_4_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(4,i); - M_WRMEM(j,i); -}; -static void set_4_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(4,i); - M_WRMEM(j,i); -}; -static void set_4_a(void) { M_SET(4,R.AF.B.h); }; -static void set_4_b(void) { M_SET(4,R.BC.B.h); }; -static void set_4_c(void) { M_SET(4,R.BC.B.l); }; -static void set_4_d(void) { M_SET(4,R.DE.B.h); }; -static void set_4_e(void) { M_SET(4,R.DE.B.l); }; -static void set_4_h(void) { M_SET(4,R.HL.B.h); }; -static void set_4_l(void) { M_SET(4,R.HL.B.l); }; - -static void set_5_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(5,i); - M_WRMEM(R.HL.D,i); -}; -static void set_5_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(5,i); - M_WRMEM(j,i); -}; -static void set_5_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(5,i); - M_WRMEM(j,i); -}; -static void set_5_a(void) { M_SET(5,R.AF.B.h); }; -static void set_5_b(void) { M_SET(5,R.BC.B.h); }; -static void set_5_c(void) { M_SET(5,R.BC.B.l); }; -static void set_5_d(void) { M_SET(5,R.DE.B.h); }; -static void set_5_e(void) { M_SET(5,R.DE.B.l); }; -static void set_5_h(void) { M_SET(5,R.HL.B.h); }; -static void set_5_l(void) { M_SET(5,R.HL.B.l); }; - -static void set_6_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(6,i); - M_WRMEM(R.HL.D,i); -}; -static void set_6_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(6,i); - M_WRMEM(j,i); -}; -static void set_6_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(6,i); - M_WRMEM(j,i); -}; -static void set_6_a(void) { M_SET(6,R.AF.B.h); }; -static void set_6_b(void) { M_SET(6,R.BC.B.h); }; -static void set_6_c(void) { M_SET(6,R.BC.B.l); }; -static void set_6_d(void) { M_SET(6,R.DE.B.h); }; -static void set_6_e(void) { M_SET(6,R.DE.B.l); }; -static void set_6_h(void) { M_SET(6,R.HL.B.h); }; -static void set_6_l(void) { M_SET(6,R.HL.B.l); }; - -static void set_7_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SET(7,i); - M_WRMEM(R.HL.D,i); -}; -static void set_7_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SET(7,i); - M_WRMEM(j,i); -}; -static void set_7_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SET(7,i); - M_WRMEM(j,i); -}; -static void set_7_a(void) { M_SET(7,R.AF.B.h); }; -static void set_7_b(void) { M_SET(7,R.BC.B.h); }; -static void set_7_c(void) { M_SET(7,R.BC.B.l); }; -static void set_7_d(void) { M_SET(7,R.DE.B.h); }; -static void set_7_e(void) { M_SET(7,R.DE.B.l); }; -static void set_7_h(void) { M_SET(7,R.HL.B.h); }; -static void set_7_l(void) { M_SET(7,R.HL.B.l); }; - -static void sla_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SLA(i); - M_WRMEM(R.HL.D,i); -} -static void sla_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SLA(i); - M_WRMEM(j,i); -} -static void sla_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SLA(i); - M_WRMEM(j,i); -} -static void sla_a(void) { M_SLA(R.AF.B.h); } -static void sla_b(void) { M_SLA(R.BC.B.h); } -static void sla_c(void) { M_SLA(R.BC.B.l); } -static void sla_d(void) { M_SLA(R.DE.B.h); } -static void sla_e(void) { M_SLA(R.DE.B.l); } -static void sla_h(void) { M_SLA(R.HL.B.h); } -static void sla_l(void) { M_SLA(R.HL.B.l); } - -static void sll_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SLL(i); - M_WRMEM(R.HL.D,i); -} -static void sll_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SLL(i); - M_WRMEM(j,i); -} -static void sll_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SLL(i); - M_WRMEM(j,i); -} -static void sll_a(void) { M_SLL(R.AF.B.h); } -static void sll_b(void) { M_SLL(R.BC.B.h); } -static void sll_c(void) { M_SLL(R.BC.B.l); } -static void sll_d(void) { M_SLL(R.DE.B.h); } -static void sll_e(void) { M_SLL(R.DE.B.l); } -static void sll_h(void) { M_SLL(R.HL.B.h); } -static void sll_l(void) { M_SLL(R.HL.B.l); } - -static void sra_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SRA(i); - M_WRMEM(R.HL.D,i); -} -static void sra_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SRA(i); - M_WRMEM(j,i); -} -static void sra_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SRA(i); - M_WRMEM(j,i); -} -static void sra_a(void) { M_SRA(R.AF.B.h); } -static void sra_b(void) { M_SRA(R.BC.B.h); } -static void sra_c(void) { M_SRA(R.BC.B.l); } -static void sra_d(void) { M_SRA(R.DE.B.h); } -static void sra_e(void) { M_SRA(R.DE.B.l); } -static void sra_h(void) { M_SRA(R.HL.B.h); } -static void sra_l(void) { M_SRA(R.HL.B.l); } - -static void srl_xhl(void) -{ - byte i; - i=M_RDMEM(R.HL.D); - M_SRL(i); - M_WRMEM(R.HL.D,i); -} -static void srl_xix(void) -{ - byte i; - int j; - j=M_XIX; - i=M_RDMEM(j); - M_SRL(i); - M_WRMEM(j,i); -} -static void srl_xiy(void) -{ - byte i; - int j; - j=M_XIY; - i=M_RDMEM(j); - M_SRL(i); - M_WRMEM(j,i); -} -static void srl_a(void) { M_SRL(R.AF.B.h); } -static void srl_b(void) { M_SRL(R.BC.B.h); } -static void srl_c(void) { M_SRL(R.BC.B.l); } -static void srl_d(void) { M_SRL(R.DE.B.h); } -static void srl_e(void) { M_SRL(R.DE.B.l); } -static void srl_h(void) { M_SRL(R.HL.B.h); } -static void srl_l(void) { M_SRL(R.HL.B.l); } - -static void sub_xhl(void) { byte i=M_RD_XHL; M_SUB(i); } -static void sub_xix(void) { byte i=M_RD_XIX(); M_SUB(i); } -static void sub_xiy(void) { byte i=M_RD_XIY(); M_SUB(i); } -static void sub_a(void) { R.AF.D=Z_FLAG|N_FLAG; } -static void sub_b(void) { M_SUB(R.BC.B.h); } -static void sub_c(void) { M_SUB(R.BC.B.l); } -static void sub_d(void) { M_SUB(R.DE.B.h); } -static void sub_e(void) { M_SUB(R.DE.B.l); } -static void sub_h(void) { M_SUB(R.HL.B.h); } -static void sub_l(void) { M_SUB(R.HL.B.l); } -static void sub_ixh(void) { M_SUB(R.IX.B.h); } -static void sub_ixl(void) { M_SUB(R.IX.B.l); } -static void sub_iyh(void) { M_SUB(R.IY.B.h); } -static void sub_iyl(void) { M_SUB(R.IY.B.l); } -static void sub_byte(void) { byte i=M_RDMEM_OPCODE(); M_SUB(i); } - -static void xor_xhl(void) { byte i=M_RD_XHL; M_XOR(i); } -static void xor_xix(void) { byte i=M_RD_XIX(); M_XOR(i); } -static void xor_xiy(void) { byte i=M_RD_XIY(); M_XOR(i); } -static void xor_a(void) { R.AF.D=Z_FLAG|V_FLAG; } -static void xor_b(void) { M_XOR(R.BC.B.h); } -static void xor_c(void) { M_XOR(R.BC.B.l); } -static void xor_d(void) { M_XOR(R.DE.B.h); } -static void xor_e(void) { M_XOR(R.DE.B.l); } -static void xor_h(void) { M_XOR(R.HL.B.h); } -static void xor_l(void) { M_XOR(R.HL.B.l); } -static void xor_ixh(void) { M_XOR(R.IX.B.h); } -static void xor_ixl(void) { M_XOR(R.IX.B.l); } -static void xor_iyh(void) { M_XOR(R.IY.B.h); } -static void xor_iyl(void) { M_XOR(R.IY.B.l); } -static void xor_byte(void) { byte i=M_RDMEM_OPCODE(); M_XOR(i); } - -static void no_op(void) -{ - --R.PC.W.l; -} - -static void patch(void) { Z80_Patch(&R); } - -static unsigned cycles_main[256]= -{ - 4,10,7,6,4,4,7,4, - 4,11,7,6,4,4,7,4, - 8,10,7,6,4,4,7,4, - 7,11,7,6,4,4,7,4, - 7,10,16,6,4,4,7,4, - 7,11,16,6,4,4,7,4, - 7,10,13,6,11,11,10,4, - 7,11,13,6,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 7,7,7,7,7,7,4,7, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 4,4,4,4,4,4,7,4, - 5,10,10,10,10,11,7,11, - 5,4,10,0,10,10,7,11, - 5,10,10,11,10,11,7,11, - 5,4,10,11,10,0,7,11, - 5,10,10,19,10,11,7,11, - 5,4,10,4,10,0,7,11, - 5,10,10,4,10,11,7,11, - 5,6,10,4,10,0,7,11 -}; - -static unsigned cycles_cb[256]= -{ - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,12,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8, - 8,8,8,8,8,8,15,8 -}; -static unsigned cycles_xx_cb[]= -{ - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 20,20,20,20,20,20,20,20, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0, - 0,0,0,0,0,0,23,0 -}; -static unsigned cycles_xx[256]= -{ - 0,0,0,0,0,0,0,0, - 0,15,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,15,0,0,0,0,0,0, - 0,14,20,10,9,9,9,0, - 0,15,20,10,9,9,9,0, - 0,0,0,0,23,23,19,0, - 0,15,0,0,0,0,0,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9, - 19,19,19,19,19,19,19,19, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,9,9,19,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,14,0,23,0,15,0,0, - 0,8,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,10,0,0,0,0,0,0 -}; -static unsigned cycles_ed[256]= -{ - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 12,12,15,20,8,8,8,9, - 12,12,15,20,8,8,8,9, - 12,12,15,20,8,8,8,9, - 12,12,15,20,8,8,8,9, - 12,12,15,20,8,8,8,18, - 12,12,15,20,8,8,8,18, - 12,12,15,20,8,8,8,0, - 12,12,15,20,8,8,8,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 16,16,16,16,0,0,0,0, - 16,16,16,16,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0 -}; - -static void no_op_xx(void) { -++R.PC.W.l; } - -static opcode_fn opcode_dd_cb[256]= -{ - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rlc_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rrc_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rl_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rr_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sla_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sra_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sll_xix ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,srl_xix ,no_op_xx , - bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix,bit_0_xix, - bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix,bit_1_xix, - bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix,bit_2_xix, - bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix,bit_3_xix, - bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix,bit_4_xix, - bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix,bit_5_xix, - bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix,bit_6_xix, - bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix,bit_7_xix, - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_0_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_1_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_2_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_3_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_4_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_5_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_6_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_7_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_0_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_1_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_2_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_3_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_4_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_5_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_6_xix,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_7_xix,no_op_xx -}; - -static opcode_fn opcode_fd_cb[256]= -{ - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rlc_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rrc_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rl_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,rr_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sla_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sra_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,sll_xiy ,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,srl_xiy ,no_op_xx , - bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy,bit_0_xiy, - bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy,bit_1_xiy, - bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy,bit_2_xiy, - bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy,bit_3_xiy, - bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy,bit_4_xiy, - bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy,bit_5_xiy, - bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy,bit_6_xiy, - bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy,bit_7_xiy, - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_0_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_1_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_2_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_3_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_4_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_5_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_6_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,res_7_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_0_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_1_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_2_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_3_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_4_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_5_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_6_xiy,no_op_xx , - no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,no_op_xx ,set_7_xiy,no_op_xx -}; - -static void dd_cb(void) -{ - unsigned opcode; - opcode=M_RDOP_ARG((R.PC.D+1)&0xFFFF); - Z80_ICount += cycles_xx_cb[opcode]; - (*(opcode_dd_cb[opcode]))(); - ++R.PC.W.l; -}; -static void fd_cb(void) -{ - unsigned opcode; - opcode=M_RDOP_ARG((R.PC.D+1)&0xFFFF); - Z80_ICount+=cycles_xx_cb[opcode]; - (*(opcode_fd_cb[opcode]))(); - ++R.PC.W.l; -}; - -static opcode_fn opcode_cb[256]= -{ - rlc_b ,rlc_c ,rlc_d ,rlc_e ,rlc_h ,rlc_l ,rlc_xhl ,rlc_a , - rrc_b ,rrc_c ,rrc_d ,rrc_e ,rrc_h ,rrc_l ,rrc_xhl ,rrc_a , - rl_b ,rl_c ,rl_d ,rl_e ,rl_h ,rl_l ,rl_xhl ,rl_a , - rr_b ,rr_c ,rr_d ,rr_e ,rr_h ,rr_l ,rr_xhl ,rr_a , - sla_b ,sla_c ,sla_d ,sla_e ,sla_h ,sla_l ,sla_xhl ,sla_a , - sra_b ,sra_c ,sra_d ,sra_e ,sra_h ,sra_l ,sra_xhl ,sra_a , - sll_b ,sll_c ,sll_d ,sll_e ,sll_h ,sll_l ,sll_xhl ,sll_a , - srl_b ,srl_c ,srl_d ,srl_e ,srl_h ,srl_l ,srl_xhl ,srl_a , - bit_0_b,bit_0_c,bit_0_d,bit_0_e,bit_0_h,bit_0_l,bit_0_xhl,bit_0_a, - bit_1_b,bit_1_c,bit_1_d,bit_1_e,bit_1_h,bit_1_l,bit_1_xhl,bit_1_a, - bit_2_b,bit_2_c,bit_2_d,bit_2_e,bit_2_h,bit_2_l,bit_2_xhl,bit_2_a, - bit_3_b,bit_3_c,bit_3_d,bit_3_e,bit_3_h,bit_3_l,bit_3_xhl,bit_3_a, - bit_4_b,bit_4_c,bit_4_d,bit_4_e,bit_4_h,bit_4_l,bit_4_xhl,bit_4_a, - bit_5_b,bit_5_c,bit_5_d,bit_5_e,bit_5_h,bit_5_l,bit_5_xhl,bit_5_a, - bit_6_b,bit_6_c,bit_6_d,bit_6_e,bit_6_h,bit_6_l,bit_6_xhl,bit_6_a, - bit_7_b,bit_7_c,bit_7_d,bit_7_e,bit_7_h,bit_7_l,bit_7_xhl,bit_7_a, - res_0_b,res_0_c,res_0_d,res_0_e,res_0_h,res_0_l,res_0_xhl,res_0_a, - res_1_b,res_1_c,res_1_d,res_1_e,res_1_h,res_1_l,res_1_xhl,res_1_a, - res_2_b,res_2_c,res_2_d,res_2_e,res_2_h,res_2_l,res_2_xhl,res_2_a, - res_3_b,res_3_c,res_3_d,res_3_e,res_3_h,res_3_l,res_3_xhl,res_3_a, - res_4_b,res_4_c,res_4_d,res_4_e,res_4_h,res_4_l,res_4_xhl,res_4_a, - res_5_b,res_5_c,res_5_d,res_5_e,res_5_h,res_5_l,res_5_xhl,res_5_a, - res_6_b,res_6_c,res_6_d,res_6_e,res_6_h,res_6_l,res_6_xhl,res_6_a, - res_7_b,res_7_c,res_7_d,res_7_e,res_7_h,res_7_l,res_7_xhl,res_7_a, - set_0_b,set_0_c,set_0_d,set_0_e,set_0_h,set_0_l,set_0_xhl,set_0_a, - set_1_b,set_1_c,set_1_d,set_1_e,set_1_h,set_1_l,set_1_xhl,set_1_a, - set_2_b,set_2_c,set_2_d,set_2_e,set_2_h,set_2_l,set_2_xhl,set_2_a, - set_3_b,set_3_c,set_3_d,set_3_e,set_3_h,set_3_l,set_3_xhl,set_3_a, - set_4_b,set_4_c,set_4_d,set_4_e,set_4_h,set_4_l,set_4_xhl,set_4_a, - set_5_b,set_5_c,set_5_d,set_5_e,set_5_h,set_5_l,set_5_xhl,set_5_a, - set_6_b,set_6_c,set_6_d,set_6_e,set_6_h,set_6_l,set_6_xhl,set_6_a, - set_7_b,set_7_c,set_7_d,set_7_e,set_7_h,set_7_l,set_7_xhl,set_7_a -}; - -static opcode_fn opcode_dd[256]= -{ - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,add_ix_bc ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,add_ix_de ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,ld_ix_word,ld_xword_ix,inc_ix ,inc_ixh ,dec_ixh ,ld_ixh_byte,no_op , - no_op ,add_ix_ix ,ld_ix_xword,dec_ix ,inc_ixl ,dec_ixl ,ld_ixl_byte,no_op , - no_op ,no_op ,no_op ,no_op ,inc_xix ,dec_xix ,ld_xix_byte,no_op , - no_op ,add_ix_sp ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_b_ixh ,ld_b_ixl ,ld_b_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_c_ixh ,ld_c_ixl ,ld_c_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_d_ixh ,ld_d_ixl ,ld_d_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_e_ixh ,ld_e_ixl ,ld_e_xix ,no_op , - ld_ixh_b,ld_ixh_c ,ld_ixh_d ,ld_ixh_e ,ld_ixh_ixh ,ld_ixh_ixl ,ld_h_xix ,ld_ixh_a, - ld_ixl_b,ld_ixl_c ,ld_ixl_d ,ld_ixl_e ,ld_ixl_ixh ,ld_ixl_ixl ,ld_l_xix ,ld_ixl_a, - ld_xix_b,ld_xix_c ,ld_xix_d ,ld_xix_e ,ld_xix_h ,ld_xix_l ,no_op ,ld_xix_a, - no_op ,no_op ,no_op ,no_op ,ld_a_ixh ,ld_a_ixl ,ld_a_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,add_a_ixh ,add_a_ixl ,add_a_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,adc_a_ixh ,adc_a_ixl ,adc_a_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,sub_ixh ,sub_ixl ,sub_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,sbc_a_ixh ,sbc_a_ixl ,sbc_a_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,and_ixh ,and_ixl ,and_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,xor_ixh ,xor_ixl ,xor_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,or_ixh ,or_ixl ,or_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,cp_ixh ,cp_ixl ,cp_xix ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,dd_cb ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,pop_ix ,no_op ,ex_xsp_ix,no_op ,push_ix ,no_op ,no_op , - no_op ,jp_ix ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,ld_sp_ix ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op -}; - -static opcode_fn opcode_ed[256]= -{ - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - in_b_c,out_c_b,sbc_hl_bc,ld_xword_bc,neg,retn,im_0 ,ld_i_a, - in_c_c,out_c_c,adc_hl_bc,ld_bc_xword,neg,reti,im_0 ,ld_r_a, - in_d_c,out_c_d,sbc_hl_de,ld_xword_de,neg,retn,im_1 ,ld_a_i, - in_e_c,out_c_e,adc_hl_de,ld_de_xword,neg,reti,im_2 ,ld_a_r, - in_h_c,out_c_h,sbc_hl_hl,ld_xword_hl,neg,retn,im_0 ,rrd , - in_l_c,out_c_l,adc_hl_hl,ld_hl_xword,neg,reti,im_0 ,rld , - in_0_c,out_c_0,sbc_hl_sp,ld_xword_sp,neg,retn,im_1 ,nop , - in_a_c,out_c_a,adc_hl_sp,ld_sp_xword,neg,reti,im_2 ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - ldi ,cpi ,ini ,outi ,nop,nop ,nop ,nop , - ldd ,cpd ,ind ,outd ,nop,nop ,nop ,nop , - ldir ,cpir ,inir ,otir ,nop,nop ,nop ,nop , - lddr ,cpdr ,indr ,otdr ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,nop ,nop , - nop ,nop ,nop ,nop ,nop,nop ,patch,nop -}; - -static opcode_fn opcode_fd[256]= -{ - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,add_iy_bc ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,add_iy_de ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,ld_iy_word,ld_xword_iy,inc_iy ,inc_iyh ,dec_iyh ,ld_iyh_byte,no_op , - no_op ,add_iy_iy ,ld_iy_xword,dec_iy ,inc_iyl ,dec_iyl ,ld_iyl_byte,no_op , - no_op ,no_op ,no_op ,no_op ,inc_xiy ,dec_xiy ,ld_xiy_byte,no_op , - no_op ,add_iy_sp ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_b_iyh ,ld_b_iyl ,ld_b_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_c_iyh ,ld_c_iyl ,ld_c_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_d_iyh ,ld_d_iyl ,ld_d_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,ld_e_iyh ,ld_e_iyl ,ld_e_xiy ,no_op , - ld_iyh_b,ld_iyh_c ,ld_iyh_d ,ld_iyh_e ,ld_iyh_iyh ,ld_iyh_iyl ,ld_h_xiy ,ld_iyh_a, - ld_iyl_b,ld_iyl_c ,ld_iyl_d ,ld_iyl_e ,ld_iyl_iyh ,ld_iyl_iyl ,ld_l_xiy ,ld_iyl_a, - ld_xiy_b,ld_xiy_c ,ld_xiy_d ,ld_xiy_e ,ld_xiy_h ,ld_xiy_l ,no_op ,ld_xiy_a, - no_op ,no_op ,no_op ,no_op ,ld_a_iyh ,ld_a_iyl ,ld_a_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,add_a_iyh ,add_a_iyl ,add_a_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,adc_a_iyh ,adc_a_iyl ,adc_a_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,sub_iyh ,sub_iyl ,sub_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,sbc_a_iyh ,sbc_a_iyl ,sbc_a_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,and_iyh ,and_iyl ,and_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,xor_iyh ,xor_iyl ,xor_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,or_iyh ,or_iyl ,or_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,cp_iyh ,cp_iyl ,cp_xiy ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,fd_cb ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,pop_iy ,no_op ,ex_xsp_iy,no_op ,push_iy ,no_op ,no_op , - no_op ,jp_iy ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op , - no_op ,ld_sp_iy ,no_op ,no_op ,no_op ,no_op ,no_op ,no_op -}; - -static void cb(void) -{ - unsigned opcode; - ++R.R; - opcode=M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount+=cycles_cb[opcode]; - (*(opcode_cb[opcode]))(); -} -static void dd(void) -{ - unsigned opcode; - ++R.R; - opcode=M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount+=cycles_xx[opcode]; - (*(opcode_dd[opcode]))(); -} -static void ed(void) -{ - unsigned opcode; - ++R.R; - opcode=M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount+=cycles_ed[opcode]; - (*(opcode_ed[opcode]))(); -} -static void fd (void) -{ - unsigned opcode; - ++R.R; - opcode=M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount+=cycles_xx[opcode]; - (*(opcode_fd[opcode]))(); -} - -static opcode_fn opcode_main[256]= -{ - nop ,ld_bc_word,ld_xbc_a ,inc_bc ,inc_b ,dec_b ,ld_b_byte ,rlca , - ex_af_af,add_hl_bc ,ld_a_xbc ,dec_bc ,inc_c ,dec_c ,ld_c_byte ,rrca , - djnz ,ld_de_word,ld_xde_a ,inc_de ,inc_d ,dec_d ,ld_d_byte ,rla , - jr ,add_hl_de ,ld_a_xde ,dec_de ,inc_e ,dec_e ,ld_e_byte ,rra , - jr_nz ,ld_hl_word,ld_xword_hl,inc_hl ,inc_h ,dec_h ,ld_h_byte ,daa , - jr_z ,add_hl_hl ,ld_hl_xword,dec_hl ,inc_l ,dec_l ,ld_l_byte ,cpl , - jr_nc ,ld_sp_word,ld_xbyte_a ,inc_sp ,inc_xhl ,dec_xhl ,ld_xhl_byte,scf , - jr_c ,add_hl_sp ,ld_a_xbyte ,dec_sp ,inc_a ,dec_a ,ld_a_byte ,ccf , - ld_b_b ,ld_b_c ,ld_b_d ,ld_b_e ,ld_b_h ,ld_b_l ,ld_b_xhl ,ld_b_a , - ld_c_b ,ld_c_c ,ld_c_d ,ld_c_e ,ld_c_h ,ld_c_l ,ld_c_xhl ,ld_c_a , - ld_d_b ,ld_d_c ,ld_d_d ,ld_d_e ,ld_d_h ,ld_d_l ,ld_d_xhl ,ld_d_a , - ld_e_b ,ld_e_c ,ld_e_d ,ld_e_e ,ld_e_h ,ld_e_l ,ld_e_xhl ,ld_e_a , - ld_h_b ,ld_h_c ,ld_h_d ,ld_h_e ,ld_h_h ,ld_h_l ,ld_h_xhl ,ld_h_a , - ld_l_b ,ld_l_c ,ld_l_d ,ld_l_e ,ld_l_h ,ld_l_l ,ld_l_xhl ,ld_l_a , - ld_xhl_b,ld_xhl_c ,ld_xhl_d ,ld_xhl_e ,ld_xhl_h,ld_xhl_l,halt ,ld_xhl_a, - ld_a_b ,ld_a_c ,ld_a_d ,ld_a_e ,ld_a_h ,ld_a_l ,ld_a_xhl ,ld_a_a , - add_a_b ,add_a_c ,add_a_d ,add_a_e ,add_a_h ,add_a_l ,add_a_xhl ,add_a_a , - adc_a_b ,adc_a_c ,adc_a_d ,adc_a_e ,adc_a_h ,adc_a_l ,adc_a_xhl ,adc_a_a , - sub_b ,sub_c ,sub_d ,sub_e ,sub_h ,sub_l ,sub_xhl ,sub_a , - sbc_a_b ,sbc_a_c ,sbc_a_d ,sbc_a_e ,sbc_a_h ,sbc_a_l ,sbc_a_xhl ,sbc_a_a , - and_b ,and_c ,and_d ,and_e ,and_h ,and_l ,and_xhl ,and_a , - xor_b ,xor_c ,xor_d ,xor_e ,xor_h ,xor_l ,xor_xhl ,xor_a , - or_b ,or_c ,or_d ,or_e ,or_h ,or_l ,or_xhl ,or_a , - cp_b ,cp_c ,cp_d ,cp_e ,cp_h ,cp_l ,cp_xhl ,cp_a , - ret_nz ,pop_bc ,jp_nz ,jp ,call_nz ,push_bc ,add_a_byte ,rst_00 , - ret_z ,ret ,jp_z ,cb ,call_z ,call ,adc_a_byte ,rst_08 , - ret_nc ,pop_de ,jp_nc ,out_byte_a,call_nc ,push_de ,sub_byte ,rst_10 , - ret_c ,exx ,jp_c ,in_a_byte ,call_c ,dd ,sbc_a_byte ,rst_18 , - ret_po ,pop_hl ,jp_po ,ex_xsp_hl ,call_po ,push_hl ,and_byte ,rst_20 , - ret_pe ,jp_hl ,jp_pe ,ex_de_hl ,call_pe ,ed ,xor_byte ,rst_28 , - ret_p ,pop_af ,jp_p ,di ,call_p ,push_af ,or_byte ,rst_30 , - ret_m ,ld_sp_hl ,jp_m ,ei ,call_m ,fd ,cp_byte ,rst_38 -}; - -static void ei(void) -{ - unsigned opcode; - /* If interrupts were disabled, execute one more instruction and check the */ - /* IRQ line. If not, simply set interrupt flip-flop 2 */ - if (!R.IFF1) - { -#ifdef DEBUG - if (R.PC.D==Z80_Trap) Z80_Trace=1; - if (Z80_Trace) Z80_Debug(&R); -#endif - R.IFF1=R.IFF2=1; - ++R.R; - opcode=M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount+=cycles_main[opcode]; - (*(opcode_main[opcode]))(); - Interrupt(Z80_IRQ); - } - else - R.IFF2=1; -} - -/****************************************************************************/ -/* Reset registers to their initial values */ -/****************************************************************************/ -void Z80_Reset (void) -{ - memset (&R,0,sizeof(Z80_Regs)); - R.SP.D=0x0000; // [AppleWin] Modified from 0xF000 to 0x0000 - R.R=rand(); - Z80_ICount = 0; // [AppleWin] Modified from Z80_IPeriod to 0 -} - -/****************************************************************************/ -/* Initialise the various lookup tables used by the emulation code */ -/****************************************************************************/ -void InitTables (void) -{ - static int InitTables_virgin=1; - byte zs; - int i,p; - if (!InitTables_virgin) return; - InitTables_virgin=0; - for (i=0;i<256;++i) - { - zs=0; - if (i==0) - zs|=Z_FLAG; - if (i&0x80) - zs|=S_FLAG; - p=0; - if (i&1) ++p; - if (i&2) ++p; - if (i&4) ++p; - if (i&8) ++p; - if (i&16) ++p; - if (i&32) ++p; - if (i&64) ++p; - if (i&128) ++p; - PTable[i]=(p&1)? 0:V_FLAG; - ZSTable[i]=zs; - ZSPTable[i]=zs|PTable[i]; - } - for (i=0;i<256;++i) - { - ZSTable[i+256]=ZSTable[i]|C_FLAG; - ZSPTable[i+256]=ZSPTable[i]|C_FLAG; - PTable[i+256]=PTable[i]|C_FLAG; - } -} - -/****************************************************************************/ -/* Issue an interrupt if necessary */ -/****************************************************************************/ -static void Interrupt (int j) -{ - if (j==Z80_IGNORE_INT) return; - if (j==Z80_NMI_INT || R.IFF1) - { - /* Clear interrupt flip-flop 1 */ - R.IFF1=0; - /* Check if processor was halted */ - if (R.HALT) - { - ++R.PC.W.l; - R.HALT=0; - } - if (j==Z80_NMI_INT) - { - M_PUSH (PC); - R.PC.D=0x0066; - } - else - { - /* Interrupt mode 2. Call [R.I:databyte] */ - if (R.IM==2) - { - M_PUSH (PC); - R.PC.D=M_RDMEM_WORD((j&255)|(R.I<<8)); - } - else - /* Interrupt mode 1. RST 38h */ - if (R.IM==1) - { - Z80_ICount+=cycles_main[0xFF]; - (*(opcode_main[0xFF]))(); - } - else - /* Interrupt mode 0. We check for CALL and JP instructions, if neither */ - /* of these were found we assume a 1 byte opcode was placed on the */ - /* databus */ - { - switch (j&0xFF0000) - { - case 0xCD: - M_PUSH(PC); - case 0xC3: - R.PC.D=j&0xFFFF; - break; - default: - j&=255; - Z80_ICount+=cycles_main[j]; - (*(opcode_main[j]))(); - break; - } - } - } - } -} - -/****************************************************************************/ -/* Set all registers to given values */ -/****************************************************************************/ -void Z80_SetRegs (Z80_Regs *Regs) -{ - R=*Regs; -} - -/****************************************************************************/ -/* Get all registers in given buffer */ -/****************************************************************************/ -void Z80_GetRegs (Z80_Regs *Regs) -{ - *Regs=R; -} - -/****************************************************************************/ -/* Return program counter */ -/****************************************************************************/ -unsigned Z80_GetPC (void) -{ - return R.PC.D; -} - -#if 0 // [AppleWin] Not used -/****************************************************************************/ -/* Execute IPeriod T-States. Return 0 if emulation should be stopped */ -/****************************************************************************/ -int Z80_Execute (void) -{ - unsigned opcode; - Z80_Running=1; - InitTables (); - do - { -#ifdef TRACE - pc_trace[pc_count]=R.PC.D; - pc_count=(pc_count+1)&255; -#endif -#ifdef DEBUG - if (R.PC.D==Z80_Trap) Z80_Trace=1; - if (Z80_Trace) Z80_Debug(&R); - if (!Z80_Running) break; -#endif - ++R.R; - opcode=M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount-=cycles_main[opcode]; - (*(opcode_main[opcode]))(); - } - while (Z80_ICount>0); - Z80_ICount+=Z80_IPeriod; - Interrupt (Z80_Interrupt()); - return Z80_Running; -} - -/****************************************************************************/ -/* Interpret Z80 code */ -/****************************************************************************/ -word Z80 (void) -{ - while (Z80_Execute()); - return(R.PC.W.l); -} -#endif - -/****************************************************************************/ -/* Dump register contents and (optionally) a PC trace to stdout */ -/****************************************************************************/ -void Z80_RegisterDump (void) -{ - int i; - printf - ( - "AF:%04X HL:%04X DE:%04X BC:%04X PC:%04X SP:%04X IX:%04X IY:%04X\n", - R.AF.W.l,R.HL.W.l,R.DE.W.l,R.BC.W.l,R.PC.W.l,R.SP.W.l,R.IX.W.l,R.IY.W.l - ); - printf ("STACK: "); - for (i=0;i<10;++i) printf ("%04X ",M_RDMEM_WORD((R.SP.D+i*2)&0xFFFF)); - puts (""); -#ifdef TRACE - puts ("PC TRACE:"); - for (i=1;i<=256;++i) printf ("%04X\n",pc_trace[(pc_count-i)&255]); -#endif -} - -/****************************************************************************/ -/* Set number of memory refresh wait states (i.e. extra cycles inserted */ -/* when the refresh register is being incremented) */ -/****************************************************************************/ -void Z80_SetWaitStates (int n) -{ - int i; - for (i=0;i<256;++i) - { - cycles_main[i]+=n; - cycles_cb[i]+=n; - cycles_ed[i]+=n; - cycles_xx[i]+=n; - } -} - -// AppleWin additions: - -//=========================================================================== - -// NB. Z80_ICount can legitimately go -ve! - -static const double uZ80ClockMultiplier = CLK_Z80 / CLK_6502; -inline static ULONG ConvertZ80TStatesTo6502Cycles(UINT uTStates) -{ - return (uTStates < 0) ? 0 : (ULONG) ((double)uTStates / uZ80ClockMultiplier); -} - -DWORD InternalZ80Execute (ULONG totalcycles, ULONG uExecutedCycles) -{ - // Nb. If uExecutedCycles == 0 (single-step) then just execute a single opcode - - totalcycles = (ULONG) ((double)totalcycles * uZ80ClockMultiplier); - uExecutedCycles = (ULONG) ((double)uExecutedCycles * uZ80ClockMultiplier); - int cycles = uExecutedCycles; // Must be signed int, as cycles can go -ve - - do { -#ifdef CPUDEBUG // ...xxx...xxx - if (g_nCumulativeCycles > 0) fprintf(arquivocpu, "%4X\n", regs.pc); - fflush(arquivocpu); -#endif // Z80 -#ifdef TRACE - pc_trace[pc_count]=R.PC.D; - pc_count=(pc_count+1)&255; -#endif -#ifdef DEBUG - if (R.PC.D==Z80_Trap) Z80_Trace=1; - if (Z80_Trace) Z80_Debug(&R); -#endif - ++R.R; - unsigned int opcode = M_RDOP(R.PC.D); - R.PC.W.l++; - Z80_ICount = cycles; - Z80_ICount += cycles_main[opcode]; - (*(opcode_main[opcode]))(); - cycles = Z80_ICount; - if (g_ActiveCPU != CPU_Z80) - break; - } - while (cycles < (int)totalcycles); - - Interrupt (Z80_Interrupt()); - - return ConvertZ80TStatesTo6502Cycles(cycles - uExecutedCycles); -} - -// -// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE ----- -// - -// Implementação da CPU Z80: - -/****************************************************************************/ -/* Input a byte from given I/O port */ -/****************************************************************************/ -byte Z80_In (byte Port) -{ - return 0; -} - -/****************************************************************************/ -/* Output a byte to given I/O port */ -/****************************************************************************/ -void Z80_Out (byte Port,byte Value) -{ -} - -/****************************************************************************/ -/* Read a byte from given memory location */ -/****************************************************************************/ -unsigned Z80_RDMEM(DWORD Addr) -{ - WORD addr; - - switch (Addr / 0x1000) - { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - case 0x8: - case 0x9: - case 0xA: - addr = (WORD)Addr + 0x1000; - return CpuRead( addr, ConvertZ80TStatesTo6502Cycles(Z80_ICount) ); - break; - - case 0xB: - case 0xC: - case 0xD: - addr = (WORD)Addr + 0x2000; - return CpuRead( addr, ConvertZ80TStatesTo6502Cycles(Z80_ICount) ); - break; - - case 0xE: - addr = (WORD)Addr - 0x2000; - if ((addr & 0xF000) == 0xC000) - { - return IORead[(addr>>4) & 0xFF]( regs.pc, addr, 0, 0, ConvertZ80TStatesTo6502Cycles(Z80_ICount) ); - } - else - { - return *(mem+addr); - } - break; - - case 0xF: - addr = (WORD)Addr - 0xF000; - return CpuRead( addr, ConvertZ80TStatesTo6502Cycles(Z80_ICount) ); - break; - } - return 255; -} - -/****************************************************************************/ -/* Write a byte to given memory location */ -/****************************************************************************/ -void Z80_WRMEM(DWORD Addr, BYTE Value) -{ - unsigned int laddr; - WORD addr; - - laddr = Addr & 0x0FFF; - switch (Addr & 0xF000) - { - case 0x0000: addr = laddr+0x1000; break; - case 0x1000: addr = laddr+0x2000; break; - case 0x2000: addr = laddr+0x3000; break; - case 0x3000: addr = laddr+0x4000; break; - case 0x4000: addr = laddr+0x5000; break; - case 0x5000: addr = laddr+0x6000; break; - case 0x6000: addr = laddr+0x7000; break; - case 0x7000: addr = laddr+0x8000; break; - case 0x8000: addr = laddr+0x9000; break; - case 0x9000: addr = laddr+0xA000; break; - case 0xA000: addr = laddr+0xB000; break; - case 0xB000: addr = laddr+0xD000; break; - case 0xC000: addr = laddr+0xE000; break; - case 0xD000: addr = laddr+0xF000; break; - case 0xE000: addr = laddr+0xC000; break; - case 0xF000: addr = laddr+0x0000; break; - } - CpuWrite( addr, Value, ConvertZ80TStatesTo6502Cycles(Z80_ICount) ); -} - -/* Called when ED FE occurs. Can be used */ -/* to emulate disk access etc. */ -void Z80_Patch (Z80_Regs *Regs) -{ -} - -/* This is called after IPeriod T-States */ -/* have been executed. It should return */ -/* Z80_IGNORE_INT, Z80_NMI_INT or a byte */ -/* identifying the device (most often */ -/* 0xFF) */ -int Z80_Interrupt(void) -{ - return Z80_IGNORE_INT; -} - -/* Called when RETI occurs */ -void Z80_Reti (void) -{ -} - -/* Called when RETN occurs */ -void Z80_Retn (void) -{ -} - diff --git a/AppleWin/source/Z80/z80.h b/AppleWin/source/Z80/z80.h deleted file mode 100644 index f96bf5b9..00000000 --- a/AppleWin/source/Z80/z80.h +++ /dev/null @@ -1,146 +0,0 @@ -/*** Z80Em: Portable Z80 emulator *******************************************/ -/*** ***/ -/*** Z80.h ***/ -/*** ***/ -/*** This file contains the function prototypes and variable declarations ***/ -/*** ***/ -/*** Copyright (C) Marcel de Kogel 1996,1997 ***/ -/*** You are not allowed to distribute this software commercially ***/ -/*** Please, notify me, if you make any changes to this file ***/ -/****************************************************************************/ - -#pragma once - -/****************************************************************************/ -/*** Machine dependent definitions ***/ -/****************************************************************************/ -/* #define DEBUG */ /* Compile debugging version */ -/* #define X86_ASM */ /* Compile optimised GCC/x86 version */ - #define LSB_FIRST /* Compile for low-endian CPU */ -/* #define __64BIT__ */ /* Compile for 64 bit machines */ -/* #define __128BIT__ */ /* Compile for 128 bit machines */ - -/****************************************************************************/ -/* If your compiler doesn't know about inlined functions, uncomment this */ -/****************************************************************************/ -/* #define INLINE static */ - -#ifndef EMU_TYPES -#define EMU_TYPES - -/****************************************************************************/ -/* sizeof(byte)=1, sizeof(word)=2, sizeof(dword)>=4 */ -/****************************************************************************/ -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned dword; -typedef signed char offset; - -/****************************************************************************/ -/* Define a Z80 word. Upper bytes are always zero */ -/****************************************************************************/ -typedef union -{ -#ifdef __128BIT__ - #ifdef LSB_FIRST - struct { byte l,h,h2,h3,h4,h5,h6,h7, - h8,h9,h10,h11,h12,h13,h14,h15; } B; - struct { word l,h,h2,h3,h4,h5,h6,h7; } W; - dword D; - #else - struct { byte h15,h14,h13,h12,h11,h10,h9,h8, - h7,h6,h5,h4,h3,h2,h,l; } B; - struct { word h7,h6,h5,h4,h3,h2,h,l; } W; - dword D; - #endif -#elif __64BIT__ - #ifdef LSB_FIRST - struct { byte l,h,h2,h3,h4,h5,h6,h7; } B; - struct { word l,h,h2,h3; } W; - dword D; - #else - struct { byte h7,h6,h5,h4,h3,h2,h,l; } B; - struct { word h3,h2,h,l; } W; - dword D; - #endif -#else - #ifdef LSB_FIRST - struct { byte l,h,h2,h3; } B; - struct { word l,h; } W; - dword D; - #else - struct { byte h3,h2,h,l; } B; - struct { word h,l; } W; - dword D; - #endif -#endif -} regpair; - -#endif /* EMU_TYPES */ - -/****************************************************************************/ -/*** End of machine dependent definitions ***/ -/****************************************************************************/ - -#ifndef INLINE -#define INLINE static inline -#endif - -/****************************************************************************/ -/* The Z80 registers. HALT is set to 1 when the CPU is halted, the refresh */ -/* register is calculated as follows: refresh=(Regs.R&127)|(Regs.R2&128) */ -/****************************************************************************/ -typedef struct -{ - regpair AF,BC,DE,HL,IX,IY,PC,SP; - regpair AF2,BC2,DE2,HL2; - unsigned IFF1,IFF2,HALT,IM,I,R,R2; -} Z80_Regs; - -/****************************************************************************/ -/* Set Z80_Trace to 1 when PC==Z80_Trap. When trace is on, Z80_Debug() is */ -/* called after every instruction */ -/****************************************************************************/ -#ifdef DEBUG -extern int Z80_Trace; -extern int Z80_Trap; -void Z80_Debug(Z80_Regs *R); -#endif - -extern int Z80_Running; /* When 0, emulation terminates */ -extern int Z80_IPeriod; /* Number of T-states per interrupt */ -extern int Z80_ICount; /* T-state count */ -extern int Z80_IRQ; /* Current IRQ status. Checked after EI occurs */ - -#define Z80_IGNORE_INT -1 /* Ignore interrupt */ -#define Z80_NMI_INT -2 /* Execute NMI */ - -DWORD InternalZ80Execute (ULONG totalcycles, ULONG uExecutedCycles); -unsigned Z80_GetPC (void); /* Get program counter */ -void InitTables (void); -void Z80_GetRegs (Z80_Regs *Regs); /* Get registers */ -void Z80_SetRegs (Z80_Regs *Regs); /* Set registers */ -void Z80_Reset (void); /* Reset registers to the initial values */ -//int Z80_Execute (void); /* Execute IPeriod T-States */ -word Z80 (void); /* Execute until Z80_Running==0 */ -void Z80_RegisterDump (void); /* Prints a dump to stdout */ -void Z80_SetWaitStates (int n); /* Set number of memory wait states. */ - /* This only affects opcode fetching, so */ - /* wait state adjustment is still */ - /* necessary in Z80_RDMEM, Z80_RDOP_ARG, */ - /* Z80_RDSTACK and Z80_WRSTACK */ -void Z80_Patch (Z80_Regs *Regs); /* Called when ED FE occurs. Can be used */ - /* to emulate disk access etc. */ -int Z80_Interrupt(void); /* This is called after IPeriod T-States */ - /* have been executed. It should return */ - /* Z80_IGNORE_INT, Z80_NMI_INT or a byte */ - /* identifying the device (most often */ - /* 0xFF) */ -void Z80_Reti (void); /* Called when RETI occurs */ -void Z80_Retn (void); /* Called when RETN occurs */ - -/****************************************************************************/ -/* Definitions of functions to read/write memory and I/O ports */ -/* You can replace these with your own, inlined if necessary */ -/****************************************************************************/ -#include "Z80IO.h" diff --git a/AppleWin/source/Z80/z80codes.h b/AppleWin/source/Z80/z80codes.h deleted file mode 100644 index c047e5ca..00000000 --- a/AppleWin/source/Z80/z80codes.h +++ /dev/null @@ -1,219 +0,0 @@ -/*** Z80Em: Portable Z80 emulator *******************************************/ -/*** ***/ -/*** Z80Codes.h ***/ -/*** ***/ -/*** This file contains various macros used by the emulation engine ***/ -/*** ***/ -/*** Copyright (C) Marcel de Kogel 1996,1997 ***/ -/*** You are not allowed to distribute this software commercially ***/ -/*** Please, notify me, if you make any changes to this file ***/ -/****************************************************************************/ - -#define M_POP(Rg) \ - R.Rg.D=M_RDSTACK(R.SP.D)+(M_RDSTACK((R.SP.D+1)&65535)<<8); \ - R.SP.W.l+=2 -#define M_PUSH(Rg) \ - R.SP.W.l-=2; \ - M_WRSTACK(R.SP.D,R.Rg.D); \ - M_WRSTACK((R.SP.D+1)&65535,R.Rg.D>>8) -#define M_CALL \ -{ \ - int q; \ - q=M_RDMEM_OPCODE_WORD(); \ - M_PUSH(PC); \ - R.PC.D=q; \ - Z80_ICount-=7; \ -} -#define M_JP \ - R.PC.D=M_RDOP_ARG(R.PC.D)+((M_RDOP_ARG((R.PC.D+1)&65535))<<8) -#define M_JR \ - R.PC.W.l+=((offset)M_RDOP_ARG(R.PC.D))+1; Z80_ICount-=5 -#define M_RET M_POP(PC); Z80_ICount-=6 -#define M_RST(Addr) M_PUSH(PC); R.PC.D=Addr -#define M_SET(Bit,Reg) Reg|=1<>7); \ - R.AF.B.l=(R.AF.B.l&0xEC)|(R.AF.B.h&C_FLAG) - -#define M_RRCA \ - R.AF.B.l=(R.AF.B.l&0xEC)|(R.AF.B.h&0x01); \ - R.AF.B.h=(R.AF.B.h>>1)|(R.AF.B.h<<7) - -#define M_RLA \ -{ \ - int i; \ - i=R.AF.B.l&C_FLAG; \ - R.AF.B.l=(R.AF.B.l&0xEC)|((R.AF.B.h&0x80)>>7); \ - R.AF.B.h=(R.AF.B.h<<1)|i; \ -} - -#define M_RRA \ -{ \ - int i; \ - i=R.AF.B.l&C_FLAG; \ - R.AF.B.l=(R.AF.B.l&0xEC)|(R.AF.B.h&0x01); \ - R.AF.B.h=(R.AF.B.h>>1)|(i<<7); \ -} - -#define M_RLC(Reg) \ -{ \ - int q; \ - q=Reg>>7; \ - Reg=(Reg<<1)|q; \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_RRC(Reg) \ -{ \ - int q; \ - q=Reg&1; \ - Reg=(Reg>>1)|(q<<7); \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_RL(Reg) \ -{ \ - int q; \ - q=Reg>>7; \ - Reg=(Reg<<1)|(R.AF.B.l&1); \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_RR(Reg) \ -{ \ - int q; \ - q=Reg&1; \ - Reg=(Reg>>1)|(R.AF.B.l<<7); \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_SLL(Reg) \ -{ \ - int q; \ - q=Reg>>7; \ - Reg=(Reg<<1)|1; \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_SLA(Reg) \ -{ \ - int q; \ - q=Reg>>7; \ - Reg<<=1; \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_SRL(Reg) \ -{ \ - int q; \ - q=Reg&1; \ - Reg>>=1; \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} -#define M_SRA(Reg) \ -{ \ - int q; \ - q=Reg&1; \ - Reg=(Reg>>1)|(Reg&0x80); \ - R.AF.B.l=ZSPTable[Reg]|q; \ -} - -#define M_INC(Reg) \ - ++Reg; \ - R.AF.B.l=(R.AF.B.l&C_FLAG)|ZSTable[Reg]| \ - ((Reg==0x80)?V_FLAG:0)|((Reg&0x0F)?0:H_FLAG) - -#define M_DEC(Reg) \ - R.AF.B.l=(R.AF.B.l&C_FLAG)|N_FLAG| \ - ((Reg==0x80)?V_FLAG:0)|((Reg&0x0F)?0:H_FLAG); \ - R.AF.B.l|=ZSTable[--Reg] - -#define M_ADD(Reg) \ -{ \ - int q; \ - q=R.AF.B.h+Reg; \ - R.AF.B.l=ZSTable[q&255]|((q&256)>>8)| \ - ((R.AF.B.h^q^Reg)&H_FLAG)| \ - (((Reg^R.AF.B.h^0x80)&(Reg^q)&0x80)>>5); \ - R.AF.B.h=q; \ -} - -#define M_ADC(Reg) \ -{ \ - int q; \ - q=R.AF.B.h+Reg+(R.AF.B.l&1); \ - R.AF.B.l=ZSTable[q&255]|((q&256)>>8)| \ - ((R.AF.B.h^q^Reg)&H_FLAG)| \ - (((Reg^R.AF.B.h^0x80)&(Reg^q)&0x80)>>5); \ - R.AF.B.h=q; \ -} - -#define M_SUB(Reg) \ -{ \ - int q; \ - q=R.AF.B.h-Reg; \ - R.AF.B.l=ZSTable[q&255]|((q&256)>>8)|N_FLAG| \ - ((R.AF.B.h^q^Reg)&H_FLAG)| \ - (((Reg^R.AF.B.h)&(Reg^q)&0x80)>>5); \ - R.AF.B.h=q; \ -} - -#define M_SBC(Reg) \ -{ \ - int q; \ - q=R.AF.B.h-Reg-(R.AF.B.l&1); \ - R.AF.B.l=ZSTable[q&255]|((q&256)>>8)|N_FLAG| \ - ((R.AF.B.h^q^Reg)&H_FLAG)| \ - (((Reg^R.AF.B.h)&(Reg^q)&0x80)>>5); \ - R.AF.B.h=q; \ -} - -#define M_CP(Reg) \ -{ \ - int q; \ - q=R.AF.B.h-Reg; \ - R.AF.B.l=ZSTable[q&255]|((q&256)>>8)|N_FLAG| \ - ((R.AF.B.h^q^Reg)&H_FLAG)| \ - (((Reg^R.AF.B.h)&(Reg^q)&0x80)>>5); \ -} - -#define M_ADDW(Reg1,Reg2) \ -{ \ - int q; \ - q=R.Reg1.D+R.Reg2.D; \ - R.AF.B.l=(R.AF.B.l&(S_FLAG|Z_FLAG|V_FLAG))| \ - (((R.Reg1.D^q^R.Reg2.D)&0x1000)>>8)| \ - ((q>>16)&1); \ - R.Reg1.W.l=q; \ -} - -#define M_ADCW(Reg) \ -{ \ - int q; \ - q=R.HL.D+R.Reg.D+(R.AF.D&1); \ - R.AF.B.l=(((R.HL.D^q^R.Reg.D)&0x1000)>>8)| \ - ((q>>16)&1)| \ - ((q&0x8000)>>8)| \ - ((q&65535)?0:Z_FLAG)| \ - (((R.Reg.D^R.HL.D^0x8000)&(R.Reg.D^q)&0x8000)>>13); \ - R.HL.W.l=q; \ -} - -#define M_SBCW(Reg) \ -{ \ - int q; \ - q=R.HL.D-R.Reg.D-(R.AF.D&1); \ - R.AF.B.l=(((R.HL.D^q^R.Reg.D)&0x1000)>>8)| \ - ((q>>16)&1)| \ - ((q&0x8000)>>8)| \ - ((q&65535)?0:Z_FLAG)| \ - (((R.Reg.D^R.HL.D)&(R.Reg.D^q)&0x8000)>>13)| \ - N_FLAG; \ - R.HL.W.l=q; \ -} - diff --git a/AppleWin/source/Z80/z80daa.h b/AppleWin/source/Z80/z80daa.h deleted file mode 100644 index b1a3c0ba..00000000 --- a/AppleWin/source/Z80/z80daa.h +++ /dev/null @@ -1,2063 +0,0 @@ -/*** Z80Em: Portable Z80 emulator *******************************************/ -/*** ***/ -/*** Z80DAA.h ***/ -/*** ***/ -/*** This file contains the DAA emulation lookup table. It is included ***/ -/*** from Z80.c ***/ -/*** ***/ -/*** Copyright (C) Marcel de Kogel 1996,1997 ***/ -/*** You are not allowed to distribute this software commercially ***/ -/*** Please, notify me, if you make any changes to this file ***/ -/****************************************************************************/ - -static short DAATable[2048]= -{ -68, -256, -512, -772, -1024, -1284, -1540, -1792, -2056, -2316, -4112, -4372, -4628, -4880, -5140, -5392, -4096, -4356, -4612, -4864, -5124, -5376, -5632, -5892, -6156, -6408, -8240, -8500, -8756, -9008, -9268, -9520, -8224, -8484, -8740, -8992, -9252, -9504, -9760, -10020, -10284, -10536, -12340, -12592, -12848, -13108, -13360, -13620, -12324, -12576, -12832, -13092, -13344, -13604, -13860, -14112, -14376, -14636, -16400, -16660, -16916, -17168, -17428, -17680, -16384, -16644, -16900, -17152, -17412, -17664, -17920, -18180, -18444, -18696, -20500, -20752, -21008, -21268, -21520, -21780, -20484, -20736, -20992, -21252, -21504, -21764, -22020, -22272, -22536, -22796, -24628, -24880, -25136, -25396, -25648, -25908, -24612, -24864, -25120, -25380, -25632, -25892, -26148, -26400, -26664, -26924, -28720, -28980, -29236, -29488, -29748, -30000, -28704, -28964, -29220, -29472, -29732, -29984, -30240, -30500, -30764, -31016, --32624, --32364, --32108, --31856, --31596, --31344, --32640, --32380, --32124, --31872, --31612, --31360, --31104, --30844, --30580, --30328, --28524, --28272, --28016, --27756, --27504, --27244, --28540, --28288, --28032, --27772, --27520, --27260, --27004, --26752, --26488, --26228, -85, -273, -529, -789, -1041, -1301, -69, -257, -513, -773, -1025, -1285, -1541, -1793, -2057, -2317, -4113, -4373, -4629, -4881, -5141, -5393, -4097, -4357, -4613, -4865, -5125, -5377, -5633, -5893, -6157, -6409, -8241, -8501, -8757, -9009, -9269, -9521, -8225, -8485, -8741, -8993, -9253, -9505, -9761, -10021, -10285, -10537, -12341, -12593, -12849, -13109, -13361, -13621, -12325, -12577, -12833, -13093, -13345, -13605, -13861, -14113, -14377, -14637, -16401, -16661, -16917, -17169, -17429, -17681, -16385, -16645, -16901, -17153, -17413, -17665, -17921, -18181, -18445, -18697, -20501, -20753, -21009, -21269, -21521, -21781, -20485, -20737, -20993, -21253, -21505, -21765, -22021, -22273, -22537, -22797, -24629, -24881, -25137, -25397, -25649, -25909, -24613, -24865, -25121, -25381, -25633, -25893, -26149, -26401, -26665, -26925, -28721, -28981, -29237, -29489, -29749, -30001, -28705, -28965, -29221, -29473, -29733, -29985, -30241, -30501, -30765, -31017, --32623, --32363, --32107, --31855, --31595, --31343, --32639, --32379, --32123, --31871, --31611, --31359, --31103, --30843, --30579, --30327, --28523, --28271, --28015, --27755, --27503, --27243, --28539, --28287, --28031, --27771, --27519, --27259, --27003, --26751, --26487, --26227, --24395, --24143, --23887, --23627, --23375, --23115, --24411, --24159, --23903, --23643, --23391, --23131, --22875, --22623, --22359, --22099, --20303, --20043, --19787, --19535, --19275, --19023, --20319, --20059, --19803, --19551, --19291, --19039, --18783, --18523, --18259, --18007, --16235, --15983, --15727, --15467, --15215, --14955, --16251, --15999, --15743, --15483, --15231, --14971, --14715, --14463, --14199, --13939, --12143, --11883, --11627, --11375, --11115, --10863, --12159, --11899, --11643, --11391, --11131, --10879, --10623, --10363, --10099, --9847, --8015, --7755, --7499, --7247, --6987, --6735, --8031, --7771, --7515, --7263, --7003, --6751, --6495, --6235, --5971, --5719, --3915, --3663, --3407, --3147, --2895, --2635, --3931, --3679, --3423, --3163, --2911, --2651, --2395, --2143, --1879, --1619, -85, -273, -529, -789, -1041, -1301, -69, -257, -513, -773, -1025, -1285, -1541, -1793, -2057, -2317, -4113, -4373, -4629, -4881, -5141, -5393, -4097, -4357, -4613, -4865, -5125, -5377, -5633, -5893, -6157, -6409, -8241, -8501, -8757, -9009, -9269, -9521, -8225, -8485, -8741, -8993, -9253, -9505, -9761, -10021, -10285, -10537, -12341, -12593, -12849, -13109, -13361, -13621, -12325, -12577, -12833, -13093, -13345, -13605, -13861, -14113, -14377, -14637, -16401, -16661, -16917, -17169, -17429, -17681, -16385, -16645, -16901, -17153, -17413, -17665, -17921, -18181, -18445, -18697, -20501, -20753, -21009, -21269, -21521, -21781, -20485, -20737, -20993, -21253, -21505, -21765, -22021, -22273, -22537, -22797, -24629, -24881, -25137, -25397, -25649, -25909, -1540, -1792, -2056, -2316, -2572, -2824, -3084, -3336, -3592, -3852, -4112, -4372, -4628, -4880, -5140, -5392, -5632, -5892, -6156, -6408, -6664, -6924, -7176, -7436, -7692, -7944, -8240, -8500, -8756, -9008, -9268, -9520, -9760, -10020, -10284, -10536, -10792, -11052, -11304, -11564, -11820, -12072, -12340, -12592, -12848, -13108, -13360, -13620, -13860, -14112, -14376, -14636, -14892, -15144, -15404, -15656, -15912, -16172, -16400, -16660, -16916, -17168, -17428, -17680, -17920, -18180, -18444, -18696, -18952, -19212, -19464, -19724, -19980, -20232, -20500, -20752, -21008, -21268, -21520, -21780, -22020, -22272, -22536, -22796, -23052, -23304, -23564, -23816, -24072, -24332, -24628, -24880, -25136, -25396, -25648, -25908, -26148, -26400, -26664, -26924, -27180, -27432, -27692, -27944, -28200, -28460, -28720, -28980, -29236, -29488, -29748, -30000, -30240, -30500, -30764, -31016, -31272, -31532, -31784, -32044, -32300, -32552, --32624, --32364, --32108, --31856, --31596, --31344, --31104, --30844, --30580, --30328, --30072, --29812, --29560, --29300, --29044, --28792, --28524, --28272, --28016, --27756, --27504, --27244, --27004, --26752, --26488, --26228, --25972, --25720, --25460, --25208, --24952, --24692, -85, -273, -529, -789, -1041, -1301, -1541, -1793, -2057, -2317, -2573, -2825, -3085, -3337, -3593, -3853, -4113, -4373, -4629, -4881, -5141, -5393, -5633, -5893, -6157, -6409, -6665, -6925, -7177, -7437, -7693, -7945, -8241, -8501, -8757, -9009, -9269, -9521, -9761, -10021, -10285, -10537, -10793, -11053, -11305, -11565, -11821, -12073, -12341, -12593, -12849, -13109, -13361, -13621, -13861, -14113, -14377, -14637, -14893, -15145, -15405, -15657, -15913, -16173, -16401, -16661, -16917, -17169, -17429, -17681, -17921, -18181, -18445, -18697, -18953, -19213, -19465, -19725, -19981, -20233, -20501, -20753, -21009, -21269, -21521, -21781, -22021, -22273, -22537, -22797, -23053, -23305, -23565, -23817, -24073, -24333, -24629, -24881, -25137, -25397, -25649, -25909, -26149, -26401, -26665, -26925, -27181, -27433, -27693, -27945, -28201, -28461, -28721, -28981, -29237, -29489, -29749, -30001, -30241, -30501, -30765, -31017, -31273, -31533, -31785, -32045, -32301, -32553, --32623, --32363, --32107, --31855, --31595, --31343, --31103, --30843, --30579, --30327, --30071, --29811, --29559, --29299, --29043, --28791, --28523, --28271, --28015, --27755, --27503, --27243, --27003, --26751, --26487, --26227, --25971, --25719, --25459, --25207, --24951, --24691, --24395, --24143, --23887, --23627, --23375, --23115, --22875, --22623, --22359, --22099, --21843, --21591, --21331, --21079, --20823, --20563, --20303, --20043, --19787, --19535, --19275, --19023, --18783, --18523, --18259, --18007, --17751, --17491, --17239, --16979, --16723, --16471, --16235, --15983, --15727, --15467, --15215, --14955, --14715, --14463, --14199, --13939, --13683, --13431, --13171, --12919, --12663, --12403, --12143, --11883, --11627, --11375, --11115, --10863, --10623, --10363, --10099, --9847, --9591, --9331, --9079, --8819, --8563, --8311, --8015, --7755, --7499, --7247, --6987, --6735, --6495, --6235, --5971, --5719, --5463, --5203, --4951, --4691, --4435, --4183, --3915, --3663, --3407, --3147, --2895, --2635, --2395, --2143, --1879, --1619, --1363, --1111, --851, --599, --343, --83, -85, -273, -529, -789, -1041, -1301, -1541, -1793, -2057, -2317, -2573, -2825, -3085, -3337, -3593, -3853, -4113, -4373, -4629, -4881, -5141, -5393, -5633, -5893, -6157, -6409, -6665, -6925, -7177, -7437, -7693, -7945, -8241, -8501, -8757, -9009, -9269, -9521, -9761, -10021, -10285, -10537, -10793, -11053, -11305, -11565, -11821, -12073, -12341, -12593, -12849, -13109, -13361, -13621, -13861, -14113, -14377, -14637, -14893, -15145, -15405, -15657, -15913, -16173, -16401, -16661, -16917, -17169, -17429, -17681, -17921, -18181, -18445, -18697, -18953, -19213, -19465, -19725, -19981, -20233, -20501, -20753, -21009, -21269, -21521, -21781, -22021, -22273, -22537, -22797, -23053, -23305, -23565, -23817, -24073, -24333, -24629, -24881, -25137, -25397, -25649, -25909, -70, -258, -514, -774, -1026, -1286, -1542, -1794, -2058, -2318, -1026, -1286, -1542, -1794, -2058, -2318, -4098, -4358, -4614, -4866, -5126, -5378, -5634, -5894, -6158, -6410, -5126, -5378, -5634, -5894, -6158, -6410, -8226, -8486, -8742, -8994, -9254, -9506, -9762, -10022, -10286, -10538, -9254, -9506, -9762, -10022, -10286, -10538, -12326, -12578, -12834, -13094, -13346, -13606, -13862, -14114, -14378, -14638, -13346, -13606, -13862, -14114, -14378, -14638, -16386, -16646, -16902, -17154, -17414, -17666, -17922, -18182, -18446, -18698, -17414, -17666, -17922, -18182, -18446, -18698, -20486, -20738, -20994, -21254, -21506, -21766, -22022, -22274, -22538, -22798, -21506, -21766, -22022, -22274, -22538, -22798, -24614, -24866, -25122, -25382, -25634, -25894, -26150, -26402, -26666, -26926, -25634, -25894, -26150, -26402, -26666, -26926, -28706, -28966, -29222, -29474, -29734, -29986, -30242, -30502, -30766, -31018, -29734, -29986, -30242, -30502, -30766, -31018, --32638, --32378, --32122, --31870, --31610, --31358, --31102, --30842, --30578, --30326, --31610, --31358, --31102, --30842, --30578, --30326, --28538, --28286, --28030, --27770, --27518, --27258, --27002, --26750, --26486, --26226, -13347, -13607, -13863, -14115, -14379, -14639, -16387, -16647, -16903, -17155, -17415, -17667, -17923, -18183, -18447, -18699, -17415, -17667, -17923, -18183, -18447, -18699, -20487, -20739, -20995, -21255, -21507, -21767, -22023, -22275, -22539, -22799, -21507, -21767, -22023, -22275, -22539, -22799, -24615, -24867, -25123, -25383, -25635, -25895, -26151, -26403, -26667, -26927, -25635, -25895, -26151, -26403, -26667, -26927, -28707, -28967, -29223, -29475, -29735, -29987, -30243, -30503, -30767, -31019, -29735, -29987, -30243, -30503, -30767, -31019, --32637, --32377, --32121, --31869, --31609, --31357, --31101, --30841, --30577, --30325, --31609, --31357, --31101, --30841, --30577, --30325, --28537, --28285, --28029, --27769, --27517, --27257, --27001, --26749, --26485, --26225, --27517, --27257, --27001, --26749, --26485, --26225, --24409, --24157, --23901, --23641, --23389, --23129, --22873, --22621, --22357, --22097, --23389, --23129, --22873, --22621, --22357, --22097, --20317, --20057, --19801, --19549, --19289, --19037, --18781, --18521, --18257, --18005, --19289, --19037, --18781, --18521, --18257, --18005, --16249, --15997, --15741, --15481, --15229, --14969, --14713, --14461, --14197, --13937, --15229, --14969, --14713, --14461, --14197, --13937, --12157, --11897, --11641, --11389, --11129, --10877, --10621, --10361, --10097, --9845, --11129, --10877, --10621, --10361, --10097, --9845, --8029, --7769, --7513, --7261, --7001, --6749, --6493, --6233, --5969, --5717, --7001, --6749, --6493, --6233, --5969, --5717, --3929, --3677, --3421, --3161, --2909, --2649, --2393, --2141, --1877, --1617, --2909, --2649, --2393, --2141, --1877, --1617, -71, -259, -515, -775, -1027, -1287, -1543, -1795, -2059, -2319, -1027, -1287, -1543, -1795, -2059, -2319, -4099, -4359, -4615, -4867, -5127, -5379, -5635, -5895, -6159, -6411, -5127, -5379, -5635, -5895, -6159, -6411, -8227, -8487, -8743, -8995, -9255, -9507, -9763, -10023, -10287, -10539, -9255, -9507, -9763, -10023, -10287, -10539, -12327, -12579, -12835, -13095, -13347, -13607, -13863, -14115, -14379, -14639, -13347, -13607, -13863, -14115, -14379, -14639, -16387, -16647, -16903, -17155, -17415, -17667, -17923, -18183, -18447, -18699, -17415, -17667, -17923, -18183, -18447, -18699, -20487, -20739, -20995, -21255, -21507, -21767, -22023, -22275, -22539, -22799, -21507, -21767, -22023, -22275, -22539, -22799, -24615, -24867, -25123, -25383, -25635, -25895, -26151, -26403, -26667, -26927, -25635, -25895, -26151, -26403, -26667, -26927, -28707, -28967, -29223, -29475, -29735, -29987, -30243, -30503, -30767, -31019, -29735, -29987, -30243, -30503, -30767, -31019, --32637, --32377, --32121, --31869, --31609, --31357, --31101, --30841, --30577, --30325, --31609, --31357, --31101, --30841, --30577, --30325, --28537, --28285, --28029, --27769, --27517, --27257, --27001, --26749, --26485, --26225, --27517, --27257, --27001, --26749, --26485, --26225, --1346, --1094, --834, --582, --326, --66, -70, -258, -514, -774, -1026, -1286, -1542, -1794, -2058, -2318, -2590, -2842, -3102, -3354, -3610, -3870, -4098, -4358, -4614, -4866, -5126, -5378, -5634, -5894, -6158, -6410, -6682, -6942, -7194, -7454, -7710, -7962, -8226, -8486, -8742, -8994, -9254, -9506, -9762, -10022, -10286, -10538, -10810, -11070, -11322, -11582, -11838, -12090, -12326, -12578, -12834, -13094, -13346, -13606, -13862, -14114, -14378, -14638, -14910, -15162, -15422, -15674, -15930, -16190, -16386, -16646, -16902, -17154, -17414, -17666, -17922, -18182, -18446, -18698, -18970, -19230, -19482, -19742, -19998, -20250, -20486, -20738, -20994, -21254, -21506, -21766, -22022, -22274, -22538, -22798, -23070, -23322, -23582, -23834, -24090, -24350, -24614, -24866, -25122, -25382, -25634, -25894, -26150, -26402, -26666, -26926, -27198, -27450, -27710, -27962, -28218, -28478, -28706, -28966, -29222, -29474, -29734, -29986, -30242, -30502, -30766, -31018, -31290, -31550, -31802, -32062, -32318, -32570, --32638, --32378, --32122, --31870, --31610, --31358, --31102, --30842, --30578, --30326, --30054, --29794, --29542, --29282, --29026, --28774, --28538, --28286, --28030, --27770, -13347, -13607, -13863, -14115, -14379, -14639, -14911, -15163, -15423, -15675, -15931, -16191, -16387, -16647, -16903, -17155, -17415, -17667, -17923, -18183, -18447, -18699, -18971, -19231, -19483, -19743, -19999, -20251, -20487, -20739, -20995, -21255, -21507, -21767, -22023, -22275, -22539, -22799, -23071, -23323, -23583, -23835, -24091, -24351, -24615, -24867, -25123, -25383, -25635, -25895, -26151, -26403, -26667, -26927, -27199, -27451, -27711, -27963, -28219, -28479, -28707, -28967, -29223, -29475, -29735, -29987, -30243, -30503, -30767, -31019, -31291, -31551, -31803, -32063, -32319, -32571, --32637, --32377, --32121, --31869, --31609, --31357, --31101, --30841, --30577, --30325, --30053, --29793, --29541, --29281, --29025, --28773, --28537, --28285, --28029, --27769, --27517, --27257, --27001, --26749, --26485, --26225, --25953, --25701, --25441, --25189, --24933, --24673, --24409, --24157, --23901, --23641, --23389, --23129, --22873, --22621, --22357, --22097, --21825, --21573, --21313, --21061, --20805, --20545, --20317, --20057, --19801, --19549, --19289, --19037, --18781, --18521, --18257, --18005, --17733, --17473, --17221, --16961, --16705, --16453, --16249, --15997, --15741, --15481, --15229, --14969, --14713, --14461, --14197, --13937, --13665, --13413, --13153, --12901, --12645, --12385, --12157, --11897, --11641, --11389, --11129, --10877, --10621, --10361, --10097, --9845, --9573, --9313, --9061, --8801, --8545, --8293, --8029, --7769, --7513, --7261, --7001, --6749, --6493, --6233, --5969, --5717, --5445, --5185, --4933, --4673, --4417, --4165, --3929, --3677, --3421, --3161, --2909, --2649, --2393, --2141, --1877, --1617, --1345, --1093, --833, --581, --325, --65, -71, -259, -515, -775, -1027, -1287, -1543, -1795, -2059, -2319, -2591, -2843, -3103, -3355, -3611, -3871, -4099, -4359, -4615, -4867, -5127, -5379, -5635, -5895, -6159, -6411, -6683, -6943, -7195, -7455, -7711, -7963, -8227, -8487, -8743, -8995, -9255, -9507, -9763, -10023, -10287, -10539, -10811, -11071, -11323, -11583, -11839, -12091, -12327, -12579, -12835, -13095, -13347, -13607, -13863, -14115, -14379, -14639, -14911, -15163, -15423, -15675, -15931, -16191, -16387, -16647, -16903, -17155, -17415, -17667, -17923, -18183, -18447, -18699, -18971, -19231, -19483, -19743, -19999, -20251, -20487, -20739, -20995, -21255, -21507, -21767, -22023, -22275, -22539, -22799, -23071, -23323, -23583, -23835, -24091, -24351, -24615, -24867, -25123, -25383, -25635, -25895, -26151, -26403, -26667, -26927, -27199, -27451, -27711, -27963, -28219, -28479, -28707, -28967, -29223, -29475, -29735, -29987, -30243, -30503, -30767, -31019, -31291, -31551, -31803, -32063, -32319, -32571, --32637, --32377, --32121, --31869, --31609, --31357, --31101, --30841, --30577, --30325, --30053, --29793, --29541, --29281, --29025, --28773, --28537, --28285, --28029, --27769, --27517, --27257, --27001, --26749, --26485, --26225 -}; diff --git a/AppleWin/source/Z80/z80io.h b/AppleWin/source/Z80/z80io.h deleted file mode 100644 index 638aac9a..00000000 --- a/AppleWin/source/Z80/z80io.h +++ /dev/null @@ -1,70 +0,0 @@ -/*** Z80Em: Portable Z80 emulator *******************************************/ -/*** ***/ -/*** Z80IO.h ***/ -/*** ***/ -/*** This file contains the prototypes for the functions accessing memory ***/ -/*** and I/O ***/ -/*** ***/ -/*** Copyright (C) Marcel de Kogel 1996,1997 ***/ -/*** You are not allowed to distribute this software commercially ***/ -/*** Please, notify me, if you make any changes to this file ***/ -/****************************************************************************/ - -/****************************************************************************/ -/* Input a byte from given I/O port */ -/****************************************************************************/ -byte Z80_In (BYTE Port); - -/****************************************************************************/ -/* Output a byte to given I/O port */ -/****************************************************************************/ -void Z80_Out (BYTE Port,BYTE Value); - -/****************************************************************************/ -/* Read a byte from given memory location */ -/****************************************************************************/ -unsigned Z80_RDMEM(DWORD A); - -/****************************************************************************/ -/* Write a byte to given memory location */ -/****************************************************************************/ -void Z80_WRMEM(DWORD A,BYTE V); - -/****************************************************************************/ -/* Just to show you can actually use macros as well */ -/****************************************************************************/ -/* - extern byte *ReadPage[256]; - extern byte *WritePage[256]; - #define Z80_RDMEM(a) ReadPage[(a)>>8][(a)&0xFF] - #define Z80_WRMEM(a,v) WritePage[(a)>>8][(a)&0xFF]=v -*/ - -/****************************************************************************/ -/* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */ -/* opcodes. In case of system with memory mapped I/O, this function can be */ -/* used to greatly speed up emulation */ -/****************************************************************************/ -#define Z80_RDOP(A) Z80_RDMEM(A) - -/****************************************************************************/ -/* Z80_RDOP_ARG() is identical to Z80_RDOP() except it is used for reading */ -/* opcode arguments. This difference can be used to support systems that */ -/* use different encoding mechanisms for opcodes and opcode arguments */ -/****************************************************************************/ -#define Z80_RDOP_ARG(A) Z80_RDOP(A) - -/****************************************************************************/ -/* Z80_RDSTACK() is identical to Z80_RDMEM() except it is used for reading */ -/* stack variables. In case of system with memory mapped I/O, this function */ -/* can be used to slightly speed up emulation */ -/****************************************************************************/ -#define Z80_RDSTACK(A) Z80_RDMEM(A) - -/****************************************************************************/ -/* Z80_WRSTACK() is identical to Z80_WRMEM() except it is used for writing */ -/* stack variables. In case of system with memory mapped I/O, this function */ -/* can be used to slightly speed up emulation */ -/****************************************************************************/ -#define Z80_WRSTACK(A,V) Z80_WRMEM(A,V) - diff --git a/AppleWin/source/Z80VICE/daa.cpp b/AppleWin/source/Z80VICE/daa.cpp new file mode 100644 index 00000000..6618c479 --- /dev/null +++ b/AppleWin/source/Z80VICE/daa.cpp @@ -0,0 +1,547 @@ +/* + * daa.c + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#include "daa.h" +#include "..\CommonVICE\types.h" // [AppleWin-TC] + + +const BYTE daa_reg_a[2048] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x30,0x31,0x32,0x33,0x34,0x35, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x38,0x39,0x40,0x41,0x42,0x43,0x44,0x45, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x48,0x49,0x50,0x51,0x52,0x53,0x54,0x55, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x58,0x59,0x60,0x61,0x62,0x63,0x64,0x65, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x70,0x71,0x72,0x73,0x74,0x75, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x80,0x81,0x82,0x83,0x84,0x85, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x90,0x91,0x92,0x93,0x94,0x95, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, + 0x98,0x99,0x00,0x01,0x02,0x03,0x04,0x05, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x30,0x31,0x32,0x33,0x34,0x35, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x38,0x39,0x40,0x41,0x42,0x43,0x44,0x45, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x48,0x49,0x50,0x51,0x52,0x53,0x54,0x55, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x58,0x59,0x60,0x61,0x62,0x63,0x64,0x65, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x70,0x71,0x72,0x73,0x74,0x75, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x80,0x81,0x82,0x83,0x84,0x85, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x90,0x91,0x92,0x93,0x94,0x95, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, + 0x98,0x99,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5, + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7, + 0xA8,0xA9,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7, + 0xB8,0xB9,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, + 0xC8,0xC9,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7, + 0xD8,0xD9,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7, + 0xE8,0xE9,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7, + 0xF8,0xF9,0x00,0x01,0x02,0x03,0x04,0x05, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x30,0x31,0x32,0x33,0x34,0x35, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x38,0x39,0x40,0x41,0x42,0x43,0x44,0x45, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x48,0x49,0x50,0x51,0x52,0x53,0x54,0x55, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x58,0x59,0x60,0x61,0x62,0x63,0x64,0x65, + 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D, + 0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D, + 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25, + 0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, + 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, + 0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D, + 0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45, + 0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D, + 0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55, + 0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D, + 0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65, + 0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D, + 0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75, + 0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D, + 0x7E,0x7F,0x80,0x81,0x82,0x83,0x84,0x85, + 0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D, + 0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95, + 0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D, + 0x9E,0x9F,0x00,0x01,0x02,0x03,0x04,0x05, + 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D, + 0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D, + 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25, + 0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, + 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, + 0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D, + 0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45, + 0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D, + 0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55, + 0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D, + 0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65, + 0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D, + 0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75, + 0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D, + 0x7E,0x7F,0x80,0x81,0x82,0x83,0x84,0x85, + 0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D, + 0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95, + 0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D, + 0x9E,0x9F,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5, + 0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD, + 0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5, + 0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD, + 0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0xC5, + 0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD, + 0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5, + 0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD, + 0xDE,0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5, + 0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED, + 0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5, + 0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD, + 0xFE,0xFF,0x00,0x01,0x02,0x03,0x04,0x05, + 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D, + 0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D, + 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25, + 0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, + 0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, + 0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D, + 0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45, + 0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D, + 0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55, + 0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D, + 0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x04,0x05,0x06,0x07,0x08,0x09, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x14,0x15,0x16,0x17,0x18,0x19, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x24,0x25,0x26,0x27,0x28,0x29, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x38,0x39,0x34,0x35,0x36,0x37,0x38,0x39, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x48,0x49,0x44,0x45,0x46,0x47,0x48,0x49, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x58,0x59,0x54,0x55,0x56,0x57,0x58,0x59, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x64,0x65,0x66,0x67,0x68,0x69, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x74,0x75,0x76,0x77,0x78,0x79, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x84,0x85,0x86,0x87,0x88,0x89, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, + 0x98,0x99,0x34,0x35,0x36,0x37,0x38,0x39, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x48,0x49,0x44,0x45,0x46,0x47,0x48,0x49, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x58,0x59,0x54,0x55,0x56,0x57,0x58,0x59, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x64,0x65,0x66,0x67,0x68,0x69, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x74,0x75,0x76,0x77,0x78,0x79, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x84,0x85,0x86,0x87,0x88,0x89, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, + 0x98,0x99,0x94,0x95,0x96,0x97,0x98,0x99, + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7, + 0xA8,0xA9,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7, + 0xB8,0xB9,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7, + 0xC8,0xC9,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7, + 0xD8,0xD9,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7, + 0xE8,0xE9,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7, + 0xF8,0xF9,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x04,0x05,0x06,0x07,0x08,0x09, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x14,0x15,0x16,0x17,0x18,0x19, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x24,0x25,0x26,0x27,0x28,0x29, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x38,0x39,0x34,0x35,0x36,0x37,0x38,0x39, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x48,0x49,0x44,0x45,0x46,0x47,0x48,0x49, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x58,0x59,0x54,0x55,0x56,0x57,0x58,0x59, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x68,0x69,0x64,0x65,0x66,0x67,0x68,0x69, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, + 0x78,0x79,0x74,0x75,0x76,0x77,0x78,0x79, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x84,0x85,0x86,0x87,0x88,0x89, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, + 0x98,0x99,0x94,0x95,0x96,0x97,0x98,0x99, + 0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, + 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11, + 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21, + 0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + 0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31, + 0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41, + 0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51, + 0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61, + 0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71, + 0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79, + 0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81, + 0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91, + 0x92,0x93,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41, + 0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51, + 0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61, + 0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71, + 0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79, + 0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81, + 0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91, + 0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99, + 0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0,0xA1, + 0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9, + 0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1, + 0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, + 0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1, + 0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9, + 0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1, + 0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, + 0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1, + 0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9, + 0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1, + 0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9, + 0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x01, + 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11, + 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21, + 0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + 0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31, + 0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41, + 0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51, + 0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61, + 0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71, + 0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79, + 0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80,0x81, + 0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91, + 0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99 }; + +const BYTE daa_reg_f[2048] = { + 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x08,0x0C,0x10,0x14,0x14,0x10,0x14,0x10, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x0C,0x08,0x30,0x34,0x34,0x30,0x34,0x30, + 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24, + 0x2C,0x28,0x34,0x30,0x30,0x34,0x30,0x34, + 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20, + 0x28,0x2C,0x10,0x14,0x14,0x10,0x14,0x10, + 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04, + 0x0C,0x08,0x14,0x10,0x10,0x14,0x10,0x14, + 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00, + 0x08,0x0C,0x34,0x30,0x30,0x34,0x30,0x34, + 0x24,0x20,0x20,0x24,0x20,0x24,0x24,0x20, + 0x28,0x2C,0x30,0x34,0x34,0x30,0x34,0x30, + 0x20,0x24,0x24,0x20,0x24,0x20,0x20,0x24, + 0x2C,0x28,0x90,0x94,0x94,0x90,0x94,0x90, + 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84, + 0x8C,0x88,0x94,0x90,0x90,0x94,0x90,0x94, + 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80, + 0x88,0x8C,0x55,0x11,0x11,0x15,0x11,0x15, + 0x45,0x01,0x01,0x05,0x01,0x05,0x05,0x01, + 0x09,0x0D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x05,0x01,0x05,0x01,0x01,0x05, + 0x0D,0x09,0x31,0x35,0x35,0x31,0x35,0x31, + 0x21,0x25,0x25,0x21,0x25,0x21,0x21,0x25, + 0x2D,0x29,0x35,0x31,0x31,0x35,0x31,0x35, + 0x25,0x21,0x21,0x25,0x21,0x25,0x25,0x21, + 0x29,0x2D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x05,0x01,0x05,0x01,0x01,0x05, + 0x0D,0x09,0x15,0x11,0x11,0x15,0x11,0x15, + 0x05,0x01,0x01,0x05,0x01,0x05,0x05,0x01, + 0x09,0x0D,0x35,0x31,0x31,0x35,0x31,0x35, + 0x25,0x21,0x21,0x25,0x21,0x25,0x25,0x21, + 0x29,0x2D,0x31,0x35,0x35,0x31,0x35,0x31, + 0x21,0x25,0x25,0x21,0x25,0x21,0x21,0x25, + 0x2D,0x29,0x91,0x95,0x95,0x91,0x95,0x91, + 0x81,0x85,0x85,0x81,0x85,0x81,0x81,0x85, + 0x8D,0x89,0x95,0x91,0x91,0x95,0x91,0x95, + 0x85,0x81,0x81,0x85,0x81,0x85,0x85,0x81, + 0x89,0x8D,0xB5,0xB1,0xB1,0xB5,0xB1,0xB5, + 0xA5,0xA1,0xA1,0xA5,0xA1,0xA5,0xA5,0xA1, + 0xA9,0xAD,0xB1,0xB5,0xB5,0xB1,0xB5,0xB1, + 0xA1,0xA5,0xA5,0xA1,0xA5,0xA1,0xA1,0xA5, + 0xAD,0xA9,0x95,0x91,0x91,0x95,0x91,0x95, + 0x85,0x81,0x81,0x85,0x81,0x85,0x85,0x81, + 0x89,0x8D,0x91,0x95,0x95,0x91,0x95,0x91, + 0x81,0x85,0x85,0x81,0x85,0x81,0x81,0x85, + 0x8D,0x89,0xB1,0xB5,0xB5,0xB1,0xB5,0xB1, + 0xA1,0xA5,0xA5,0xA1,0xA5,0xA1,0xA1,0xA5, + 0xAD,0xA9,0xB5,0xB1,0xB1,0xB5,0xB1,0xB5, + 0xA5,0xA1,0xA1,0xA5,0xA1,0xA5,0xA5,0xA1, + 0xA9,0xAD,0x55,0x11,0x11,0x15,0x11,0x15, + 0x45,0x01,0x01,0x05,0x01,0x05,0x05,0x01, + 0x09,0x0D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x05,0x01,0x05,0x01,0x01,0x05, + 0x0D,0x09,0x31,0x35,0x35,0x31,0x35,0x31, + 0x21,0x25,0x25,0x21,0x25,0x21,0x21,0x25, + 0x2D,0x29,0x35,0x31,0x31,0x35,0x31,0x35, + 0x25,0x21,0x21,0x25,0x21,0x25,0x25,0x21, + 0x29,0x2D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x05,0x01,0x05,0x01,0x01,0x05, + 0x0D,0x09,0x15,0x11,0x11,0x15,0x11,0x15, + 0x05,0x01,0x01,0x05,0x01,0x05,0x05,0x01, + 0x09,0x0D,0x35,0x31,0x31,0x35,0x31,0x35, + 0x04,0x00,0x08,0x0C,0x0C,0x08,0x0C,0x08, + 0x08,0x0C,0x10,0x14,0x14,0x10,0x14,0x10, + 0x00,0x04,0x0C,0x08,0x08,0x0C,0x08,0x0C, + 0x0C,0x08,0x30,0x34,0x34,0x30,0x34,0x30, + 0x20,0x24,0x2C,0x28,0x28,0x2C,0x28,0x2C, + 0x2C,0x28,0x34,0x30,0x30,0x34,0x30,0x34, + 0x24,0x20,0x28,0x2C,0x2C,0x28,0x2C,0x28, + 0x28,0x2C,0x10,0x14,0x14,0x10,0x14,0x10, + 0x00,0x04,0x0C,0x08,0x08,0x0C,0x08,0x0C, + 0x0C,0x08,0x14,0x10,0x10,0x14,0x10,0x14, + 0x04,0x00,0x08,0x0C,0x0C,0x08,0x0C,0x08, + 0x08,0x0C,0x34,0x30,0x30,0x34,0x30,0x34, + 0x24,0x20,0x28,0x2C,0x2C,0x28,0x2C,0x28, + 0x28,0x2C,0x30,0x34,0x34,0x30,0x34,0x30, + 0x20,0x24,0x2C,0x28,0x28,0x2C,0x28,0x2C, + 0x2C,0x28,0x90,0x94,0x94,0x90,0x94,0x90, + 0x80,0x84,0x8C,0x88,0x88,0x8C,0x88,0x8C, + 0x8C,0x88,0x94,0x90,0x90,0x94,0x90,0x94, + 0x84,0x80,0x88,0x8C,0x8C,0x88,0x8C,0x88, + 0x88,0x8C,0x55,0x11,0x11,0x15,0x11,0x15, + 0x05,0x01,0x09,0x0D,0x0D,0x09,0x0D,0x09, + 0x09,0x0D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x0D,0x09,0x09,0x0D,0x09,0x0D, + 0x0D,0x09,0x31,0x35,0x35,0x31,0x35,0x31, + 0x21,0x25,0x2D,0x29,0x29,0x2D,0x29,0x2D, + 0x2D,0x29,0x35,0x31,0x31,0x35,0x31,0x35, + 0x25,0x21,0x29,0x2D,0x2D,0x29,0x2D,0x29, + 0x29,0x2D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x0D,0x09,0x09,0x0D,0x09,0x0D, + 0x0D,0x09,0x15,0x11,0x11,0x15,0x11,0x15, + 0x05,0x01,0x09,0x0D,0x0D,0x09,0x0D,0x09, + 0x09,0x0D,0x35,0x31,0x31,0x35,0x31,0x35, + 0x25,0x21,0x29,0x2D,0x2D,0x29,0x2D,0x29, + 0x29,0x2D,0x31,0x35,0x35,0x31,0x35,0x31, + 0x21,0x25,0x2D,0x29,0x29,0x2D,0x29,0x2D, + 0x2D,0x29,0x91,0x95,0x95,0x91,0x95,0x91, + 0x81,0x85,0x8D,0x89,0x89,0x8D,0x89,0x8D, + 0x8D,0x89,0x95,0x91,0x91,0x95,0x91,0x95, + 0x85,0x81,0x89,0x8D,0x8D,0x89,0x8D,0x89, + 0x89,0x8D,0xB5,0xB1,0xB1,0xB5,0xB1,0xB5, + 0xA5,0xA1,0xA9,0xAD,0xAD,0xA9,0xAD,0xA9, + 0xA9,0xAD,0xB1,0xB5,0xB5,0xB1,0xB5,0xB1, + 0xA1,0xA5,0xAD,0xA9,0xA9,0xAD,0xA9,0xAD, + 0xAD,0xA9,0x95,0x91,0x91,0x95,0x91,0x95, + 0x85,0x81,0x89,0x8D,0x8D,0x89,0x8D,0x89, + 0x89,0x8D,0x91,0x95,0x95,0x91,0x95,0x91, + 0x81,0x85,0x8D,0x89,0x89,0x8D,0x89,0x8D, + 0x8D,0x89,0xB1,0xB5,0xB5,0xB1,0xB5,0xB1, + 0xA1,0xA5,0xAD,0xA9,0xA9,0xAD,0xA9,0xAD, + 0xAD,0xA9,0xB5,0xB1,0xB1,0xB5,0xB1,0xB5, + 0xA5,0xA1,0xA9,0xAD,0xAD,0xA9,0xAD,0xA9, + 0xA9,0xAD,0x55,0x11,0x11,0x15,0x11,0x15, + 0x05,0x01,0x09,0x0D,0x0D,0x09,0x0D,0x09, + 0x09,0x0D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x0D,0x09,0x09,0x0D,0x09,0x0D, + 0x0D,0x09,0x31,0x35,0x35,0x31,0x35,0x31, + 0x21,0x25,0x2D,0x29,0x29,0x2D,0x29,0x2D, + 0x2D,0x29,0x35,0x31,0x31,0x35,0x31,0x35, + 0x25,0x21,0x29,0x2D,0x2D,0x29,0x2D,0x29, + 0x29,0x2D,0x11,0x15,0x15,0x11,0x15,0x11, + 0x01,0x05,0x0D,0x09,0x09,0x0D,0x09,0x0D, + 0x0D,0x09,0x15,0x11,0x11,0x15,0x11,0x15, + 0x05,0x01,0x09,0x0D,0x0D,0x09,0x0D,0x09, + 0x09,0x0D,0x35,0x31,0x31,0x35,0x31,0x35, + 0x46,0x02,0x02,0x06,0x02,0x06,0x06,0x02, + 0x0A,0x0E,0x02,0x06,0x06,0x02,0x0A,0x0E, + 0x02,0x06,0x06,0x02,0x06,0x02,0x02,0x06, + 0x0E,0x0A,0x06,0x02,0x02,0x06,0x0E,0x0A, + 0x22,0x26,0x26,0x22,0x26,0x22,0x22,0x26, + 0x2E,0x2A,0x26,0x22,0x22,0x26,0x2E,0x2A, + 0x26,0x22,0x22,0x26,0x22,0x26,0x26,0x22, + 0x2A,0x2E,0x22,0x26,0x26,0x22,0x2A,0x2E, + 0x02,0x06,0x06,0x02,0x06,0x02,0x02,0x06, + 0x0E,0x0A,0x06,0x02,0x02,0x06,0x0E,0x0A, + 0x06,0x02,0x02,0x06,0x02,0x06,0x06,0x02, + 0x0A,0x0E,0x02,0x06,0x06,0x02,0x0A,0x0E, + 0x26,0x22,0x22,0x26,0x22,0x26,0x26,0x22, + 0x2A,0x2E,0x22,0x26,0x26,0x22,0x2A,0x2E, + 0x22,0x26,0x26,0x22,0x26,0x22,0x22,0x26, + 0x2E,0x2A,0x26,0x22,0x22,0x26,0x2E,0x2A, + 0x82,0x86,0x86,0x82,0x86,0x82,0x82,0x86, + 0x8E,0x8A,0x86,0x82,0x82,0x86,0x8E,0x8A, + 0x86,0x82,0x82,0x86,0x82,0x86,0x86,0x82, + 0x8A,0x8E,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x03,0x07,0x07,0x03,0x07,0x03,0x03,0x07, + 0x0F,0x0B,0x07,0x03,0x03,0x07,0x0F,0x0B, + 0x07,0x03,0x03,0x07,0x03,0x07,0x07,0x03, + 0x0B,0x0F,0x03,0x07,0x07,0x03,0x0B,0x0F, + 0x27,0x23,0x23,0x27,0x23,0x27,0x27,0x23, + 0x2B,0x2F,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x23,0x27,0x27,0x23,0x27,0x23,0x23,0x27, + 0x2F,0x2B,0x27,0x23,0x23,0x27,0x2F,0x2B, + 0x83,0x87,0x87,0x83,0x87,0x83,0x83,0x87, + 0x8F,0x8B,0x87,0x83,0x83,0x87,0x8F,0x8B, + 0x87,0x83,0x83,0x87,0x83,0x87,0x87,0x83, + 0x8B,0x8F,0x83,0x87,0x87,0x83,0x8B,0x8F, + 0xA7,0xA3,0xA3,0xA7,0xA3,0xA7,0xA7,0xA3, + 0xAB,0xAF,0xA3,0xA7,0xA7,0xA3,0xAB,0xAF, + 0xA3,0xA7,0xA7,0xA3,0xA7,0xA3,0xA3,0xA7, + 0xAF,0xAB,0xA7,0xA3,0xA3,0xA7,0xAF,0xAB, + 0x87,0x83,0x83,0x87,0x83,0x87,0x87,0x83, + 0x8B,0x8F,0x83,0x87,0x87,0x83,0x8B,0x8F, + 0x83,0x87,0x87,0x83,0x87,0x83,0x83,0x87, + 0x8F,0x8B,0x87,0x83,0x83,0x87,0x8F,0x8B, + 0xA3,0xA7,0xA7,0xA3,0xA7,0xA3,0xA3,0xA7, + 0xAF,0xAB,0xA7,0xA3,0xA3,0xA7,0xAF,0xAB, + 0xA7,0xA3,0xA3,0xA7,0xA3,0xA7,0xA7,0xA3, + 0xAB,0xAF,0xA3,0xA7,0xA7,0xA3,0xAB,0xAF, + 0x47,0x03,0x03,0x07,0x03,0x07,0x07,0x03, + 0x0B,0x0F,0x03,0x07,0x07,0x03,0x0B,0x0F, + 0x03,0x07,0x07,0x03,0x07,0x03,0x03,0x07, + 0x0F,0x0B,0x07,0x03,0x03,0x07,0x0F,0x0B, + 0x23,0x27,0x27,0x23,0x27,0x23,0x23,0x27, + 0x2F,0x2B,0x27,0x23,0x23,0x27,0x2F,0x2B, + 0x27,0x23,0x23,0x27,0x23,0x27,0x27,0x23, + 0x2B,0x2F,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x03,0x07,0x07,0x03,0x07,0x03,0x03,0x07, + 0x0F,0x0B,0x07,0x03,0x03,0x07,0x0F,0x0B, + 0x07,0x03,0x03,0x07,0x03,0x07,0x07,0x03, + 0x0B,0x0F,0x03,0x07,0x07,0x03,0x0B,0x0F, + 0x27,0x23,0x23,0x27,0x23,0x27,0x27,0x23, + 0x2B,0x2F,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x23,0x27,0x27,0x23,0x27,0x23,0x23,0x27, + 0x2F,0x2B,0x27,0x23,0x23,0x27,0x2F,0x2B, + 0x83,0x87,0x87,0x83,0x87,0x83,0x83,0x87, + 0x8F,0x8B,0x87,0x83,0x83,0x87,0x8F,0x8B, + 0x87,0x83,0x83,0x87,0x83,0x87,0x87,0x83, + 0x8B,0x8F,0x83,0x87,0x87,0x83,0x8B,0x8F, + 0xBE,0xBA,0xBE,0xBA,0xBA,0xBE,0x46,0x02, + 0x02,0x06,0x02,0x06,0x06,0x02,0x0A,0x0E, + 0x1E,0x1A,0x1E,0x1A,0x1A,0x1E,0x02,0x06, + 0x06,0x02,0x06,0x02,0x02,0x06,0x0E,0x0A, + 0x1A,0x1E,0x1A,0x1E,0x1E,0x1A,0x22,0x26, + 0x26,0x22,0x26,0x22,0x22,0x26,0x2E,0x2A, + 0x3A,0x3E,0x3A,0x3E,0x3E,0x3A,0x26,0x22, + 0x22,0x26,0x22,0x26,0x26,0x22,0x2A,0x2E, + 0x3E,0x3A,0x3E,0x3A,0x3A,0x3E,0x02,0x06, + 0x06,0x02,0x06,0x02,0x02,0x06,0x0E,0x0A, + 0x1A,0x1E,0x1A,0x1E,0x1E,0x1A,0x06,0x02, + 0x02,0x06,0x02,0x06,0x06,0x02,0x0A,0x0E, + 0x1E,0x1A,0x1E,0x1A,0x1A,0x1E,0x26,0x22, + 0x22,0x26,0x22,0x26,0x26,0x22,0x2A,0x2E, + 0x3E,0x3A,0x3E,0x3A,0x3A,0x3E,0x22,0x26, + 0x26,0x22,0x26,0x22,0x22,0x26,0x2E,0x2A, + 0x3A,0x3E,0x3A,0x3E,0x3E,0x3A,0x82,0x86, + 0x86,0x82,0x86,0x82,0x82,0x86,0x8E,0x8A, + 0x9A,0x9E,0x9A,0x9E,0x9E,0x9A,0x86,0x82, + 0x82,0x86,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x3F,0x3B,0x3F,0x3B,0x3B,0x3F,0x03,0x07, + 0x07,0x03,0x07,0x03,0x03,0x07,0x0F,0x0B, + 0x1B,0x1F,0x1B,0x1F,0x1F,0x1B,0x07,0x03, + 0x03,0x07,0x03,0x07,0x07,0x03,0x0B,0x0F, + 0x1F,0x1B,0x1F,0x1B,0x1B,0x1F,0x27,0x23, + 0x23,0x27,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x3F,0x3B,0x3F,0x3B,0x3B,0x3F,0x23,0x27, + 0x27,0x23,0x27,0x23,0x23,0x27,0x2F,0x2B, + 0x3B,0x3F,0x3B,0x3F,0x3F,0x3B,0x83,0x87, + 0x87,0x83,0x87,0x83,0x83,0x87,0x8F,0x8B, + 0x9B,0x9F,0x9B,0x9F,0x9F,0x9B,0x87,0x83, + 0x83,0x87,0x83,0x87,0x87,0x83,0x8B,0x8F, + 0x9F,0x9B,0x9F,0x9B,0x9B,0x9F,0xA7,0xA3, + 0xA3,0xA7,0xA3,0xA7,0xA7,0xA3,0xAB,0xAF, + 0xBF,0xBB,0xBF,0xBB,0xBB,0xBF,0xA3,0xA7, + 0xA7,0xA3,0xA7,0xA3,0xA3,0xA7,0xAF,0xAB, + 0xBB,0xBF,0xBB,0xBF,0xBF,0xBB,0x87,0x83, + 0x83,0x87,0x83,0x87,0x87,0x83,0x8B,0x8F, + 0x9F,0x9B,0x9F,0x9B,0x9B,0x9F,0x83,0x87, + 0x87,0x83,0x87,0x83,0x83,0x87,0x8F,0x8B, + 0x9B,0x9F,0x9B,0x9F,0x9F,0x9B,0xA3,0xA7, + 0xA7,0xA3,0xA7,0xA3,0xA3,0xA7,0xAF,0xAB, + 0xBB,0xBF,0xBB,0xBF,0xBF,0xBB,0xA7,0xA3, + 0xA3,0xA7,0xA3,0xA7,0xA7,0xA3,0xAB,0xAF, + 0xBF,0xBB,0xBF,0xBB,0xBB,0xBF,0x47,0x03, + 0x03,0x07,0x03,0x07,0x07,0x03,0x0B,0x0F, + 0x1F,0x1B,0x1F,0x1B,0x1B,0x1F,0x03,0x07, + 0x07,0x03,0x07,0x03,0x03,0x07,0x0F,0x0B, + 0x1B,0x1F,0x1B,0x1F,0x1F,0x1B,0x23,0x27, + 0x27,0x23,0x27,0x23,0x23,0x27,0x2F,0x2B, + 0x3B,0x3F,0x3B,0x3F,0x3F,0x3B,0x27,0x23, + 0x23,0x27,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x3F,0x3B,0x3F,0x3B,0x3B,0x3F,0x03,0x07, + 0x07,0x03,0x07,0x03,0x03,0x07,0x0F,0x0B, + 0x1B,0x1F,0x1B,0x1F,0x1F,0x1B,0x07,0x03, + 0x03,0x07,0x03,0x07,0x07,0x03,0x0B,0x0F, + 0x1F,0x1B,0x1F,0x1B,0x1B,0x1F,0x27,0x23, + 0x23,0x27,0x23,0x27,0x27,0x23,0x2B,0x2F, + 0x3F,0x3B,0x3F,0x3B,0x3B,0x3F,0x23,0x27, + 0x27,0x23,0x27,0x23,0x23,0x27,0x2F,0x2B, + 0x3B,0x3F,0x3B,0x3F,0x3F,0x3B,0x83,0x87, + 0x87,0x83,0x87,0x83,0x83,0x87,0x8F,0x8B, + 0x9B,0x9F,0x9B,0x9F,0x9F,0x9B,0x87,0x83, + 0x83,0x87,0x83,0x87,0x87,0x83,0x8B,0x8F +}; + diff --git a/AppleWin/source/Z80VICE/daa.h b/AppleWin/source/Z80VICE/daa.h new file mode 100644 index 00000000..ede77b9f --- /dev/null +++ b/AppleWin/source/Z80VICE/daa.h @@ -0,0 +1,36 @@ +/* + * daa.h + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _DAA_H +#define _DAA_H + +#include "..\CommonVICE\types.h" // [AppleWin-TC] + +extern const BYTE daa_reg_a[]; +extern const BYTE daa_reg_f[]; + +#endif + diff --git a/AppleWin/source/Z80VICE/z80.cpp b/AppleWin/source/Z80VICE/z80.cpp new file mode 100644 index 00000000..f3463d99 --- /dev/null +++ b/AppleWin/source/Z80VICE/z80.cpp @@ -0,0 +1,6418 @@ +/* + * z80.c + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#include "..\stdafx.h" +#undef IN // Defined in windef.h +#undef OUT // Defined in windef.h + +//#include "vice.h" // [AppleWin-TC] + +#include + +#include "..\CommonVICE\6510core.h" // [AppleWin-TC] +#include "..\CommonVICE\alarm.h" +#include "daa.h" +//#include "debug.h" // [AppleWin-TC] +#include "..\CommonVICE\interrupt.h" +//#include "log.h" // [AppleWin-TC] +//#include "maincpu.h" // [AppleWin-TC] +//#include "monitor.h" // [AppleWin-TC] +#include "..\CommonVICE\types.h" +#include "z80.h" +#include "z80mem.h" +#include "z80regs.h" + + +/*#define DEBUG_Z80*/ + +static CLOCK maincpu_clk = 0; // [AppleWin-TC] + +static BYTE reg_a = 0; +static BYTE reg_b = 0; +static BYTE reg_c = 0; +static BYTE reg_d = 0; +static BYTE reg_e = 0; +static BYTE reg_f = 0; +static BYTE reg_h = 0; +static BYTE reg_l = 0; +static BYTE reg_ixh = 0; +static BYTE reg_ixl = 0; +static BYTE reg_iyh = 0; +static BYTE reg_iyl = 0; +static WORD reg_sp = 0; +static DWORD z80_reg_pc = 0; +static BYTE reg_i = 0; +static BYTE reg_r = 0; + +static BYTE iff1 = 0; +static BYTE iff2 = 0; +static BYTE im_mode = 0; + +static BYTE reg_a2 = 0; +static BYTE reg_b2 = 0; +static BYTE reg_c2 = 0; +static BYTE reg_d2 = 0; +static BYTE reg_e2 = 0; +static BYTE reg_f2 = 0; +static BYTE reg_h2 = 0; +static BYTE reg_l2 = 0; + +static int dma_request = 0; + +static BYTE *z80_bank_base; +static int z80_bank_limit; + + +void z80_trigger_dma(void) +{ + dma_request = 1; +} + +void z80_reset(void) +{ + z80_reg_pc = 0; + z80_regs.reg_pc = 0; + iff1 = 0; + iff2 = 0; + im_mode = 0; +} + +/*inline*/ static BYTE *z80mem_read_base(int addr) // [AppleWin-TC] +{ + BYTE *p = _z80mem_read_base_tab_ptr[addr >> 8]; + + if (p == 0) + return p; + + return p - (addr & 0xff00); +} + +/*inline*/ static int z80mem_read_limit(int addr) // [AppleWin-TC] +{ + return z80mem_read_limit_tab_ptr[addr >> 8]; +} + +#define JUMP(addr) \ + do { \ + z80_reg_pc = (addr); \ + z80_bank_base = z80mem_read_base(z80_reg_pc); \ + z80_bank_limit = z80mem_read_limit(z80_reg_pc); \ + z80_old_reg_pc = z80_reg_pc; \ + } while (0) + + +#define LOAD(addr) \ + (*_z80mem_read_tab_ptr[(addr) >> 8])((WORD)(addr)) + +#define STORE(addr, value) \ + (*_z80mem_write_tab_ptr[(addr) >> 8])((WORD)(addr), (BYTE)(value)) + +#define IN(addr) \ + (io_read_tab[(addr) >> 8])((WORD)(addr)) + +#define OUT(addr, value) \ + (io_write_tab[(addr) >> 8])((WORD)(addr), (BYTE)(value)) + +#define opcode_t DWORD +#define FETCH_OPCODE(o) ((o) = (LOAD(z80_reg_pc) \ + | (LOAD(z80_reg_pc + 1) << 8) \ + | (LOAD(z80_reg_pc + 2) << 16) \ + | (LOAD(z80_reg_pc + 3) << 24))) + +#define p0 (opcode & 0xff) +#define p1 ((opcode >> 8) & 0xff) +#define p2 ((opcode >> 16) & 0xff) +#define p3 (opcode >> 24) + +#define p12 ((opcode >> 8) & 0xffff) +#define p23 ((opcode >> 16) & 0xffff) + +#define CLK maincpu_clk + +#define INC_PC(value) (z80_reg_pc += (value)) + +/* ------------------------------------------------------------------------- */ + +static unsigned int z80_last_opcode_info; + +#define LAST_OPCODE_INFO z80_last_opcode_info + +#if 0 // [AppleWin-TC] +/* Remember the number of the last opcode. By default, the opcode does not + delay interrupt and does not change the I flag. */ +#define SET_LAST_OPCODE(x) \ + OPINFO_SET(LAST_OPCODE_INFO, (x), 0, 0, 0) + +/* Remember that the last opcode delayed a pending IRQ or NMI by one cycle. */ +#define OPCODE_DELAYS_INTERRUPT() \ + OPINFO_SET_DELAYS_INTERRUPT(LAST_OPCODE_INFO, 1) + +/* Remember that the last opcode changed the I flag from 0 to 1, so we have + to dispatch an IRQ even if the I flag is 0 when we check it. */ +#define OPCODE_DISABLES_IRQ() \ + OPINFO_SET_DISABLES_IRQ(LAST_OPCODE_INFO, 1) + +/* Remember that the last opcode changed the I flag from 1 to 0, so we must + not dispatch an IRQ even if the I flag is 1 when we check it. */ +#define OPCODE_ENABLES_IRQ() \ + OPINFO_SET_ENABLES_IRQ(LAST_OPCODE_INFO, 1) + +#else // [AppleWin-TC] + +#define SET_LAST_OPCODE(x) +#define OPCODE_DELAYS_INTERRUPT() +#define OPCODE_DISABLES_IRQ() +#define OPCODE_ENABLES_IRQ() +#endif + +/* ------------------------------------------------------------------------- */ + +/* Word register manipulation. */ + +#define BC_WORD() ((reg_b << 8) | reg_c) +#define DE_WORD() ((reg_d << 8) | reg_e) +#define HL_WORD() ((reg_h << 8) | reg_l) +#define IX_WORD() ((reg_ixh << 8) | reg_ixl) +#define IY_WORD() ((reg_iyh << 8) | reg_iyl) + +#define IX_WORD_OFF(offset) (IX_WORD() + (signed char)(offset)) +#define IY_WORD_OFF(offset) (IY_WORD() + (signed char)(offset)) + +#define DEC_BC_WORD() \ + do { \ + if (!reg_c) \ + reg_b--; \ + reg_c--; \ + } while (0) + +#define DEC_DE_WORD() \ + do { \ + if (!reg_e) \ + reg_d--; \ + reg_e--; \ + } while (0) + +#define DEC_HL_WORD() \ + do { \ + if (!reg_l) \ + reg_h--; \ + reg_l--; \ + } while (0) + +#define DEC_IX_WORD() \ + do { \ + if (!reg_ixl) \ + reg_ixh--; \ + reg_ixl--; \ + } while (0) + +#define DEC_IY_WORD() \ + do { \ + if (!reg_iyl) \ + reg_iyh--; \ + reg_iyl--; \ + } while (0) + +#define INC_BC_WORD() \ + do { \ + reg_c++; \ + if (!reg_c) \ + reg_b++; \ + } while (0) + +#define INC_DE_WORD() \ + do { \ + reg_e++; \ + if (!reg_e) \ + reg_d++; \ + } while (0) + +#define INC_HL_WORD() \ + do { \ + reg_l++; \ + if (!reg_l) \ + reg_h++; \ + } while (0) + +#define INC_IX_WORD() \ + do { \ + reg_ixl++; \ + if (!reg_ixl) \ + reg_ixh++; \ + } while (0) + +#define INC_IY_WORD() \ + do { \ + reg_iyl++; \ + if (!reg_iyl) \ + reg_iyh++; \ + } while (0) + +/* ------------------------------------------------------------------------- */ + +/* Flags. */ + +#define C_FLAG 0x01 +#define N_FLAG 0x02 +#define P_FLAG 0x04 +#define U3_FLAG 0x08 +#define H_FLAG 0x10 +#define U5_FLAG 0x20 +#define Z_FLAG 0x40 +#define S_FLAG 0x80 + +#define LOCAL_SET_CARRY(val) \ + do { \ + if (val) \ + reg_f |= C_FLAG; \ + else \ + reg_f &= ~C_FLAG; \ + } while (0) + +#define LOCAL_SET_NADDSUB(val) \ + do { \ + if (val) \ + reg_f |= N_FLAG; \ + else \ + reg_f &= ~N_FLAG; \ + } while (0) + +#define LOCAL_SET_PARITY(val) \ + do { \ + if (val) \ + reg_f |= P_FLAG; \ + else \ + reg_f &= ~P_FLAG; \ + } while (0) + +#define LOCAL_SET_HALFCARRY(val) \ + do { \ + if (val) \ + reg_f |= H_FLAG; \ + else \ + reg_f &= ~H_FLAG; \ + } while (0) + +#define LOCAL_SET_ZERO(val) \ + do { \ + if (val) \ + reg_f |= Z_FLAG; \ + else \ + reg_f &= ~Z_FLAG; \ + } while (0) + +#define LOCAL_SET_SIGN(val) \ + do { \ + if (val) \ + reg_f |= S_FLAG; \ + else \ + reg_f &= ~S_FLAG; \ + } while (0) + +#define LOCAL_CARRY() (reg_f & C_FLAG) +#define LOCAL_NADDSUB() (reg_f & N_FLAG) +#define LOCAL_PARITY() (reg_f & P_FLAG) +#define LOCAL_HALFCARRY() (reg_f & H_FLAG) +#define LOCAL_ZERO() (reg_f & Z_FLAG) +#define LOCAL_SIGN() (reg_f & S_FLAG) + +static const BYTE SZP[256] = { + P_FLAG|Z_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + P_FLAG, 0, 0, P_FLAG, + P_FLAG, 0, 0, P_FLAG, + 0, P_FLAG, P_FLAG, 0, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG, S_FLAG|P_FLAG, S_FLAG|P_FLAG, S_FLAG, + S_FLAG|P_FLAG, S_FLAG, S_FLAG, S_FLAG|P_FLAG }; + +/* ------------------------------------------------------------------------- */ + +z80_regs_t z80_regs; + +static void import_registers(void) +{ + reg_a = z80_regs.reg_af >> 8; + reg_f = z80_regs.reg_af & 0xff; + reg_b = z80_regs.reg_bc >> 8; + reg_c = z80_regs.reg_bc & 0xff; + reg_d = z80_regs.reg_de >> 8; + reg_e = z80_regs.reg_de & 0xff; + reg_h = z80_regs.reg_hl >> 8; + reg_l = z80_regs.reg_hl & 0xff; + reg_ixh = z80_regs.reg_ix >> 8; + reg_ixl = z80_regs.reg_ix & 0xff; + reg_iyh = z80_regs.reg_iy >> 8; + reg_iyl = z80_regs.reg_iy & 0xff; + reg_sp = z80_regs.reg_sp; + z80_reg_pc = (DWORD)z80_regs.reg_pc; + reg_i = z80_regs.reg_i; + reg_r = z80_regs.reg_r; + reg_a2 = z80_regs.reg_af2 >> 8; + reg_f2 = z80_regs.reg_af2 & 0xff; + reg_b2 = z80_regs.reg_bc2 >> 8; + reg_c2 = z80_regs.reg_bc2 & 0xff; + reg_d2 = z80_regs.reg_de2 >> 8; + reg_e2 = z80_regs.reg_de2 & 0xff; + reg_h2 = z80_regs.reg_hl2 >> 8; + reg_l2 = z80_regs.reg_hl2 & 0xff; +} + +static void export_registers(void) +{ + z80_regs.reg_af = (reg_a << 8) | reg_f; + z80_regs.reg_bc = (reg_b << 8) | reg_c; + z80_regs.reg_de = (reg_d << 8) | reg_e; + z80_regs.reg_hl = (reg_h << 8) | reg_l; + z80_regs.reg_ix = (reg_ixh << 8) | reg_ixl; + z80_regs.reg_iy = (reg_iyh << 8) | reg_iyl; + z80_regs.reg_sp = reg_sp; + z80_regs.reg_pc = (WORD)z80_reg_pc; + z80_regs.reg_i = reg_i; + z80_regs.reg_r = reg_r; + z80_regs.reg_af2 = (reg_a2 << 8) | reg_f2; + z80_regs.reg_bc2 = (reg_b2 << 8) | reg_c2; + z80_regs.reg_de2 = (reg_d2 << 8) | reg_e2; + z80_regs.reg_hl2 = (reg_h2 << 8) | reg_l2; +} + +/* ------------------------------------------------------------------------- */ + +/* Interrupt handling. */ + +#define DO_INTERRUPT(int_kind) \ + do { \ + BYTE ik = (int_kind); \ + \ + if (ik & (IK_IRQ | IK_NMI)) { \ + if ((ik & IK_NMI) && 0) { \ + } else if ((ik & IK_IRQ) && iff1 \ + && !OPINFO_DISABLES_IRQ(LAST_OPCODE_INFO)) { \ + WORD jumpdst; \ + /*TRACE_IRQ();*/ \ + if (monitor_mask[e_comp_space] & (MI_STEP)) { \ + monitor_check_icount_interrupt(); \ + } \ + CLK += 4; \ + --reg_sp; \ + STORE((reg_sp), ((BYTE)(z80_reg_pc >> 8))); \ + CLK += 4; \ + --reg_sp; \ + STORE((reg_sp), ((BYTE)(z80_reg_pc & 0xff))); \ + iff1 = 0; \ + iff2 = 0; \ + if (im_mode == 1) { \ + jumpdst = 0x38; \ + CLK += 4; \ + JUMP(jumpdst); \ + CLK += 3; \ + } else { \ + jumpdst = (LOAD(reg_i << 8) << 8); \ + CLK += 4; \ + jumpdst |= (LOAD((reg_i << 8) + 1)); \ + JUMP(jumpdst); \ + CLK += 3; \ + } \ + } \ + } \ + if (ik & (IK_TRAP | IK_RESET)) { \ + if (ik & IK_TRAP) { \ + export_registers(); \ + interrupt_do_trap(cpu_int_status, (WORD)z80_reg_pc); \ + import_registers(); \ + if (cpu_int_status->global_pending_int & IK_RESET) \ + ik |= IK_RESET; \ + } \ + if (ik & IK_RESET) { \ + interrupt_ack_reset(cpu_int_status); \ + maincpu_reset(); \ + } \ + } \ + if (ik & (IK_MONITOR)) { \ + caller_space = e_comp_space; \ + if (monitor_force_import(e_comp_space)) \ + import_registers(); \ + if (monitor_mask[e_comp_space]) \ + export_registers(); \ + if (monitor_mask[e_comp_space] & (MI_BREAK)) { \ + if (monitor_check_breakpoints(e_comp_space, \ + (WORD)z80_reg_pc)) { \ + monitor_startup(); \ + } \ + } \ + if (monitor_mask[e_comp_space] & (MI_STEP)) { \ + monitor_check_icount((WORD)z80_reg_pc); \ + } \ + if (monitor_mask[e_comp_space] & (MI_WATCH)) { \ + monitor_check_watchpoints((WORD)z80_reg_pc); \ + } \ + } \ + } while (0) + +/* ------------------------------------------------------------------------- */ + +/* Opcodes. */ + +#define ADC(loadval, clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp, carry, value; \ + \ + CLK += clk_inc1; \ + value = (BYTE)(loadval); \ + carry = LOCAL_CARRY(); \ + tmp = reg_a + value + carry; \ + reg_f = SZP[tmp]; \ + LOCAL_SET_CARRY((WORD)((WORD)reg_a + (WORD)value \ + + (WORD)(carry)) & 0x100); \ + LOCAL_SET_HALFCARRY((reg_a ^ value ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY((~(reg_a ^ value)) & (reg_a ^ tmp) & 0x80); \ + reg_a = tmp; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define ADCHLREG(reg_valh, reg_vall) \ + do { \ + DWORD tmp, carry; \ + \ + carry = LOCAL_CARRY(); \ + tmp = (DWORD)((reg_h << 8) + reg_l) \ + + (DWORD)((reg_valh << 8) + reg_vall) + carry; \ + LOCAL_SET_ZERO(!(tmp & 0xffff)); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_SIGN(tmp & 0x8000); \ + LOCAL_SET_CARRY(tmp & 0x10000); \ + LOCAL_SET_HALFCARRY(((tmp >> 8) ^ reg_valh ^ reg_h) & H_FLAG); \ + LOCAL_SET_PARITY((~(reg_h ^ reg_valh)) & \ + (reg_valh ^ (tmp >> 8)) & 0x80); \ + reg_h = (BYTE)(tmp >> 8); \ + reg_l = (BYTE)(tmp & 0xff); \ + CLK += 15; \ + INC_PC(2); \ + } while (0) + +#define ADCHLSP() \ + do { \ + DWORD tmp, carry; \ + \ + carry = LOCAL_CARRY(); \ + tmp = (DWORD)((reg_h << 8) + reg_l) + (DWORD)(reg_sp) + carry; \ + LOCAL_SET_ZERO(!(tmp & 0xffff)); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_SIGN(tmp & 0x8000); \ + LOCAL_SET_CARRY(tmp & 0x10000); \ + LOCAL_SET_HALFCARRY(((tmp >> 8) ^ (reg_sp >> 8) ^ reg_h) & H_FLAG); \ + LOCAL_SET_PARITY((~(reg_h ^ (reg_sp >> 8))) & \ + ((reg_sp >> 8) ^ (tmp >> 8)) & 0x80); \ + reg_h = (BYTE)(tmp >> 8); \ + reg_l = (BYTE)(tmp & 0xff); \ + CLK += 15; \ + INC_PC(2); \ + } while (0) + +#define ADD(loadval, clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp, value; \ + \ + CLK += clk_inc1; \ + value = (BYTE)(loadval); \ + tmp = reg_a + value; \ + reg_f = SZP[tmp]; \ + LOCAL_SET_CARRY((WORD)((WORD)reg_a + (WORD)value) & 0x100); \ + LOCAL_SET_HALFCARRY((reg_a ^ value ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY((~(reg_a ^ value)) & (reg_a ^ tmp) & 0x80); \ + reg_a = tmp; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define ADDXXREG(reg_dsth, reg_dstl, reg_valh, reg_vall, clk_inc, pc_inc) \ + do { \ + DWORD tmp; \ + \ + tmp = (DWORD)((reg_dsth << 8) + reg_dstl) \ + + (DWORD)((reg_valh << 8) + reg_vall); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_CARRY(tmp & 0x10000); \ + LOCAL_SET_HALFCARRY(((tmp >> 8) ^ reg_valh ^ reg_dsth) & H_FLAG); \ + reg_dsth = (BYTE)(tmp >> 8); \ + reg_dstl = (BYTE)(tmp & 0xff); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define ADDXXSP(reg_dsth, reg_dstl, clk_inc, pc_inc) \ + do { \ + DWORD tmp; \ + \ + tmp = (DWORD)((reg_dsth << 8) + reg_dstl) + (DWORD)(reg_sp); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_CARRY(tmp & 0x10000); \ + LOCAL_SET_HALFCARRY(((tmp >> 8) ^ (reg_sp >> 8) ^ reg_dsth) & H_FLAG); \ + reg_dsth = (BYTE)(tmp >> 8); \ + reg_dstl = (BYTE)(tmp & 0xff); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define AND(value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_a &= (value); \ + reg_f = SZP[reg_a]; \ + LOCAL_SET_HALFCARRY(1); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define BIT(reg_val, value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_HALFCARRY(1); \ + LOCAL_SET_ZERO(!((reg_val) & (1 << value))); \ + /***LOCAL_SET_PARITY(LOCAL_ZERO());***/ \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define BRANCH(cond, value, pc_inc) \ + do { \ + if (cond) { \ + unsigned int dest_addr; \ + \ + dest_addr = z80_reg_pc + pc_inc + (signed char)(value); \ + z80_reg_pc = dest_addr & 0xffff; \ + CLK += 7; \ + } else { \ + CLK += 7; \ + INC_PC(pc_inc); \ + } \ + } while (0) + +#define CALL(reg_val, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + INC_PC(pc_inc); \ + CLK += clk_inc1; \ + --reg_sp; \ + STORE((reg_sp), ((BYTE)(z80_reg_pc >> 8))); \ + CLK += clk_inc2; \ + --reg_sp; \ + STORE((reg_sp), ((BYTE)(z80_reg_pc & 0xff))); \ + JUMP(reg_val); \ + CLK += clk_inc3; \ + } while (0) + +#define CALL_COND(reg_value, cond, clk_inc1, clk_inc2, clk_inc3, \ + clk_inc4, pc_inc) \ + do { \ + if (cond) { \ + CALL(reg_value, clk_inc1, clk_inc2, clk_inc3, pc_inc); \ + } else { \ + CLK += clk_inc4; \ + INC_PC(3); \ + } \ + } while (0) + +#define CCF(clk_inc, pc_inc) \ + do { \ + LOCAL_SET_HALFCARRY((LOCAL_CARRY())); \ + LOCAL_SET_CARRY(!(LOCAL_CARRY())); \ + LOCAL_SET_NADDSUB(0); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define CP(loadval, clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp, value; \ + \ + CLK += clk_inc1; \ + value = (BYTE)(loadval); \ + tmp = reg_a - value; \ + reg_f = N_FLAG | SZP[tmp]; \ + LOCAL_SET_CARRY(value > reg_a); \ + LOCAL_SET_HALFCARRY((reg_a ^ value ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY((reg_a ^ value) & (reg_a ^ tmp) & 0x80); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define CPDI(HL_FUNC) \ + do { \ + BYTE val, tmp; \ + \ + CLK += 4; \ + val = LOAD(HL_WORD()); \ + tmp = reg_a - val; \ + HL_FUNC; \ + DEC_BC_WORD(); \ + reg_f = N_FLAG | SZP[tmp] | LOCAL_CARRY(); \ + /***LOCAL_SET_CARRY(val > reg_a);***/ \ + LOCAL_SET_HALFCARRY((reg_a ^ val ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY(reg_b | reg_c); \ + CLK += 1; \ + INC_PC(2); \ + } while (0) + +#define CPDIR(HL_FUNC) \ + do { \ + BYTE val, tmp; \ + \ + CLK += 4; \ + val = LOAD(HL_WORD()); \ + tmp = reg_a - val; \ + HL_FUNC; \ + DEC_BC_WORD(); \ + CLK += 17; \ + if (!(BC_WORD() && tmp)) { \ + reg_f = N_FLAG | SZP[tmp] | LOCAL_CARRY(); \ + /***LOCAL_SET_CARRY(val > reg_a);***/ \ + LOCAL_SET_HALFCARRY((reg_a ^ val ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY(reg_b | reg_c); \ + CLK += 5; \ + INC_PC(2); \ + } \ + } while (0) + +#define CPL(clk_inc, pc_inc) \ + do { \ + reg_a ^= 0xff; \ + LOCAL_SET_NADDSUB(1); \ + LOCAL_SET_HALFCARRY(1); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define DAA(clk_inc, pc_inc) \ + do { \ + WORD tmp; \ + \ + tmp = reg_a | (LOCAL_CARRY() ? 0x100 : 0) \ + | (LOCAL_HALFCARRY() ? 0x200 : 0) \ + | (LOCAL_NADDSUB() ? 0x400 : 0); \ + reg_a = daa_reg_a[tmp]; \ + reg_f = daa_reg_f[tmp]; \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define DECXXIND(reg_val, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((reg_val)); \ + tmp--; \ + CLK += clk_inc2; \ + STORE((reg_val), tmp); \ + reg_f = N_FLAG | SZP[tmp] | LOCAL_CARRY(); \ + LOCAL_SET_PARITY((tmp == 0x7f)); \ + LOCAL_SET_HALFCARRY(((tmp & 0x0f) == 0x0f)); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define DECINC(FUNC, clk_inc, pc_inc) \ + do { \ + CLK += clk_inc; \ + FUNC; \ + INC_PC(pc_inc); \ + } while (0) + +#define DECREG(reg_val, clk_inc, pc_inc) \ + do { \ + reg_val--; \ + reg_f = N_FLAG | SZP[reg_val] | LOCAL_CARRY(); \ + LOCAL_SET_PARITY((reg_val == 0x7f)); \ + LOCAL_SET_HALFCARRY(((reg_val & 0x0f) == 0x0f)); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define DJNZ(value, pc_inc) \ + do { \ + reg_b--; \ + /***LOCAL_SET_NADDSUB(1);***/ \ + BRANCH(reg_b, value, pc_inc); \ + } while (0) + +#define DI(clk_inc, pc_inc) \ + do { \ + iff1 = 0; \ + iff2 = 0; \ + OPCODE_DISABLES_IRQ(); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define EI(clk_inc, pc_inc) \ + do { \ + iff1 = 1; \ + iff2 = 1; \ + OPCODE_DISABLES_IRQ(); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define EXAFAF(clk_inc, pc_inc) \ + do { \ + BYTE tmpl, tmph; \ + \ + tmph = reg_a; \ + tmpl = reg_f; \ + reg_a = reg_a2; \ + reg_f = reg_f2; \ + reg_a2 = tmph; \ + reg_f2 = tmpl; \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define EXX(clk_inc, pc_inc) \ + do { \ + BYTE tmpl, tmph; \ + \ + tmph = reg_b; \ + tmpl = reg_c; \ + reg_b = reg_b2; \ + reg_c = reg_c2; \ + reg_b2 = tmph; \ + reg_c2 = tmpl; \ + tmph = reg_d; \ + tmpl = reg_e; \ + reg_d = reg_d2; \ + reg_e = reg_e2; \ + reg_d2 = tmph; \ + reg_e2 = tmpl; \ + tmph = reg_h; \ + tmpl = reg_l; \ + reg_h = reg_h2; \ + reg_l = reg_l2; \ + reg_h2 = tmph; \ + reg_l2 = tmpl; \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define EXDEHL(clk_inc, pc_inc) \ + do { \ + BYTE tmpl, tmph; \ + \ + tmph = reg_d; \ + tmpl = reg_e; \ + reg_d = reg_h; \ + reg_e = reg_l; \ + reg_h = tmph; \ + reg_l = tmpl; \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define EXXXSP(reg_valh, reg_vall, clk_inc1, clk_inc2, clk_inc3, \ + clk_inc4, clk_inc5, pc_inc) \ + do { \ + BYTE tmpl, tmph; \ + \ + tmph = reg_valh; \ + tmpl = reg_vall; \ + CLK += clk_inc1; \ + reg_valh = LOAD(reg_sp + 1); \ + CLK += clk_inc2; \ + reg_vall = LOAD(reg_sp); \ + CLK += clk_inc3; \ + STORE((reg_sp + 1), tmph); \ + CLK += clk_inc4; \ + STORE(reg_sp, tmpl); \ + CLK += clk_inc5; \ + INC_PC(pc_inc); \ + } while (0) + +/* FIXME: Continue if INT occurs. */ +#define HALT() \ + do { \ + CLK += 4; \ + } while (0) + +#define IM(value) \ + do { \ + im_mode = value; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define INA(value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + /***reg_a = IN(value);***/ \ + reg_a = IN((reg_a << 8) | value); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define INBC(reg_val, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_val = IN(BC_WORD()); \ + reg_f = SZP[reg_val & 0xff] | LOCAL_CARRY(); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define INBC0(clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp; \ + CLK += clk_inc1; \ + tmp = IN(BC_WORD()); \ + reg_f = SZP[tmp] | LOCAL_CARRY(); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define INCXXIND(reg_val, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((reg_val)); \ + tmp++; \ + CLK += clk_inc2; \ + STORE((reg_val), tmp); \ + reg_f = SZP[tmp] | LOCAL_CARRY(); \ + LOCAL_SET_PARITY((tmp == 0x80)); \ + LOCAL_SET_HALFCARRY(!(tmp & 0x0f)); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define INCREG(reg_val, clk_inc, pc_inc) \ + do { \ + reg_val++; \ + reg_f = SZP[reg_val] | LOCAL_CARRY(); \ + LOCAL_SET_PARITY((reg_val == 0x80)); \ + LOCAL_SET_HALFCARRY(!(reg_val & 0x0f)); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define INDI(HL_FUNC) \ + do { \ + BYTE tmp; \ + \ + CLK += 4; \ + tmp = IN(BC_WORD()); \ + CLK += 4; \ + STORE(HL_WORD(), tmp); \ + HL_FUNC; \ + reg_b--; \ + reg_f = N_FLAG; \ + LOCAL_SET_ZERO(!reg_b); \ + CLK += 4; \ + INC_PC(2); \ + } while (0) + +#define INDIR(HL_FUNC) \ + do { \ + BYTE tmp; \ + \ + CLK += 4; \ + tmp = IN(BC_WORD()); \ + CLK += 4; \ + STORE(HL_WORD(), tmp); \ + HL_FUNC; \ + reg_b--; \ + if (!reg_b) { \ + CLK += 4; \ + reg_f = N_FLAG | Z_FLAG; \ + INC_PC(2); \ + } else { \ + reg_f = N_FLAG; \ + } \ + CLK += 4; \ + } while (0) + +#define JMP(addr, clk_inc) \ + do { \ + CLK += clk_inc; \ + JUMP(addr); \ + } while (0) + +#define JMP_COND(addr, cond, clk_inc1, clk_inc2) \ + do { \ + if (cond) { \ + JMP(addr, clk_inc1); \ + } else { \ + CLK += clk_inc2; \ + INC_PC(3); \ + } \ + } while (0) + +#define LDAIR(reg_val) \ + do { \ + CLK += 6; \ + reg_a = reg_val; \ + reg_f = SZP[reg_a] | LOCAL_CARRY(); \ + LOCAL_SET_PARITY(iff2); \ + CLK += 3; \ + INC_PC(2); \ + } while (0) + +#define LDDI(DE_FUNC, HL_FUNC) \ + do { \ + BYTE tmp; \ + \ + CLK += 4; \ + tmp = LOAD(HL_WORD()); \ + CLK += 4; \ + STORE(DE_WORD(), tmp); \ + DEC_BC_WORD(); \ + DE_FUNC; \ + HL_FUNC; \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_PARITY(reg_b | reg_c); \ + LOCAL_SET_HALFCARRY(0); \ + CLK += 12; \ + INC_PC(2); \ + } while (0) + +#define LDDIR(DE_FUNC, HL_FUNC) \ + do { \ + BYTE tmp; \ + \ + CLK += 4; \ + tmp = LOAD(HL_WORD()); \ + CLK += 4; \ + STORE(DE_WORD(), tmp); \ + DEC_BC_WORD(); \ + DE_FUNC; \ + HL_FUNC; \ + CLK += 13; \ + if (!(BC_WORD())) { \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_PARITY(0); \ + LOCAL_SET_HALFCARRY(0); \ + CLK += 5; \ + INC_PC(2); \ + } \ + } while (0) + +#define LDIND(val, reg_valh, reg_vall, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_vall = LOAD((val)); \ + CLK += clk_inc2; \ + reg_valh = LOAD((val) + 1); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define LDSP(value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_sp = (WORD)(value); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define LDSPIND(value, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_sp = LOAD(value); \ + CLK += clk_inc2; \ + reg_sp |= LOAD(value + 1) << 8; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define LDREG(reg_dest, value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = (BYTE)(value); \ + reg_dest = tmp; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define LDW(value, reg_valh, reg_vall, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_vall = (BYTE)((value) & 0xff); \ + reg_valh = (BYTE)((value) >> 8); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define NEG() \ + do { \ + BYTE tmp; \ + \ + tmp = 0 - reg_a; \ + reg_f = N_FLAG | SZP[tmp]; \ + LOCAL_SET_HALFCARRY((reg_a ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY(reg_a & tmp & 0x80); \ + LOCAL_SET_CARRY(reg_a > 0); \ + reg_a = tmp; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define NOP(clk_inc, pc_inc) \ + do { \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define OR(reg_val, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_a |= reg_val; \ + reg_f = SZP[reg_a]; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define OUTA(value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + /***OUT(value, reg_a);***/ \ + OUT((reg_a << 8) | value, reg_a); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define OUTBC(value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + OUT(BC_WORD(), value); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define OUTDI(HL_FUNC) \ + do { \ + BYTE tmp; \ + \ + CLK += 4; \ + tmp = LOAD(HL_WORD()); \ + CLK += 4; \ + OUT(BC_WORD(), tmp); \ + HL_FUNC; \ + reg_b--; \ + reg_f = N_FLAG; \ + LOCAL_SET_ZERO(!reg_b); \ + CLK += 4; \ + INC_PC(2); \ + } while (0) + +#define OTDIR(HL_FUNC) \ + do { \ + BYTE tmp; \ + \ + CLK += 4; \ + tmp = LOAD(HL_WORD()); \ + CLK += 4; \ + OUT(BC_WORD(), tmp); \ + HL_FUNC; \ + reg_b--; \ + if (!reg_b) { \ + CLK += 4; \ + reg_f = N_FLAG | Z_FLAG; \ + INC_PC(2); \ + } else { \ + reg_f = N_FLAG; \ + } \ + CLK += 4; \ + } while (0) + +#define POP(reg_valh, reg_vall, pc_inc) \ + do { \ + CLK += 4; \ + reg_vall = LOAD(reg_sp); \ + ++reg_sp; \ + CLK += 4; \ + reg_valh = LOAD(reg_sp); \ + ++reg_sp; \ + CLK += 2; \ + INC_PC(pc_inc); \ + } while (0) + +#define PUSH(reg_valh, reg_vall, pc_inc) \ + do { \ + CLK += 4; \ + --reg_sp; \ + STORE((reg_sp), (reg_valh)); \ + CLK += 4; \ + --reg_sp; \ + STORE((reg_sp), (reg_vall)); \ + CLK += 3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RES(reg_val, value) \ + do { \ + reg_val &= (~(1 << value)); \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define RESXX(value, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + tmp &= (~(1 << value)); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RESXXREG(value, reg_val, addr, clk_inc1, clk_inc2, \ + clk_inc3, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + tmp &= (~(1 << value)); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RET(clk_inc1, clk_inc2, clk_inc3) \ + do { \ + WORD tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD(reg_sp); \ + CLK += clk_inc2; \ + tmp |= LOAD((reg_sp + 1)) << 8; \ + reg_sp += 2; \ + JUMP(tmp); \ + CLK += clk_inc3; \ + } while (0) + +#define RET_COND(cond, clk_inc1, clk_inc2, clk_inc3, clk_inc4, pc_inc) \ + do { \ + if (cond) { \ + RET(clk_inc1, clk_inc2, clk_inc3); \ + } else { \ + CLK += clk_inc4; \ + INC_PC(pc_inc); \ + } \ + } while (0) + +#define RETNI() \ + do { \ + WORD tmp; \ + \ + CLK += 4; \ + tmp = LOAD(reg_sp); \ + CLK += 4; \ + tmp |= LOAD((reg_sp + 1)) << 8; \ + reg_sp += 2; \ + iff1 = iff2; \ + JUMP(tmp); \ + CLK += 2; \ + } while (0) + +#define RL(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = (reg_val & 0x80) ? C_FLAG : 0; \ + reg_val = (reg_val << 1) | LOCAL_CARRY(); \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define RLA(clk_inc, pc_inc) \ + do { \ + BYTE rot; \ + \ + rot = (reg_a & 0x80) ? C_FLAG : 0; \ + reg_a = (reg_a << 1) | LOCAL_CARRY(); \ + LOCAL_SET_CARRY(rot); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_HALFCARRY(0); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define RLC(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = (reg_val & 0x80) ? C_FLAG : 0; \ + reg_val = (reg_val << 1) | rot; \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define RLCA(clk_inc, pc_inc) \ + do { \ + BYTE rot; \ + \ + rot = (reg_a & 0x80) ? C_FLAG : 0; \ + reg_a = (reg_a << 1) | rot; \ + LOCAL_SET_CARRY(rot); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_HALFCARRY(0); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define RLCXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp = (tmp << 1) | rot; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RLCXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp = (tmp << 1) | rot; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RLD() \ + do { \ + BYTE tmp; \ + \ + tmp = LOAD(HL_WORD()); \ + CLK += 8; \ + STORE(HL_WORD(), (tmp << 4) | (reg_a & 0x0f)); \ + reg_a = (tmp >> 4) | (reg_a & 0xf0); \ + reg_f = SZP[reg_a] | LOCAL_CARRY(); \ + CLK += 10; \ + INC_PC(2); \ + } while (0) + +#define RLXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp = (tmp << 1) | LOCAL_CARRY(); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RLXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp = (tmp << 1) | LOCAL_CARRY(); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RR(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = reg_val & C_FLAG; \ + reg_val = (reg_val >> 1) | (LOCAL_CARRY() ? 0x80 : 0); \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define RRA(clk_inc, pc_inc) \ + do { \ + BYTE rot; \ + \ + rot = reg_a & C_FLAG; \ + reg_a = (reg_a >> 1) | (LOCAL_CARRY() ? 0x80 : 0); \ + LOCAL_SET_CARRY(rot); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_HALFCARRY(0); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define RRC(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = reg_val & C_FLAG; \ + reg_val = (reg_val >> 1) | ((rot) ? 0x80 : 0); \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define RRCA(clk_inc, pc_inc) \ + do { \ + BYTE rot; \ + \ + rot = reg_a & C_FLAG; \ + reg_a = (reg_a >> 1) | ((rot) ? 0x80 : 0); \ + LOCAL_SET_CARRY(rot); \ + LOCAL_SET_NADDSUB(0); \ + LOCAL_SET_HALFCARRY(0); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define RRCXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp = (tmp >> 1) | ((rot) ? 0x80 : 0); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RRCXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp = (tmp >> 1) | ((rot) ? 0x80 : 0); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RRD() \ + do { \ + BYTE tmp; \ + \ + tmp = LOAD(HL_WORD()); \ + CLK += 8; \ + STORE(HL_WORD(), (tmp >> 4) | (reg_a << 4)); \ + reg_a = (tmp & 0x0f) | (reg_a & 0xf0); \ + reg_f = SZP[reg_a] | LOCAL_CARRY(); \ + CLK += 10; \ + INC_PC(2); \ + } while (0) + +#define RRXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp = (tmp >> 1) | (LOCAL_CARRY() ? 0x80 : 0); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define RRXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp = (tmp >> 1) | (LOCAL_CARRY() ? 0x80 : 0); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SBCHLREG(reg_valh, reg_vall) \ + do { \ + DWORD tmp; \ + BYTE carry; \ + \ + carry = LOCAL_CARRY(); \ + tmp = (DWORD)(HL_WORD()) - (DWORD)((reg_valh << 8) + reg_vall) \ + - (DWORD)(carry); \ + reg_f = N_FLAG; \ + LOCAL_SET_CARRY(tmp & 0x10000); \ + LOCAL_SET_HALFCARRY((reg_h ^ reg_valh ^ (tmp >> 8)) & H_FLAG); \ + LOCAL_SET_PARITY(((reg_h ^ (tmp >> 8)) & (reg_h ^ reg_valh)) & 0x80); \ + LOCAL_SET_ZERO(!(tmp & 0xffff)); \ + LOCAL_SET_SIGN(tmp & 0x8000); \ + reg_h = (BYTE)(tmp >> 8); \ + reg_l = (BYTE)(tmp & 0xff); \ + CLK += 15; \ + INC_PC(2); \ + } while (0) + +#define SBCHLSP() \ + do { \ + DWORD tmp; \ + BYTE carry; \ + \ + carry = LOCAL_CARRY(); \ + tmp = (DWORD)(HL_WORD()) - (DWORD)reg_sp - (DWORD)(carry); \ + reg_f = N_FLAG; \ + LOCAL_SET_CARRY(tmp & 0x10000); \ + LOCAL_SET_HALFCARRY((reg_h ^ (reg_sp >> 8) ^ (tmp >> 8)) & H_FLAG); \ + LOCAL_SET_PARITY(((reg_h ^ (tmp >> 8)) \ + & (reg_h ^ (reg_sp >> 8))) & 0x80); \ + LOCAL_SET_ZERO(!(tmp & 0xffff)); \ + LOCAL_SET_SIGN(tmp & 0x8000); \ + reg_h = (BYTE)(tmp >> 8); \ + reg_l = (BYTE)(tmp & 0xff); \ + CLK += 15; \ + INC_PC(2); \ + } while (0) + +#define SBC(loadval, clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp, carry, value; \ + \ + CLK += clk_inc1; \ + value = (BYTE)(loadval); \ + carry = LOCAL_CARRY(); \ + tmp = reg_a - value - carry; \ + reg_f = N_FLAG | SZP[tmp]; \ + LOCAL_SET_HALFCARRY((reg_a ^ value ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY((reg_a ^ value) & (reg_a ^ tmp) & 0x80); \ + LOCAL_SET_CARRY((WORD)((WORD)value \ + + (WORD)(carry)) > reg_a); \ + reg_a = tmp; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define SCF(clk_inc, pc_inc) \ + do { \ + LOCAL_SET_CARRY(1); \ + LOCAL_SET_HALFCARRY(0); \ + LOCAL_SET_NADDSUB(0); \ + CLK += clk_inc; \ + INC_PC(pc_inc); \ + } while (0) + +#define SET(reg_val, value) \ + do { \ + reg_val |= (1 << value); \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define SETXX(value, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + tmp |= (1 << value); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SETXXREG(value, reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + tmp |= (1 << value); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SLA(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = (reg_val & 0x80) ? C_FLAG : 0; \ + reg_val <<= 1; \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define SLAXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp <<= 1; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SLAXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp <<= 1; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SLL(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = (reg_val & 0x80) ? C_FLAG : 0; \ + reg_val = (reg_val << 1) | 1; \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define SLLXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp = (tmp << 1) | 1; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SLLXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = (tmp & 0x80) ? C_FLAG : 0; \ + tmp = (tmp << 1) | 1; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SRA(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = reg_val & C_FLAG; \ + reg_val = (reg_val >> 1) | (reg_val & 0x80); \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define SRAXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp = (tmp >> 1) | (tmp & 0x80); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SRAXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp = (tmp >> 1) | (tmp & 0x80); \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SRL(reg_val) \ + do { \ + BYTE rot; \ + \ + rot = reg_val & C_FLAG; \ + reg_val >>= 1; \ + reg_f = rot | SZP[reg_val]; \ + CLK += 8; \ + INC_PC(2); \ + } while (0) + +#define SRLXX(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp >>= 1; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define SRLXXREG(reg_val, addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + BYTE rot, tmp; \ + \ + CLK += clk_inc1; \ + tmp = LOAD((addr)); \ + rot = tmp & C_FLAG; \ + tmp >>= 1; \ + CLK += clk_inc2; \ + STORE((addr), tmp); \ + reg_val = tmp; \ + reg_f = rot | SZP[tmp]; \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define STW(addr, reg_valh, reg_vall, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + CLK += clk_inc1; \ + STORE((WORD)(addr), reg_vall); \ + CLK += clk_inc2; \ + STORE((WORD)(addr + 1), reg_valh); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define STSPW(addr, clk_inc1, clk_inc2, clk_inc3, pc_inc) \ + do { \ + CLK += clk_inc1; \ + STORE((WORD)(addr), (reg_sp & 0xff)); \ + CLK += clk_inc2; \ + STORE((WORD)(addr + 1), (reg_sp >> 8)); \ + CLK += clk_inc3; \ + INC_PC(pc_inc); \ + } while (0) + +#define STREG(addr, reg_val, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + STORE(addr, reg_val); \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define SUB(loadval, clk_inc1, clk_inc2, pc_inc) \ + do { \ + BYTE tmp, value; \ + \ + CLK += clk_inc1; \ + value = (BYTE)(loadval); \ + tmp = reg_a - value; \ + reg_f = N_FLAG | SZP[tmp]; \ + LOCAL_SET_HALFCARRY((reg_a ^ value ^ tmp) & H_FLAG); \ + LOCAL_SET_PARITY((reg_a ^ value) & (reg_a ^ tmp) & 0x80); \ + LOCAL_SET_CARRY(value > reg_a); \ + reg_a = tmp; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + +#define XOR(value, clk_inc1, clk_inc2, pc_inc) \ + do { \ + CLK += clk_inc1; \ + reg_a ^= value; \ + reg_f = SZP[reg_a]; \ + CLK += clk_inc2; \ + INC_PC(pc_inc); \ + } while (0) + + +/* ------------------------------------------------------------------------- */ + +/* Extented opcodes. */ + +static void opcode_cb(BYTE ip1, BYTE ip2, BYTE ip3, WORD ip12, WORD ip23) +{ + switch (ip1) { + case 0x00: /* RLC B */ + RLC(reg_b); + break; + case 0x01: /* RLC C */ + RLC(reg_c); + break; + case 0x02: /* RLC D */ + RLC(reg_d); + break; + case 0x03: /* RLC E */ + RLC(reg_e); + break; + case 0x04: /* RLC H */ + RLC(reg_h); + break; + case 0x05: /* RLC L */ + RLC(reg_l); + break; + case 0x06: /* RLC (HL) */ + RLCXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x07: /* RLC A */ + RLC(reg_a); + break; + case 0x08: /* RRC B */ + RRC(reg_b); + break; + case 0x09: /* RRC C */ + RRC(reg_c); + break; + case 0x0a: /* RRC D */ + RRC(reg_d); + break; + case 0x0b: /* RRC E */ + RRC(reg_e); + break; + case 0x0c: /* RRC H */ + RRC(reg_h); + break; + case 0x0d: /* RRC L */ + RRC(reg_l); + break; + case 0x0e: /* RRC (HL) */ + RRCXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x0f: /* RRC A */ + RRC(reg_a); + break; + case 0x10: /* RL B */ + RL(reg_b); + break; + case 0x11: /* RL C */ + RL(reg_c); + break; + case 0x12: /* RL D */ + RL(reg_d); + break; + case 0x13: /* RL E */ + RL(reg_e); + break; + case 0x14: /* RL H */ + RL(reg_h); + break; + case 0x15: /* RL L */ + RL(reg_l); + break; + case 0x16: /* RL (HL) */ + RLXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x17: /* RL A */ + RL(reg_a); + break; + case 0x18: /* RR B */ + RR(reg_b); + break; + case 0x19: /* RR C */ + RR(reg_c); + break; + case 0x1a: /* RR D */ + RR(reg_d); + break; + case 0x1b: /* RR E */ + RR(reg_e); + break; + case 0x1c: /* RR H */ + RR(reg_h); + break; + case 0x1d: /* RR L */ + RR(reg_l); + break; + case 0x1e: /* RR (HL) */ + RRXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x1f: /* RR A */ + RR(reg_a); + break; + case 0x20: /* SLA B */ + SLA(reg_b); + break; + case 0x21: /* SLA C */ + SLA(reg_c); + break; + case 0x22: /* SLA D */ + SLA(reg_d); + break; + case 0x23: /* SLA E */ + SLA(reg_e); + break; + case 0x24: /* SLA H */ + SLA(reg_h); + break; + case 0x25: /* SLA L */ + SLA(reg_l); + break; + case 0x26: /* SLA (HL) */ + SLAXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x27: /* SLA A */ + SLA(reg_a); + break; + case 0x28: /* SRA B */ + SRA(reg_b); + break; + case 0x29: /* SRA C */ + SRA(reg_c); + break; + case 0x2a: /* SRA D */ + SRA(reg_d); + break; + case 0x2b: /* SRA E */ + SRA(reg_e); + break; + case 0x2c: /* SRA H */ + SRA(reg_h); + break; + case 0x2d: /* SRA L */ + SRA(reg_l); + break; + case 0x2e: /* SRA (HL) */ + SRAXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x2f: /* SRA A */ + SRA(reg_a); + break; + case 0x30: /* SLL B */ + SLL(reg_b); + break; + case 0x31: /* SLL C */ + SLL(reg_c); + break; + case 0x32: /* SLL D */ + SLL(reg_d); + break; + case 0x33: /* SLL E */ + SLL(reg_e); + break; + case 0x34: /* SLL H */ + SLL(reg_h); + break; + case 0x35: /* SLL L */ + SLL(reg_l); + break; + case 0x36: /* SLL (HL) */ + SLLXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x37: /* SLL A */ + SLL(reg_a); + break; + case 0x38: /* SRL B */ + SRL(reg_b); + break; + case 0x39: /* SRL C */ + SRL(reg_c); + break; + case 0x3a: /* SRL D */ + SRL(reg_d); + break; + case 0x3b: /* SRL E */ + SRL(reg_e); + break; + case 0x3c: /* SRL H */ + SRL(reg_h); + break; + case 0x3d: /* SRL L */ + SRL(reg_l); + break; + case 0x3e: /* SRL (HL) */ + SRLXX(HL_WORD(), 4, 4, 7, 2); + break; + case 0x3f: /* SRL A */ + SRL(reg_a); + break; + case 0x40: /* BIT B 0 */ + BIT(reg_b, 0, 0, 8, 2); + break; + case 0x41: /* BIT C 0 */ + BIT(reg_c, 0, 0, 8, 2); + break; + case 0x42: /* BIT D 0 */ + BIT(reg_d, 0, 0, 8, 2); + break; + case 0x43: /* BIT E 0 */ + BIT(reg_e, 0, 0, 8, 2); + break; + case 0x44: /* BIT H 0 */ + BIT(reg_h, 0, 0, 8, 2); + break; + case 0x45: /* BIT L 0 */ + BIT(reg_l, 0, 0, 8, 2); + break; + case 0x46: /* BIT (HL) 0 */ + BIT(LOAD(HL_WORD()), 0, 4, 8, 2); + break; + case 0x47: /* BIT A 0 */ + BIT(reg_a, 0, 0, 8, 2); + break; + case 0x48: /* BIT B 1 */ + BIT(reg_b, 1, 0, 8, 2); + break; + case 0x49: /* BIT C 1 */ + BIT(reg_c, 1, 0, 8, 2); + break; + case 0x4a: /* BIT D 1 */ + BIT(reg_d, 1, 0, 8, 2); + break; + case 0x4b: /* BIT E 1 */ + BIT(reg_e, 1, 0, 8, 2); + break; + case 0x4c: /* BIT H 1 */ + BIT(reg_h, 1, 0, 8, 2); + break; + case 0x4d: /* BIT L 1 */ + BIT(reg_l, 1, 0, 8, 2); + break; + case 0x4e: /* BIT (HL) 1 */ + BIT(LOAD(HL_WORD()), 1, 4, 8, 2); + break; + case 0x4f: /* BIT A 1 */ + BIT(reg_a, 1, 0, 8, 2); + break; + case 0x50: /* BIT B 2 */ + BIT(reg_b, 2, 0, 8, 2); + break; + case 0x51: /* BIT C 2 */ + BIT(reg_c, 2, 0, 8, 2); + break; + case 0x52: /* BIT D 2 */ + BIT(reg_d, 2, 0, 8, 2); + break; + case 0x53: /* BIT E 2 */ + BIT(reg_e, 2, 0, 8, 2); + break; + case 0x54: /* BIT H 2 */ + BIT(reg_h, 2, 0, 8, 2); + break; + case 0x55: /* BIT L 2 */ + BIT(reg_l, 2, 0, 8, 2); + break; + case 0x56: /* BIT (HL) 2 */ + BIT(LOAD(HL_WORD()), 2, 4, 8, 2); + break; + case 0x57: /* BIT A 2 */ + BIT(reg_a, 2, 0, 8, 2); + break; + case 0x58: /* BIT B 3 */ + BIT(reg_b, 3, 0, 8, 2); + break; + case 0x59: /* BIT C 3 */ + BIT(reg_c, 3, 0, 8, 2); + break; + case 0x5a: /* BIT D 3 */ + BIT(reg_d, 3, 0, 8, 2); + break; + case 0x5b: /* BIT E 3 */ + BIT(reg_e, 3, 0, 8, 2); + break; + case 0x5c: /* BIT H 3 */ + BIT(reg_h, 3, 0, 8, 2); + break; + case 0x5d: /* BIT L 3 */ + BIT(reg_l, 3, 0, 8, 2); + break; + case 0x5e: /* BIT (HL) 3 */ + BIT(LOAD(HL_WORD()), 3, 4, 8, 2); + break; + case 0x5f: /* BIT A 3 */ + BIT(reg_a, 3, 0, 8, 2); + break; + case 0x60: /* BIT B 4 */ + BIT(reg_b, 4, 0, 8, 2); + break; + case 0x61: /* BIT C 4 */ + BIT(reg_c, 4, 0, 8, 2); + break; + case 0x62: /* BIT D 4 */ + BIT(reg_d, 4, 0, 8, 2); + break; + case 0x63: /* BIT E 4 */ + BIT(reg_e, 4, 0, 8, 2); + break; + case 0x64: /* BIT H 4 */ + BIT(reg_h, 4, 0, 8, 2); + break; + case 0x65: /* BIT L 4 */ + BIT(reg_l, 4, 0, 8, 2); + break; + case 0x66: /* BIT (HL) 4 */ + BIT(LOAD(HL_WORD()), 4, 4, 8, 2); + break; + case 0x67: /* BIT A 4 */ + BIT(reg_a, 4, 0, 8, 2); + break; + case 0x68: /* BIT B 5 */ + BIT(reg_b, 5, 0, 8, 2); + break; + case 0x69: /* BIT C 5 */ + BIT(reg_c, 5, 0, 8, 2); + break; + case 0x6a: /* BIT D 5 */ + BIT(reg_d, 5, 0, 8, 2); + break; + case 0x6b: /* BIT E 5 */ + BIT(reg_e, 5, 0, 8, 2); + break; + case 0x6c: /* BIT H 5 */ + BIT(reg_h, 5, 0, 8, 2); + break; + case 0x6d: /* BIT L 5 */ + BIT(reg_l, 5, 0, 8, 2); + break; + case 0x6e: /* BIT (HL) 5 */ + BIT(LOAD(HL_WORD()), 5, 4, 8, 2); + break; + case 0x6f: /* BIT A 5 */ + BIT(reg_a, 5, 0, 8, 2); + break; + case 0x70: /* BIT B 6 */ + BIT(reg_b, 6, 0, 8, 2); + break; + case 0x71: /* BIT C 6 */ + BIT(reg_c, 6, 0, 8, 2); + break; + case 0x72: /* BIT D 6 */ + BIT(reg_d, 6, 0, 8, 2); + break; + case 0x73: /* BIT E 6 */ + BIT(reg_e, 6, 0, 8, 2); + break; + case 0x74: /* BIT H 6 */ + BIT(reg_h, 6, 0, 8, 2); + break; + case 0x75: /* BIT L 6 */ + BIT(reg_l, 6, 0, 8, 2); + break; + case 0x76: /* BIT (HL) 6 */ + BIT(LOAD(HL_WORD()), 6, 4, 8, 2); + break; + case 0x77: /* BIT A 6 */ + BIT(reg_a, 6, 0, 8, 2); + break; + case 0x78: /* BIT B 7 */ + BIT(reg_b, 7, 0, 8, 2); + break; + case 0x79: /* BIT C 7 */ + BIT(reg_c, 7, 0, 8, 2); + break; + case 0x7a: /* BIT D 7 */ + BIT(reg_d, 7, 0, 8, 2); + break; + case 0x7b: /* BIT E 7 */ + BIT(reg_e, 7, 0, 8, 2); + break; + case 0x7c: /* BIT H 7 */ + BIT(reg_h, 7, 0, 8, 2); + break; + case 0x7d: /* BIT L 7 */ + BIT(reg_l, 7, 0, 8, 2); + break; + case 0x7e: /* BIT (HL) 7 */ + BIT(LOAD(HL_WORD()), 7, 4, 8, 2); + break; + case 0x7f: /* BIT A 7 */ + BIT(reg_a, 7, 0, 8, 2); + break; + case 0x80: /* RES B 0 */ + RES(reg_b, 0); + break; + case 0x81: /* RES C 0 */ + RES(reg_c, 0); + break; + case 0x82: /* RES D 0 */ + RES(reg_d, 0); + break; + case 0x83: /* RES E 0 */ + RES(reg_e, 0); + break; + case 0x84: /* RES H 0 */ + RES(reg_h, 0); + break; + case 0x85: /* RES L 0 */ + RES(reg_l, 0); + break; + case 0x86: /* RES (HL) 0 */ + RESXX(0, HL_WORD(), 4, 4, 7, 2); + break; + case 0x87: /* RES A 0 */ + RES(reg_a, 0); + break; + case 0x88: /* RES B 1 */ + RES(reg_b, 1); + break; + case 0x89: /* RES C 1 */ + RES(reg_c, 1); + break; + case 0x8a: /* RES D 1 */ + RES(reg_d, 1); + break; + case 0x8b: /* RES E 1 */ + RES(reg_e, 1); + break; + case 0x8c: /* RES H 1 */ + RES(reg_h, 1); + break; + case 0x8d: /* RES L 1 */ + RES(reg_l, 1); + break; + case 0x8e: /* RES (HL) 1 */ + RESXX(1, HL_WORD(), 4, 4, 7, 2); + break; + case 0x8f: /* RES A 1 */ + RES(reg_a, 1); + break; + case 0x90: /* RES B 2 */ + RES(reg_b, 2); + break; + case 0x91: /* RES C 2 */ + RES(reg_c, 2); + break; + case 0x92: /* RES D 2 */ + RES(reg_d, 2); + break; + case 0x93: /* RES E 2 */ + RES(reg_e, 2); + break; + case 0x94: /* RES H 2 */ + RES(reg_h, 2); + break; + case 0x95: /* RES L 2 */ + RES(reg_l, 2); + break; + case 0x96: /* RES (HL) 2 */ + RESXX(2, HL_WORD(), 4, 4, 7, 2); + break; + case 0x97: /* RES A 2 */ + RES(reg_a, 2); + break; + case 0x98: /* RES B 3 */ + RES(reg_b, 3); + break; + case 0x99: /* RES C 3 */ + RES(reg_c, 3); + break; + case 0x9a: /* RES D 3 */ + RES(reg_d, 3); + break; + case 0x9b: /* RES E 3 */ + RES(reg_e, 3); + break; + case 0x9c: /* RES H 3 */ + RES(reg_h, 3); + break; + case 0x9d: /* RES L 3 */ + RES(reg_l, 3); + break; + case 0x9e: /* RES (HL) 3 */ + RESXX(3, HL_WORD(), 4, 4, 7, 2); + break; + case 0x9f: /* RES A 3 */ + RES(reg_a, 3); + break; + case 0xa0: /* RES B 4 */ + RES(reg_b, 4); + break; + case 0xa1: /* RES C 4 */ + RES(reg_c, 4); + break; + case 0xa2: /* RES D 4 */ + RES(reg_d, 4); + break; + case 0xa3: /* RES E 4 */ + RES(reg_e, 4); + break; + case 0xa4: /* RES H 4 */ + RES(reg_h, 4); + break; + case 0xa5: /* RES L 4 */ + RES(reg_l, 4); + break; + case 0xa6: /* RES (HL) 4 */ + RESXX(4, HL_WORD(), 4, 4, 7, 2); + break; + case 0xa7: /* RES A 4 */ + RES(reg_a, 4); + break; + case 0xa8: /* RES B 5 */ + RES(reg_b, 5); + break; + case 0xa9: /* RES C 5 */ + RES(reg_c, 5); + break; + case 0xaa: /* RES D 5 */ + RES(reg_d, 5); + break; + case 0xab: /* RES E 5 */ + RES(reg_e, 5); + break; + case 0xac: /* RES H 5 */ + RES(reg_h, 5); + break; + case 0xad: /* RES L 5 */ + RES(reg_l, 5); + break; + case 0xae: /* RES (HL) 5 */ + RESXX(5, HL_WORD(), 4, 4, 7, 2); + break; + case 0xaf: /* RES A 5 */ + RES(reg_a, 5); + break; + case 0xb0: /* RES B 6 */ + RES(reg_b, 6); + break; + case 0xb1: /* RES C 6 */ + RES(reg_c, 6); + break; + case 0xb2: /* RES D 6 */ + RES(reg_d, 6); + break; + case 0xb3: /* RES E 6 */ + RES(reg_e, 6); + break; + case 0xb4: /* RES H 6 */ + RES(reg_h, 6); + break; + case 0xb5: /* RES L 6 */ + RES(reg_l, 6); + break; + case 0xb6: /* RES (HL) 6 */ + RESXX(6, HL_WORD(), 4, 4, 7, 2); + break; + case 0xb7: /* RES A 6 */ + RES(reg_a, 6); + break; + case 0xb8: /* RES B 7 */ + RES(reg_b, 7); + break; + case 0xb9: /* RES C 7 */ + RES(reg_c, 7); + break; + case 0xba: /* RES D 7 */ + RES(reg_d, 7); + break; + case 0xbb: /* RES E 7 */ + RES(reg_e, 7); + break; + case 0xbc: /* RES H 7 */ + RES(reg_h, 7); + break; + case 0xbd: /* RES L 7 */ + RES(reg_l, 7); + break; + case 0xbe: /* RES (HL) 7 */ + RESXX(7, HL_WORD(), 4, 4, 7, 2); + break; + case 0xbf: /* RES A 7 */ + RES(reg_a, 7); + break; + case 0xc0: /* SET B 0 */ + SET(reg_b, 0); + break; + case 0xc1: /* SET C 0 */ + SET(reg_c, 0); + break; + case 0xc2: /* SET D 0 */ + SET(reg_d, 0); + break; + case 0xc3: /* SET E 0 */ + SET(reg_e, 0); + break; + case 0xc4: /* SET H 0 */ + SET(reg_h, 0); + break; + case 0xc5: /* SET L 0 */ + SET(reg_l, 0); + break; + case 0xc6: /* SET (HL) 0 */ + SETXX(0, HL_WORD(), 4, 4, 7, 2); + break; + case 0xc7: /* SET A 0 */ + SET(reg_a, 0); + break; + case 0xc8: /* SET B 1 */ + SET(reg_b, 1); + break; + case 0xc9: /* SET C 1 */ + SET(reg_c, 1); + break; + case 0xca: /* SET D 1 */ + SET(reg_d, 1); + break; + case 0xcb: /* SET E 1 */ + SET(reg_e, 1); + break; + case 0xcc: /* SET H 1 */ + SET(reg_h, 1); + break; + case 0xcd: /* SET L 1 */ + SET(reg_l, 1); + break; + case 0xce: /* SET (HL) 1 */ + SETXX(1, HL_WORD(), 4, 4, 7, 2); + break; + case 0xcf: /* SET A 1 */ + SET(reg_a, 1); + break; + case 0xd0: /* SET B 2 */ + SET(reg_b, 2); + break; + case 0xd1: /* SET C 2 */ + SET(reg_c, 2); + break; + case 0xd2: /* SET D 2 */ + SET(reg_d, 2); + break; + case 0xd3: /* SET E 2 */ + SET(reg_e, 2); + break; + case 0xd4: /* SET H 2 */ + SET(reg_h, 2); + break; + case 0xd5: /* SET L 2 */ + SET(reg_l, 2); + break; + case 0xd6: /* SET (HL) 2 */ + SETXX(2, HL_WORD(), 4, 4, 7, 2); + break; + case 0xd7: /* SET A 2 */ + SET(reg_a, 2); + break; + case 0xd8: /* SET B 3 */ + SET(reg_b, 3); + break; + case 0xd9: /* SET C 3 */ + SET(reg_c, 3); + break; + case 0xda: /* SET D 3 */ + SET(reg_d, 3); + break; + case 0xdb: /* SET E 3 */ + SET(reg_e, 3); + break; + case 0xdc: /* SET H 3 */ + SET(reg_h, 3); + break; + case 0xdd: /* SET L 3 */ + SET(reg_l, 3); + break; + case 0xde: /* SET (HL) 3 */ + SETXX(3, HL_WORD(), 4, 4, 7, 2); + break; + case 0xdf: /* SET A 3 */ + SET(reg_a, 3); + break; + case 0xe0: /* SET B 4 */ + SET(reg_b, 4); + break; + case 0xe1: /* SET C 4 */ + SET(reg_c, 4); + break; + case 0xe2: /* SET D 4 */ + SET(reg_d, 4); + break; + case 0xe3: /* SET E 4 */ + SET(reg_e, 4); + break; + case 0xe4: /* SET H 4 */ + SET(reg_h, 4); + break; + case 0xe5: /* SET L 4 */ + SET(reg_l, 4); + break; + case 0xe6: /* SET (HL) 4 */ + SETXX(4, HL_WORD(), 4, 4, 7, 2); + break; + case 0xe7: /* SET A 4 */ + SET(reg_a, 4); + break; + case 0xe8: /* SET B 5 */ + SET(reg_b, 5); + break; + case 0xe9: /* SET C 5 */ + SET(reg_c, 5); + break; + case 0xea: /* SET D 5 */ + SET(reg_d, 5); + break; + case 0xeb: /* SET E 5 */ + SET(reg_e, 5); + break; + case 0xec: /* SET H 5 */ + SET(reg_h, 5); + break; + case 0xed: /* SET L 5 */ + SET(reg_l, 5); + break; + case 0xee: /* SET (HL) 5 */ + SETXX(5, HL_WORD(), 4, 4, 7, 2); + break; + case 0xef: /* SET A 5 */ + SET(reg_a, 5); + break; + case 0xf0: /* SET B 6 */ + SET(reg_b, 6); + break; + case 0xf1: /* SET C 6 */ + SET(reg_c, 6); + break; + case 0xf2: /* SET D 6 */ + SET(reg_d, 6); + break; + case 0xf3: /* SET E 6 */ + SET(reg_e, 6); + break; + case 0xf4: /* SET H 6 */ + SET(reg_h, 6); + break; + case 0xf5: /* SET L 6 */ + SET(reg_l, 6); + break; + case 0xf6: /* SET (HL) 6 */ + SETXX(6, HL_WORD(), 4, 4, 7, 2); + break; + case 0xf7: /* SET A 6 */ + SET(reg_a, 6); + break; + case 0xf8: /* SET B 7 */ + SET(reg_b, 7); + break; + case 0xf9: /* SET C 7 */ + SET(reg_c, 7); + break; + case 0xfa: /* SET D 7 */ + SET(reg_d, 7); + break; + case 0xfb: /* SET E 7 */ + SET(reg_e, 7); + break; + case 0xfc: /* SET H 7 */ + SET(reg_h, 7); + break; + case 0xfd: /* SET L 7 */ + SET(reg_l, 7); + break; + case 0xfe: /* SET (HL) 7 */ + SETXX(7, HL_WORD(), 4, 4, 7, 2); + break; + case 0xff: /* SET A 7 */ + SET(reg_a, 7); + break; + default: + INC_PC(2); + } +} + +static void opcode_dd_cb(BYTE iip2, BYTE iip3, WORD iip23) +{ + switch (iip3) { + case 0x00: /* RLC (IX+d),B */ + RLCXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x01: /* RLC (IX+d),C */ + RLCXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x02: /* RLC (IX+d),D */ + RLCXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x03: /* RLC (IX+d),E */ + RLCXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x04: /* RLC (IX+d),H */ + RLCXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x05: /* RLC (IX+d),L */ + RLCXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x06: /* RLC (IX+d) */ + RLCXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x07: /* RLC (IX+d),A */ + RLCXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x08: /* RRC (IX+d),B */ + RRCXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x09: /* RRC (IX+d),C */ + RRCXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0a: /* RRC (IX+d),D */ + RRCXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0b: /* RRC (IX+d),E */ + RRCXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0c: /* RRC (IX+d),H */ + RRCXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0d: /* RRC (IX+d),L */ + RRCXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0e: /* RRC (IX+d) */ + RRCXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0f: /* RRC (IX+d),A */ + RRCXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x10: /* RL (IX+d),B */ + RLXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x11: /* RL (IX+d),C */ + RLXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x12: /* RL (IX+d),D */ + RLXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x13: /* RL (IX+d),E */ + RLXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x14: /* RL (IX+d),H */ + RLXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x15: /* RL (IX+d),L */ + RLXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x16: /* RL (IX+d) */ + RLXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x17: /* RL (IX+d),A */ + RLXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x18: /* RR (IX+d),B */ + RRXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x19: /* RR (IX+d),C */ + RRXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1a: /* RR (IX+d),D */ + RRXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1b: /* RR (IX+d),E */ + RRXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1c: /* RR (IX+d),H */ + RRXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1d: /* RR (IX+d),L */ + RRXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1e: /* RR (IX+d) */ + RRXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1f: /* RR (IX+d),A */ + RRXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x20: /* SLA (IX+d),B */ + SLAXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x21: /* SLA (IX+d),C */ + SLAXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x22: /* SLA (IX+d),D */ + SLAXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x23: /* SLA (IX+d),E */ + SLAXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x24: /* SLA (IX+d),H */ + SLAXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x25: /* SLA (IX+d),L */ + SLAXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x26: /* SLA (IX+d) */ + SLAXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x27: /* SLA (IX+d),A */ + SLAXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x28: /* SRA (IX+d),B */ + SRAXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x29: /* SRA (IX+d),C */ + SRAXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2a: /* SRA (IX+d),D */ + SRAXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2b: /* SRA (IX+d),E */ + SRAXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2c: /* SRA (IX+d),H */ + SRAXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2d: /* SRA (IX+d),L */ + SRAXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2e: /* SRA (IX+d) */ + SRAXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2f: /* SRA (IX+d),A */ + SRAXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x30: /* SLL (IX+d),B */ + SLLXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x31: /* SLL (IX+d),C */ + SLLXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x32: /* SLL (IX+d),D */ + SLLXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x33: /* SLL (IX+d),E */ + SLLXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x34: /* SLL (IX+d),H */ + SLLXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x35: /* SLL (IX+d),L */ + SLLXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x36: /* SLL (IX+d) */ + SLLXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x37: /* SLL (IX+d),A */ + SLLXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x38: /* SRL (IX+d),B */ + SRLXXREG(reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x39: /* SRL (IX+d),C */ + SRLXXREG(reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3a: /* SRL (IX+d),D */ + SRLXXREG(reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3b: /* SRL (IX+d),E */ + SRLXXREG(reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3c: /* SRL (IX+d),H */ + SRLXXREG(reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3d: /* SRL (IX+d),L */ + SRLXXREG(reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3e: /* SRL (IX+d) */ + SRLXX(IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3f: /* SRL (IX+d),A */ + SRLXXREG(reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x40: /* BIT (IX+d) 0 */ + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + BIT(LOAD(IX_WORD_OFF(iip2)), 0, 8, 12, 4); + break; + case 0x48: /* BIT (IX+d) 1 */ + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + BIT(LOAD(IX_WORD_OFF(iip2)), 1, 8, 12, 4); + break; + case 0x50: /* BIT (IX+d) 2 */ + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + BIT(LOAD(IX_WORD_OFF(iip2)), 2, 8, 12, 4); + break; + case 0x58: /* BIT (IX+d) 3 */ + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + BIT(LOAD(IX_WORD_OFF(iip2)), 3, 8, 12, 4); + break; + case 0x60: /* BIT (IX+d) 4 */ + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + BIT(LOAD(IX_WORD_OFF(iip2)), 4, 8, 12, 4); + break; + case 0x68: /* BIT (IX+d) 5 */ + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + BIT(LOAD(IX_WORD_OFF(iip2)), 5, 8, 12, 4); + break; + case 0x70: /* BIT (IX+d) 6 */ + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + BIT(LOAD(IX_WORD_OFF(iip2)), 6, 8, 12, 4); + break; + case 0x78: /* BIT (IX+d) 7 */ + case 0x79: + case 0x7a: + case 0x7b: + case 0x7c: + case 0x7d: + case 0x7e: + case 0x7f: + BIT(LOAD(IX_WORD_OFF(iip2)), 7, 8, 12, 4); + break; + case 0x80: /* RES (IX+d),B 0 */ + RESXXREG(0, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x81: /* RES (IX+d),C 0 */ + RESXXREG(0, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x82: /* RES (IX+d),D 0 */ + RESXXREG(0, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x83: /* RES (IX+d),E 0 */ + RESXXREG(0, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x84: /* RES (IX+d),H 0 */ + RESXXREG(0, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x85: /* RES (IX+d),L 0 */ + RESXXREG(0, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x86: /* RES (IX+d) 0 */ + RESXX(0, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x87: /* RES (IX+d),A 0 */ + RESXXREG(0, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x88: /* RES (IX+d),B 1 */ + RESXXREG(1, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x89: /* RES (IX+d),C 1 */ + RESXXREG(1, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8a: /* RES (IX+d),D 1 */ + RESXXREG(1, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8b: /* RES (IX+d),E 1 */ + RESXXREG(1, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8c: /* RES (IX+d),H 1 */ + RESXXREG(1, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8d: /* RES (IX+d),L 1 */ + RESXXREG(1, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8e: /* RES (IX+d) 1 */ + RESXX(1, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8f: /* RES (IX+d),A 1 */ + RESXXREG(1, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x90: /* RES (IX+d),B 2 */ + RESXXREG(2, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x91: /* RES (IX+d),C 2 */ + RESXXREG(2, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x92: /* RES (IX+d),D 2 */ + RESXXREG(2, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x93: /* RES (IX+d),E 2 */ + RESXXREG(2, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x94: /* RES (IX+d),H 2 */ + RESXXREG(2, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x95: /* RES (IX+d),L 2 */ + RESXXREG(2, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x96: /* RES (IX+d) 2 */ + RESXX(2, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x97: /* RES (IX+d),A 2 */ + RESXXREG(2, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x98: /* RES (IX+d),B 3 */ + RESXXREG(3, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x99: /* RES (IX+d),C 3 */ + RESXXREG(3, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9a: /* RES (IX+d),D 3 */ + RESXXREG(3, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9b: /* RES (IX+d),E 3 */ + RESXXREG(3, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9c: /* RES (IX+d),H 3 */ + RESXXREG(3, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9d: /* RES (IX+d),L 3 */ + RESXXREG(3, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9e: /* RES (IX+d) 3 */ + RESXX(3, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9f: /* RES (IX+d),A 3 */ + RESXXREG(3, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa0: /* RES (IX+d),B 4 */ + RESXXREG(4, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa1: /* RES (IX+d),C 4 */ + RESXXREG(4, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa2: /* RES (IX+d),D 4 */ + RESXXREG(4, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa3: /* RES (IX+d),E 4 */ + RESXXREG(4, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa4: /* RES (IX+d),H 4 */ + RESXXREG(4, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa5: /* RES (IX+d),L 4 */ + RESXXREG(4, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa6: /* RES (IX+d) 4 */ + RESXX(4, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa7: /* RES (IX+d),A 4 */ + RESXXREG(4, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa8: /* RES (IX+d),B 5 */ + RESXXREG(5, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa9: /* RES (IX+d),C 5 */ + RESXXREG(5, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xaa: /* RES (IX+d),D 5 */ + RESXXREG(5, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xab: /* RES (IX+d),E 5 */ + RESXXREG(5, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xac: /* RES (IX+d),H 5 */ + RESXXREG(5, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xad: /* RES (IX+d),L 5 */ + RESXXREG(5, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xae: /* RES (IX+d) 5 */ + RESXX(5, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xaf: /* RES (IX+d),A 5 */ + RESXXREG(5, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb0: /* RES (IX+d),B 6 */ + RESXXREG(6, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb1: /* RES (IX+d),C 6 */ + RESXXREG(6, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb2: /* RES (IX+d),D 6 */ + RESXXREG(6, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb3: /* RES (IX+d),E 6 */ + RESXXREG(6, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb4: /* RES (IX+d),H 6 */ + RESXXREG(6, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb5: /* RES (IX+d),L 6 */ + RESXXREG(6, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb6: /* RES (IX+d) 6 */ + RESXX(6, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb7: /* RES (IX+d),A 6 */ + RESXXREG(6, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb8: /* RES (IX+d),B 7 */ + RESXXREG(7, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb9: /* RES (IX+d),C 7 */ + RESXXREG(7, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xba: /* RES (IX+d),D 7 */ + RESXXREG(7, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbb: /* RES (IX+d),E 7 */ + RESXXREG(7, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbc: /* RES (IX+d),H 7 */ + RESXXREG(7, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbd: /* RES (IX+d),L 7 */ + RESXXREG(7, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbe: /* RES (IX+d) 7 */ + RESXX(7, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbf: /* RES (IX+d),A 7 */ + RESXXREG(7, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc0: /* SET (IX+d),B 0 */ + SETXXREG(0, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc1: /* SET (IX+d),C 0 */ + SETXXREG(0, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc2: /* SET (IX+d),D 0 */ + SETXXREG(0, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc3: /* SET (IX+d),E 0 */ + SETXXREG(0, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc4: /* SET (IX+d),H 0 */ + SETXXREG(0, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc5: /* SET (IX+d),L 0 */ + SETXXREG(0, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc6: /* SET (IX+d) 0 */ + SETXX(0, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc7: /* SET (IX+d),A 0 */ + SETXXREG(0, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc8: /* SET (IX+d),B 1 */ + SETXXREG(1, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc9: /* SET (IX+d),C 1 */ + SETXXREG(1, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xca: /* SET (IX+d),D 1 */ + SETXXREG(1, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcb: /* SET (IX+d),E 1 */ + SETXXREG(1, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcc: /* SET (IX+d),H 1 */ + SETXXREG(1, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcd: /* SET (IX+d),L 1 */ + SETXXREG(1, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xce: /* SET (IX+d) 1 */ + SETXX(1, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcf: /* SET (IX+d),A 1 */ + SETXXREG(1, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd0: /* SET (IX+d),B 2 */ + SETXXREG(2, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd1: /* SET (IX+d),C 2 */ + SETXXREG(2, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd2: /* SET (IX+d),D 2 */ + SETXXREG(2, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd3: /* SET (IX+d),E 2 */ + SETXXREG(2, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd4: /* SET (IX+d),H 2 */ + SETXXREG(2, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd5: /* SET (IX+d),L 2 */ + SETXXREG(2, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd6: /* SET (IX+d) 2 */ + SETXX(2, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd7: /* SET (IX+d),A 2 */ + SETXXREG(2, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd8: /* SET (IX+d),B 3 */ + SETXXREG(3, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd9: /* SET (IX+d),C 3 */ + SETXXREG(3, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xda: /* SET (IX+d),D 3 */ + SETXXREG(3, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdb: /* SET (IX+d),E 3 */ + SETXXREG(3, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdc: /* SET (IX+d),H 3 */ + SETXXREG(3, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdd: /* SET (IX+d),L 3 */ + SETXXREG(3, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xde: /* SET (IX+d) 3 */ + SETXX(3, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdf: /* SET (IX+d),A 3 */ + SETXXREG(3, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe0: /* SET (IX+d),B 4 */ + SETXXREG(4, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe1: /* SET (IX+d),C 4 */ + SETXXREG(4, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe2: /* SET (IX+d),D 4 */ + SETXXREG(4, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe3: /* SET (IX+d),E 4 */ + SETXXREG(4, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe4: /* SET (IX+d),H 4 */ + SETXXREG(4, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe5: /* SET (IX+d),L 4 */ + SETXXREG(4, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe6: /* SET (IX+d) 4 */ + SETXX(4, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe7: /* SET (IX+d),A 4 */ + SETXXREG(4, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe8: /* SET (IX+d),B 5 */ + SETXXREG(5, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe9: /* SET (IX+d),C 5 */ + SETXXREG(5, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xea: /* SET (IX+d),D 5 */ + SETXXREG(5, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xeb: /* SET (IX+d),E 5 */ + SETXXREG(5, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xec: /* SET (IX+d),H 5 */ + SETXXREG(5, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xed: /* SET (IX+d),L 5 */ + SETXXREG(5, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xee: /* SET (IX+d) 5 */ + SETXX(5, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xef: /* SET (IX+d),A 5 */ + SETXXREG(5, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf0: /* SET (IX+d),B 6 */ + SETXXREG(6, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf1: /* SET (IX+d),C 6 */ + SETXXREG(6, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf2: /* SET (IX+d),D 6 */ + SETXXREG(6, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf3: /* SET (IX+d),E 6 */ + SETXXREG(6, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf4: /* SET (IX+d),H 6 */ + SETXXREG(6, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf5: /* SET (IX+d),L 6 */ + SETXXREG(6, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf6: /* SET (IX+d) 6 */ + SETXX(6, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf7: /* SET (IX+d),A 6 */ + SETXXREG(6, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf8: /* SET (IX+d),B 7 */ + SETXXREG(7, reg_b, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf9: /* SET (IX+d),C 7 */ + SETXXREG(7, reg_c, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfa: /* SET (IX+d),D 7 */ + SETXXREG(7, reg_d, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfb: /* SET (IX+d),E 7 */ + SETXXREG(7, reg_e, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfc: /* SET (IX+d),H 7 */ + SETXXREG(7, reg_h, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfd: /* SET (IX+d),L 7 */ + SETXXREG(7, reg_l, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfe: /* SET (IX+d) 7 */ + SETXX(7, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xff: /* SET (IX+d),A 7 */ + SETXXREG(7, reg_a, IX_WORD_OFF(iip2), 4, 4, 15, 4); + break; + default: + INC_PC(4); + } +} + +static void opcode_dd(BYTE ip1, BYTE ip2, BYTE ip3, WORD ip12, WORD ip23) +{ + switch (ip1) { + case 0x00: /* NOP */ + NOP(8, 2); + break; + case 0x01: /* LD BC # */ + LDW(ip23, reg_b, reg_c, 10, 0, 4); + break; + case 0x02: /* LD (BC) A */ + STREG(BC_WORD(), reg_a, 8, 3, 2); + break; + case 0x03: /* INC BC */ + DECINC(INC_BC_WORD(), 10, 2); + break; + case 0x04: /* INC B */ + INCREG(reg_b, 7, 2); + break; + case 0x05: /* DEC B */ + DECREG(reg_b, 7, 2); + break; + case 0x06: /* LD B # */ + LDREG(reg_b, ip2, 4, 5, 3); + break; + case 0x07: /* RLCA */ + RLCA(8, 2); + break; + case 0x08: /* EX AF AF' */ + EXAFAF(12, 2); + break; + case 0x09: /* ADD IX BC */ + ADDXXREG(reg_ixh, reg_ixl, reg_b, reg_c, 15, 2); + break; + case 0x0a: /* LD A (BC) */ + LDREG(reg_a, LOAD(BC_WORD()), 8, 3, 2); + break; + case 0x0b: /* DEC BC */ + DECINC(DEC_BC_WORD(), 10, 2); + break; + case 0x0c: /* INC C */ + INCREG(reg_c, 7, 2); + break; + case 0x0d: /* DEC C */ + DECREG(reg_c, 7, 2); + break; + case 0x0e: /* LD C # */ + LDREG(reg_c, ip2, 4, 5, 3); + break; + case 0x0f: /* RRCA */ + RRCA(8, 2); + break; + case 0x10: /* DJNZ */ + DJNZ(ip2, 3); + break; + case 0x11: /* LD DE # */ + LDW(ip23, reg_d, reg_e, 10, 0, 4); + break; + case 0x12: /* LD (DE) A */ + STREG(DE_WORD(), reg_a, 8, 3, 2); + break; + case 0x13: /* INC DE */ + DECINC(INC_DE_WORD(), 10, 2); + break; + case 0x14: /* INC D */ + INCREG(reg_d, 7, 2); + break; + case 0x15: /* DEC D */ + DECREG(reg_d, 7, 2); + break; + case 0x16: /* LD D # */ + LDREG(reg_d, ip2, 4, 5, 3); + break; + case 0x17: /* RLA */ + RLA(8, 2); + break; + case 0x19: /* ADD IX DE */ + ADDXXREG(reg_ixh, reg_ixl, reg_d, reg_e, 15, 2); + break; + case 0x1a: /* LD A DE */ + LDREG(reg_a, LOAD(DE_WORD()), 8, 3, 2); + break; + case 0x1b: /* DEC DE */ + DECINC(DEC_DE_WORD(), 10, 2); + break; + case 0x1c: /* INC E */ + INCREG(reg_e, 7, 2); + break; + case 0x1d: /* DEC E */ + DECREG(reg_e, 7, 2); + break; + case 0x1e: /* LD E # */ + LDREG(reg_e, ip2, 4, 5, 3); + break; + case 0x1f: /* RRA */ + RRA(8, 2); + break; + case 0x20: /* JR NZ */ + BRANCH(!LOCAL_ZERO(), ip2, 3); + break; + case 0x21: /* LD IX # */ + LDW(ip23, reg_ixh, reg_ixl, 10, 4, 4); + break; + case 0x22: /* LD (WORD) IX */ + STW(ip23, reg_ixh, reg_ixl, 4, 9, 7, 4); + break; + case 0x23: /* INC IX */ + DECINC(INC_IX_WORD(), 10, 2); + break; + case 0x24: /* INC IXH */ + INCREG(reg_ixh, 7, 2); + break; + case 0x25: /* DEC IXH */ + DECREG(reg_ixh, 7, 2); + break; + case 0x26: /* LD IXH # */ + LDREG(reg_ixh, ip2, 4, 5, 3); + break; + case 0x27: /* DAA */ + DAA(8, 2); + break; + case 0x29: /* ADD IX IX */ + ADDXXREG(reg_ixh, reg_ixl, reg_ixh, reg_ixl, 15, 2); + break; + case 0x28: /* JR Z */ + BRANCH(LOCAL_ZERO(), ip2, 3); + break; + case 0x2a: /* LD IX (WORD) */ + LDIND(ip23, reg_ixh, reg_ixl, 4, 4, 12, 4); + break; + case 0x2b: /* DEC IX */ + DECINC(DEC_IX_WORD(), 10, 2); + break; + case 0x2c: /* INC IXL */ + INCREG(reg_ixl, 7, 2); + break; + case 0x2d: /* DEC IXL */ + DECREG(reg_ixl, 7, 2); + break; + case 0x2e: /* LD IXL # */ + LDREG(reg_ixl, ip2, 4, 5, 3); + break; + case 0x2f: /* CPL */ + CPL(8, 2); + break; + case 0x30: /* JR NC */ + BRANCH(!LOCAL_CARRY(), ip2, 3); + break; + case 0x31: /* LD SP # */ + LDSP(ip23, 10, 0, 4); + break; + case 0x32: /* LD (WORD) A */ + STREG(ip23, reg_a, 10, 7, 4); + break; + case 0x33: /* INC SP */ + DECINC(reg_sp++, 10, 2); + break; + case 0x34: /* INC (IX+d) */ + INCXXIND(IX_WORD_OFF(ip2), 4, 7, 12, 3); + break; + case 0x35: /* DEC (IX+d) */ + DECXXIND(IX_WORD_OFF(ip2), 4, 7, 12, 3); + break; + case 0x36: /* LD (IX+d) # */ + STREG(IX_WORD_OFF(ip2), ip3, 8, 11, 4); + break; + case 0x37: /* SCF */ + SCF(8, 2); + break; + case 0x38: /* JR C */ + BRANCH(LOCAL_CARRY(), ip2, 3); + break; + case 0x39: /* ADD IX SP */ + ADDXXSP(reg_ixh, reg_ixl, 15, 2); + break; + case 0x3a: /* LD A (WORD) */ + LDREG(reg_a, LOAD(ip23), 10, 7, 4); + break; + case 0x3b: /* DEC SP */ + DECINC(reg_sp--, 10, 2); + break; + case 0x3c: /* INC A */ + INCREG(reg_a, 7, 2); + break; + case 0x3d: /* DEC A */ + DECREG(reg_a, 7, 2); + break; + case 0x3e: /* LD A # */ + LDREG(reg_a, ip2, 4, 5, 3); + break; + case 0x3f: /* CCF */ + CCF(8, 2); + break; + case 0x40: /* LD B B */ + LDREG(reg_b, reg_b, 0, 4, 2); + break; + case 0x41: /* LD B C */ + LDREG(reg_b, reg_c, 0, 4, 2); + break; + case 0x42: /* LD B D */ + LDREG(reg_b, reg_d, 0, 4, 2); + break; + case 0x43: /* LD B E */ + LDREG(reg_b, reg_e, 0, 4, 2); + break; + case 0x44: /* LD B IXH */ + LDREG(reg_b, reg_ixh, 0, 4, 2); + break; + case 0x45: /* LD B IXL */ + LDREG(reg_b, reg_ixl, 0, 4, 2); + break; + case 0x46: /* LD B (IX+d) */ + LDREG(reg_b, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x47: /* LD B A */ + LDREG(reg_b, reg_a, 0, 4, 2); + break; + case 0x48: /* LD C B */ + LDREG(reg_c, reg_b, 0, 4, 2); + break; + case 0x49: /* LD C C */ + LDREG(reg_c, reg_c, 0, 4, 2); + break; + case 0x4a: /* LD C D */ + LDREG(reg_c, reg_d, 0, 4, 2); + break; + case 0x4b: /* LD C E */ + LDREG(reg_c, reg_e, 0, 4, 2); + break; + case 0x4c: /* LD C IXH */ + LDREG(reg_c, reg_ixh, 0, 4, 2); + break; + case 0x4d: /* LD C IXL */ + LDREG(reg_c, reg_ixl, 0, 4, 2); + break; + case 0x4e: /* LD C (IX+d) */ + LDREG(reg_c, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x4f: /* LD C A */ + LDREG(reg_c, reg_a, 0, 4, 2); + break; + case 0x50: /* LD D B */ + LDREG(reg_d, reg_b, 0, 4, 2); + break; + case 0x51: /* LD D C */ + LDREG(reg_d, reg_c, 0, 4, 2); + break; + case 0x52: /* LD D D */ + LDREG(reg_d, reg_d, 0, 4, 2); + break; + case 0x53: /* LD D E */ + LDREG(reg_d, reg_e, 0, 4, 2); + break; + case 0x54: /* LD D IXH */ + LDREG(reg_d, reg_ixh, 0, 4, 2); + break; + case 0x55: /* LD D L */ + LDREG(reg_d, reg_ixl, 0, 4, 2); + break; + case 0x56: /* LD D (IX+d) */ + LDREG(reg_d, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x57: /* LD D A */ + LDREG(reg_d, reg_a, 0, 4, 2); + break; + case 0x58: /* LD E B */ + LDREG(reg_e, reg_b, 0, 4, 2); + break; + case 0x59: /* LD E C */ + LDREG(reg_e, reg_c, 0, 4, 2); + break; + case 0x5a: /* LD E D */ + LDREG(reg_e, reg_d, 0, 4, 2); + break; + case 0x5b: /* LD E E */ + LDREG(reg_e, reg_e, 0, 4, 2); + break; + case 0x5c: /* LD E IXH */ + LDREG(reg_e, reg_ixh, 0, 4, 2); + break; + case 0x5d: /* LD E IXL */ + LDREG(reg_e, reg_ixl, 0, 4, 2); + break; + case 0x5e: /* LD E (IX+d) */ + LDREG(reg_e, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x5f: /* LD E A */ + LDREG(reg_e, reg_a, 0, 4, 2); + break; + case 0x60: /* LD IXH B */ + LDREG(reg_ixh, reg_b, 0, 4, 2); + break; + case 0x61: /* LD IXH C */ + LDREG(reg_ixh, reg_c, 0, 4, 2); + break; + case 0x62: /* LD IXH D */ + LDREG(reg_ixh, reg_d, 0, 4, 2); + break; + case 0x63: /* LD IXH E */ + LDREG(reg_ixh, reg_e, 0, 4, 2); + break; + case 0x64: /* LD IXH IXH */ + LDREG(reg_ixh, reg_ixh, 0, 4, 2); + break; + case 0x65: /* LD IXH IXL */ + LDREG(reg_ixh, reg_ixl, 0, 4, 2); + break; + case 0x66: /* LD H (IX+d) */ + LDREG(reg_h, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x67: /* LD IXH A */ + LDREG(reg_ixh, reg_a, 0, 4, 2); + break; + case 0x68: /* LD IXL B */ + LDREG(reg_ixl, reg_b, 0, 4, 2); + break; + case 0x69: /* LD IXL C */ + LDREG(reg_ixl, reg_c, 0, 4, 2); + break; + case 0x6a: /* LD IXL D */ + LDREG(reg_ixl, reg_d, 0, 4, 2); + break; + case 0x6b: /* LD IXL E */ + LDREG(reg_ixl, reg_e, 0, 4, 2); + break; + case 0x6c: /* LD IXL IXH */ + LDREG(reg_ixl, reg_ixh, 0, 4, 2); + break; + case 0x6d: /* LD IXL IXL */ + LDREG(reg_ixl, reg_ixl, 0, 4, 2); + break; + case 0x6e: /* LD L (IX+d) */ + LDREG(reg_l, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x6f: /* LD IXL A */ + LDREG(reg_ixl, reg_a, 0, 4, 2); + break; + case 0x70: /* LD (IX+d) B */ + STREG(IX_WORD_OFF(ip2), reg_b, 8, 11, 3); + break; + case 0x71: /* LD (IX+d) C */ + STREG(IX_WORD_OFF(ip2), reg_c, 8, 11, 3); + break; + case 0x72: /* LD (IX+d) D */ + STREG(IX_WORD_OFF(ip2), reg_d, 8, 11, 3); + break; + case 0x73: /* LD (IX+d) E */ + STREG(IX_WORD_OFF(ip2), reg_e, 8, 11, 3); + break; + case 0x74: /* LD (IX+d) H */ + STREG(IX_WORD_OFF(ip2), reg_h, 8, 11, 3); + break; + case 0x75: /* LD (IX+d) L */ + STREG(IX_WORD_OFF(ip2), reg_l, 8, 11, 3); + break; + case 0x76: /* HALT */ + HALT(); + break; + case 0x77: /* LD (IX+d) A */ + STREG(IX_WORD_OFF(ip2), reg_a, 8, 11, 3); + break; + case 0x78: /* LD A B */ + LDREG(reg_a, reg_b, 0, 4, 2); + break; + case 0x79: /* LD A C */ + LDREG(reg_a, reg_c, 0, 4, 2); + break; + case 0x7a: /* LD A D */ + LDREG(reg_a, reg_d, 0, 4, 2); + break; + case 0x7b: /* LD A E */ + LDREG(reg_a, reg_e, 0, 4, 2); + break; + case 0x7c: /* LD A IXH */ + LDREG(reg_a, reg_ixh, 0, 4, 2); + break; + case 0x7d: /* LD A IXL */ + LDREG(reg_a, reg_ixl, 0, 4, 2); + break; + case 0x7e: /* LD A (IX+d) */ + LDREG(reg_a, LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x7f: /* LD A A */ + LDREG(reg_a, reg_a, 0, 4, 2); + break; + case 0x80: /* ADD B */ + ADD(reg_b, 0, 4, 2); + break; + case 0x81: /* ADD C */ + ADD(reg_c, 0, 4, 2); + break; + case 0x82: /* ADD D */ + ADD(reg_d, 0, 4, 2); + break; + case 0x83: /* ADD E */ + ADD(reg_e, 0, 4, 2); + break; + case 0x84: /* ADD IXH */ + ADD(reg_ixh, 0, 4, 2); + break; + case 0x85: /* ADD IXL */ + ADD(reg_ixl, 0, 4, 2); + break; + case 0x86: /* ADD (IX+d) */ + ADD(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x87: /* ADD A */ + ADD(reg_a, 0, 4, 2); + break; + case 0x88: /* ADC B */ + ADC(reg_b, 0, 4, 2); + break; + case 0x89: /* ADC C */ + ADC(reg_c, 0, 4, 2); + break; + case 0x8a: /* ADC D */ + ADC(reg_d, 0, 4, 2); + break; + case 0x8b: /* ADC E */ + ADC(reg_e, 0, 4, 2); + break; + case 0x8c: /* ADC IXH */ + ADC(reg_ixh, 0, 4, 2); + break; + case 0x8d: /* ADC IXL */ + ADC(reg_ixl, 0, 4, 2); + break; + case 0x8e: /* ADC (IX+d) */ + ADC(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x8f: /* ADC A */ + ADC(reg_a, 0, 4, 2); + break; + case 0x90: /* SUB B */ + SUB(reg_b, 0, 4, 2); + break; + case 0x91: /* SUB C */ + SUB(reg_c, 0, 4, 2); + break; + case 0x92: /* SUB D */ + SUB(reg_d, 0, 4, 2); + break; + case 0x93: /* SUB E */ + SUB(reg_e, 0, 4, 2); + break; + case 0x94: /* SUB IXH */ + SUB(reg_ixh, 0, 4, 2); + break; + case 0x95: /* SUB IXL */ + SUB(reg_ixl, 0, 4, 2); + break; + case 0x96: /* SUB (IX+d) */ + SUB(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x97: /* SUB A */ + SUB(reg_a, 0, 4, 2); + break; + case 0x98: /* SBC B */ + SBC(reg_b, 0, 4, 2); + break; + case 0x99: /* SBC C */ + SBC(reg_c, 0, 4, 2); + break; + case 0x9a: /* SBC D */ + SBC(reg_d, 0, 4, 2); + break; + case 0x9b: /* SBC E */ + SBC(reg_e, 0, 4, 2); + break; + case 0x9c: /* SBC IXH */ + SBC(reg_ixh, 0, 4, 2); + break; + case 0x9d: /* SBC IXL */ + SBC(reg_ixl, 0, 4, 2); + break; + case 0x9e: /* SBC (IX+d) */ + SBC(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x9f: /* SBC A */ + SBC(reg_a, 0, 4, 2); + break; + case 0xa0: /* AND B */ + AND(reg_b, 0, 4, 2); + break; + case 0xa1: /* AND C */ + AND(reg_c, 0, 4, 2); + break; + case 0xa2: /* AND D */ + AND(reg_d, 0, 4, 2); + break; + case 0xa3: /* AND E */ + AND(reg_e, 0, 4, 2); + break; + case 0xa4: /* AND IXH */ + AND(reg_ixh, 0, 4, 2); + break; + case 0xa5: /* AND IXL */ + AND(reg_ixl, 0, 4, 2); + break; + case 0xa6: /* AND (IX+d) */ + AND(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xa7: /* AND A */ + AND(reg_a, 0, 4, 2); + break; + case 0xa8: /* XOR B */ + XOR(reg_b, 0, 4, 2); + break; + case 0xa9: /* XOR C */ + XOR(reg_c, 0, 4, 2); + break; + case 0xaa: /* XOR D */ + XOR(reg_d, 0, 4, 2); + break; + case 0xab: /* XOR E */ + XOR(reg_e, 0, 4, 2); + break; + case 0xac: /* XOR IXH */ + XOR(reg_ixh, 0, 4, 2); + break; + case 0xad: /* XOR IXL */ + XOR(reg_ixl, 0, 4, 2); + break; + case 0xae: /* XOR (IX+d) */ + XOR(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xaf: /* XOR A */ + XOR(reg_a, 0, 4, 2); + break; + case 0xb0: /* OR B */ + OR(reg_b, 0, 4, 2); + break; + case 0xb1: /* OR C */ + OR(reg_c, 0, 4, 2); + break; + case 0xb2: /* OR D */ + OR(reg_d, 0, 4, 2); + break; + case 0xb3: /* OR E */ + OR(reg_e, 0, 4, 2); + break; + case 0xb4: /* OR IXH */ + OR(reg_ixh, 0, 4, 2); + break; + case 0xb5: /* OR IXL */ + OR(reg_ixl, 0, 4, 2); + break; + case 0xb6: /* OR (IX+d) */ + OR(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xb7: /* OR A */ + OR(reg_a, 0, 4, 2); + break; + case 0xb8: /* CP B */ + CP(reg_b, 0, 4, 2); + break; + case 0xb9: /* CP C */ + CP(reg_c, 0, 4, 2); + break; + case 0xba: /* CP D */ + CP(reg_d, 0, 4, 2); + break; + case 0xbb: /* CP E */ + CP(reg_e, 0, 4, 2); + break; + case 0xbc: /* CP IXH */ + CP(reg_ixh, 0, 4, 2); + break; + case 0xbd: /* CP IXL */ + CP(reg_ixl, 0, 4, 2); + break; + case 0xbe: /* CP (IX+d) */ + CP(LOAD(IX_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xbf: /* CP A */ + CP(reg_a, 0, 4, 2); + break; + case 0xc1: /* POP BC */ + POP(reg_b, reg_c, 2); + break; + case 0xc5: /* PUSH BC */ + PUSH(reg_b, reg_c, 2); + break; + case 0xcb: /* OPCODE DD CB */ + opcode_dd_cb((BYTE)ip2, (BYTE)ip3, (WORD)ip23); + break; + case 0xd1: /* POP DE */ + POP(reg_d, reg_e, 2); + break; + case 0xd3: /* OUT A */ + OUTA(ip2, 8, 7, 3); + break; + case 0xd5: /* PUSH DE */ + PUSH(reg_d, reg_e, 2); + break; + case 0xd9: /* EXX */ + EXX(12, 2); + break; + case 0xdb: /* IN A */ + INA(ip2, 8, 7, 3); + break; + case 0xdd: /* Skip DD */ + NOP(4, 1); + break; + case 0xe1: /* POP IX */ + POP(reg_ixh, reg_ixl, 2); + break; + case 0xe3: /* EX IX (SP) */ + EXXXSP(reg_ixh, reg_ixl, 4, 4, 4, 4, 7, 2); + break; + case 0xe5: /* PUSH IX */ + PUSH(reg_ixh, reg_ixl, 2); + break; + case 0xe9: /* LD PC IX */ + JMP((IX_WORD()), 8); + break; + case 0xeb: + EXDEHL(8, 2); + break; + case 0xed: /* Skip DD */ + NOP(4, 1); + break; + case 0xf1: /* POP AF */ + POP(reg_a, reg_f, 2); + break; + case 0xf3: /* DI */ + DI(8, 2); + break; + case 0xf5: /* PUSH AF */ + PUSH(reg_a, reg_f, 2); + break; + case 0xf9: /* LD SP IX */ + LDSP(IX_WORD(), 4, 6, 2); + break; + case 0xfb: /* EI */ + EI(8, 2); + break; + case 0xfd: /* Skip DD */ + NOP(4, 1); + break; + default: +#ifdef DEBUG_Z80 + log_message(LOG_DEFAULT, + "%i PC %04x A%02x F%02x B%02x C%02x D%02x E%02x " + "H%02x L%02x SP%04x OP DD %02x %02x %02x.", + (int)(CLK), (unsigned int)(z80_reg_pc), + reg_a, reg_f, reg_b, reg_c, reg_d, reg_e, + reg_h, reg_l, reg_sp, ip1, ip2, ip3); +#endif + INC_PC(2); + } +} + +static void opcode_ed(BYTE ip1, BYTE ip2, BYTE ip3, WORD ip12, WORD ip23) +{ + switch (ip1) { + case 0x40: /* IN B BC */ + INBC(reg_b, 4, 8, 2); + break; + case 0x41: /* OUT BC B */ + OUTBC(reg_b, 4, 8, 2); + break; + case 0x42: /* SBC HL BC */ + SBCHLREG(reg_b, reg_c); + break; + case 0x43: /* LD (WORD) BC */ + STW(ip23, reg_b, reg_c, 4, 13, 3, 4); + break; + case 0x44: /* NEG */ + NEG(); + break; + case 0x45: /* RETN */ + RETNI(); + break; + case 0x46: /* IM0 */ + IM(0); + break; + case 0x47: /* LD I A */ + LDREG(reg_i, reg_a, 6, 3, 2); + break; + case 0x48: /* IN C BC */ + INBC(reg_c, 4, 8, 2); + break; + case 0x49: /* OUT BC C */ + OUTBC(reg_c, 4, 8, 2); + break; + case 0x4a: /* ADC HL BC */ + ADCHLREG(reg_b, reg_c); + break; + case 0x4b: /* LD BC (WORD) */ + LDIND(ip23, reg_b, reg_c, 4, 4, 12, 4); + break; + case 0x4d: /* RETI */ + RETNI(); + break; + case 0x4f: /* LD R A FIXME: Not emulated. */ + NOP(8, 2); + break; + case 0x50: /* IN D BC */ + INBC(reg_d, 4, 8, 2); + break; + case 0x51: /* OUT BC D */ + OUTBC(reg_d, 4, 8, 2); + break; + case 0x52: /* SBC HL DE */ + SBCHLREG(reg_d, reg_e); + break; + case 0x53: /* LD (WORD) DE */ + STW(ip23, reg_d, reg_e, 4, 13, 3, 4); + break; + case 0x56: /* IM1 */ + IM(1); + break; + case 0x57: /* LD A I */ + LDAIR(reg_i); + break; + case 0x58: /* IN E BC */ + INBC(reg_e, 4, 8, 2); + break; + case 0x59: /* OUT BC E */ + OUTBC(reg_e, 4, 8, 2); + break; + case 0x5a: /* ADC HL DE */ + ADCHLREG(reg_d, reg_e); + break; + case 0x5b: /* LD DE (WORD) */ + LDIND(ip23, reg_d, reg_e, 4, 4, 12, 4); + break; + case 0x5e: /* IM2 */ + IM(2); + break; + case 0x5f: /* LD A R */ + LDAIR((BYTE)(CLK & 0xff)); + break; + case 0x60: /* IN H BC */ + INBC(reg_h, 4, 8, 2); + break; + case 0x61: /* OUT BC H */ + OUTBC(reg_h, 4, 8, 2); + break; + case 0x62: /* SBC HL HL */ + SBCHLREG(reg_h, reg_l); + break; + case 0x63: /* LD (WORD) HL */ + STW(ip23, reg_h, reg_l, 4, 13, 3, 4); + break; + case 0x67: /* RRD */ + RRD(); + break; + case 0x68: /* IN L BC */ + INBC(reg_l, 4, 8, 2); + break; + case 0x69: /* OUT BC L */ + OUTBC(reg_l, 4, 8, 2); + break; + case 0x6a: /* ADC HL HL */ + ADCHLREG(reg_h, reg_l); + break; + case 0x6b: /* LD HL (WORD) */ + LDIND(ip23, reg_h, reg_l, 4, 4, 12, 4); + break; + case 0x6f: /* RLD */ + RLD(); + break; + case 0x70: /* IN F BC */ + INBC0(4, 8, 2); + break; + case 0x71: /* OUT BC #0 */ + OUTBC(0, 4, 8, 2); + break; + case 0x72: /* SBC HL SP */ + SBCHLSP(); + break; + case 0x73: /* LD (WORD) SP */ + STSPW(ip23, 4, 13, 3, 4); + break; + case 0x78: /* IN A BC */ + INBC(reg_a, 4, 8, 2); + break; + case 0x79: /* OUT BC A */ + OUTBC(reg_a, 4, 8, 2); + break; + case 0x7a: /* ADC HL SP */ + ADCHLSP(); + break; + case 0x7b: /* LD SP (WORD) */ + LDSPIND(ip23, 4, 4, 12, 4); + break; + case 0xa0: /* LDI */ + LDDI(INC_DE_WORD(), INC_HL_WORD()); + break; + case 0xa1: /* CPI */ + CPDI(INC_HL_WORD()); + break; + case 0xa2: /* INI */ + INDI(INC_HL_WORD()); + break; + case 0xa3: /* OUTI */ + OUTDI(INC_HL_WORD()); + break; + case 0xa8: /* LDD */ + LDDI(DEC_DE_WORD(), DEC_HL_WORD()); + break; + case 0xa9: /* CPD */ + CPDI(DEC_HL_WORD()); + break; + case 0xaa: /* IND */ + INDI(DEC_HL_WORD()); + break; + case 0xab: /* OUTD */ + OUTDI(DEC_HL_WORD()); + break; + case 0xb0: /* LDIR */ + LDDIR(INC_DE_WORD(), INC_HL_WORD()); + break; + case 0xb1: /* CPIR */ + CPDIR(INC_HL_WORD()); + break; + case 0xb2: /* INIR */ + INDIR(INC_HL_WORD()); + break; + case 0xb3: /* OTIR */ + OTDIR(INC_HL_WORD()); + break; + case 0xb8: /* LDDR */ + LDDIR(DEC_DE_WORD(), DEC_HL_WORD()); + break; + case 0xb9: /* CPDR */ + CPDIR(DEC_HL_WORD()); + break; + case 0xba: /* INDR */ + INDIR(DEC_HL_WORD()); + break; + case 0xbb: /* OTDR */ + OTDIR(DEC_HL_WORD()); + break; + case 0xcb: /* NOP */ + NOP(8, 2); + break; + case 0xdd: /* NOP */ + NOP(8, 2); + break; + case 0xed: /* NOP */ + NOP(8, 2); + break; + case 0xfd: /* NOP */ + NOP(8, 2); + break; + default: +#ifdef DEBUG_Z80 + log_message(LOG_DEFAULT, + "%i PC %04x A%02x F%02x B%02x C%02x D%02x E%02x " + "H%02x L%02x SP%04x OP ED %02x %02x %02x.", + (int)(CLK), (unsigned int)(z80_reg_pc), + reg_a, reg_f, reg_b, reg_c, reg_d, reg_e, + reg_h, reg_l, reg_sp, ip1, ip2, ip3); +#endif + INC_PC(2); + } +} + +static void opcode_fd_cb(BYTE iip2, BYTE iip3, WORD iip23) +{ + switch (iip3) { + case 0x00: /* RLC (IY+d),B */ + RLCXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x01: /* RLC (IY+d),C */ + RLCXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x02: /* RLC (IY+d),D */ + RLCXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x03: /* RLC (IY+d),E */ + RLCXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x04: /* RLC (IY+d),H */ + RLCXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x05: /* RLC (IY+d),L */ + RLCXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x06: /* RLC (IY+d) */ + RLCXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x07: /* RLC (IY+d),A */ + RLCXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x08: /* RRC (IY+d),B */ + RRCXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x09: /* RRC (IY+d),C */ + RRCXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0a: /* RRC (IY+d),D */ + RRCXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0b: /* RRC (IY+d),E */ + RRCXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0c: /* RRC (IY+d),H */ + RRCXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0d: /* RRC (IY+d),L */ + RRCXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0e: /* RRC (IY+d) */ + RRCXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x0f: /* RRC (IY+d),A */ + RRCXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x10: /* RL (IY+d),B */ + RLXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x11: /* RL (IY+d),C */ + RLXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x12: /* RL (IY+d),D */ + RLXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x13: /* RL (IY+d),E */ + RLXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x14: /* RL (IY+d),H */ + RLXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x15: /* RL (IY+d),L */ + RLXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x16: /* RL (IY+d) */ + RLXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x17: /* RL (IY+d),A */ + RLXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x18: /* RR (IY+d),B */ + RRXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x19: /* RR (IY+d),C */ + RRXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1a: /* RR (IY+d),D */ + RRXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1b: /* RR (IY+d),E */ + RRXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1c: /* RR (IY+d),H */ + RRXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1d: /* RR (IY+d),L */ + RRXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1e: /* RR (IY+d) */ + RRXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x1f: /* RR (IY+d),A */ + RRXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x20: /* SLA (IY+d),B */ + SLAXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x21: /* SLA (IY+d),C */ + SLAXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x22: /* SLA (IY+d),D */ + SLAXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x23: /* SLA (IY+d),E */ + SLAXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x24: /* SLA (IY+d),H */ + SLAXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x25: /* SLA (IY+d),L */ + SLAXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x26: /* SLA (IY+d) */ + SLAXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x27: /* SLA (IY+d),A */ + SLAXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x28: /* SRA (IY+d),B */ + SRAXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x29: /* SRA (IY+d),C */ + SRAXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2a: /* SRA (IY+d),D */ + SRAXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2b: /* SRA (IY+d),E */ + SRAXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2c: /* SRA (IY+d),H */ + SRAXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2d: /* SRA (IY+d),L */ + SRAXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2e: /* SRA (IY+d) */ + SRAXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x2f: /* SRA (IY+d),A */ + SRAXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x30: /* SLL (IY+d),B */ + SLLXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x31: /* SLL (IY+d),C */ + SLLXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x32: /* SLL (IY+d),D */ + SLLXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x33: /* SLL (IY+d),E */ + SLLXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x34: /* SLL (IY+d),H */ + SLLXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x35: /* SLL (IY+d),L */ + SLLXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x36: /* SLL (IY+d) */ + SLLXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x37: /* SLL (IY+d),A */ + SLLXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x38: /* SRL (IY+d),B */ + SRLXXREG(reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x39: /* SRL (IY+d),C */ + SRLXXREG(reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3a: /* SRL (IY+d),D */ + SRLXXREG(reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3b: /* SRL (IY+d),E */ + SRLXXREG(reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3c: /* SRL (IY+d),H */ + SRLXXREG(reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3d: /* SRL (IY+d),L */ + SRLXXREG(reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3e: /* SRL (IY+d) */ + SRLXX(IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x3f: /* SRL (IY+d),A */ + SRLXXREG(reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x40: /* BIT (IY+d) 0 */ + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + BIT(LOAD(IY_WORD_OFF(iip2)), 0, 8, 12, 4); + break; + case 0x48: /* BIT (IY+d) 1 */ + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + BIT(LOAD(IY_WORD_OFF(iip2)), 1, 8, 12, 4); + break; + case 0x50: /* BIT (IY+d) 2 */ + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + BIT(LOAD(IY_WORD_OFF(iip2)), 2, 8, 12, 4); + break; + case 0x58: /* BIT (IY+d) 3 */ + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + BIT(LOAD(IY_WORD_OFF(iip2)), 3, 8, 12, 4); + break; + case 0x60: /* BIT (IY+d) 4 */ + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + BIT(LOAD(IY_WORD_OFF(iip2)), 4, 8, 12, 4); + break; + case 0x68: /* BIT (IY+d) 5 */ + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + BIT(LOAD(IY_WORD_OFF(iip2)), 5, 8, 12, 4); + break; + case 0x70: /* BIT (IY+d) 6 */ + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + BIT(LOAD(IY_WORD_OFF(iip2)), 6, 8, 12, 4); + break; + case 0x78: /* BIT (IY+d) 7 */ + case 0x79: + case 0x7a: + case 0x7b: + case 0x7c: + case 0x7d: + case 0x7e: + case 0x7f: + BIT(LOAD(IY_WORD_OFF(iip2)), 7, 8, 12, 4); + break; + case 0x80: /* RES (IY+d),B 0 */ + RESXXREG(0, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x81: /* RES (IY+d),C 0 */ + RESXXREG(0, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x82: /* RES (IY+d),D 0 */ + RESXXREG(0, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x83: /* RES (IY+d),E 0 */ + RESXXREG(0, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x84: /* RES (IY+d),H 0 */ + RESXXREG(0, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x85: /* RES (IY+d),L 0 */ + RESXXREG(0, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x86: /* RES (IY+d) 0 */ + RESXX(0, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x87: /* RES (IY+d),A 0 */ + RESXXREG(0, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x88: /* RES (IY+d),B 1 */ + RESXXREG(1, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x89: /* RES (IY+d),C 1 */ + RESXXREG(1, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8a: /* RES (IY+d),D 1 */ + RESXXREG(1, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8b: /* RES (IY+d),E 1 */ + RESXXREG(1, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8c: /* RES (IY+d),H 1 */ + RESXXREG(1, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8d: /* RES (IY+d),L 1 */ + RESXXREG(1, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8e: /* RES (IY+d) 1 */ + RESXX(1, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x8f: /* RES (IY+d),A 1 */ + RESXXREG(1, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x90: /* RES (IY+d),B 2 */ + RESXXREG(2, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x91: /* RES (IY+d),C 2 */ + RESXXREG(2, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x92: /* RES (IY+d),D 2 */ + RESXXREG(2, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x93: /* RES (IY+d),E 2 */ + RESXXREG(2, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x94: /* RES (IY+d),H 2 */ + RESXXREG(2, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x95: /* RES (IY+d),L 2 */ + RESXXREG(2, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x96: /* RES (IY+d) 2 */ + RESXX(2, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x97: /* RES (IY+d),A 2 */ + RESXXREG(2, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x98: /* RES (IY+d),B 3 */ + RESXXREG(3, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x99: /* RES (IY+d),C 3 */ + RESXXREG(3, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9a: /* RES (IY+d),D 3 */ + RESXXREG(3, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9b: /* RES (IY+d),E 3 */ + RESXXREG(3, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9c: /* RES (IY+d),H 3 */ + RESXXREG(3, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9d: /* RES (IY+d),L 3 */ + RESXXREG(3, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9e: /* RES (IY+d) 3 */ + RESXX(3, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0x9f: /* RES (IY+d),A 3 */ + RESXXREG(3, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa0: /* RES (IY+d),B 4 */ + RESXXREG(4, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa1: /* RES (IY+d),C 4 */ + RESXXREG(4, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa2: /* RES (IY+d),D 4 */ + RESXXREG(4, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa3: /* RES (IY+d),E 4 */ + RESXXREG(4, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa4: /* RES (IY+d),H 4 */ + RESXXREG(4, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa5: /* RES (IY+d),L 4 */ + RESXXREG(4, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa6: /* RES (IY+d) 4 */ + RESXX(4, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa7: /* RES (IY+d),A 4 */ + RESXXREG(4, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa8: /* RES (IY+d),B 5 */ + RESXXREG(5, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xa9: /* RES (IY+d),C 5 */ + RESXXREG(5, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xaa: /* RES (IY+d),D 5 */ + RESXXREG(5, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xab: /* RES (IY+d),E 5 */ + RESXXREG(5, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xac: /* RES (IY+d),H 5 */ + RESXXREG(5, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xad: /* RES (IY+d),L 5 */ + RESXXREG(5, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xae: /* RES (IY+d) 5 */ + RESXX(5, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xaf: /* RES (IY+d),A 5 */ + RESXXREG(5, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb0: /* RES (IY+d),B 6 */ + RESXXREG(6, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb1: /* RES (IY+d),C 6 */ + RESXXREG(6, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb2: /* RES (IY+d),D 6 */ + RESXXREG(6, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb3: /* RES (IY+d),E 6 */ + RESXXREG(6, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb4: /* RES (IY+d),H 6 */ + RESXXREG(6, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb5: /* RES (IY+d),L 6 */ + RESXXREG(6, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb6: /* RES (IY+d) 6 */ + RESXX(6, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb7: /* RES (IY+d),A 6 */ + RESXXREG(6, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb8: /* RES (IY+d),B 7 */ + RESXXREG(7, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xb9: /* RES (IY+d),C 7 */ + RESXXREG(7, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xba: /* RES (IY+d),D 7 */ + RESXXREG(7, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbb: /* RES (IY+d),E 7 */ + RESXXREG(7, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbc: /* RES (IY+d),H 7 */ + RESXXREG(7, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbd: /* RES (IY+d),L 7 */ + RESXXREG(7, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbe: /* RES (IY+d) 7 */ + RESXX(7, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xbf: /* RES (IY+d),A 7 */ + RESXXREG(7, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc0: /* SET (IY+d),B 0 */ + SETXXREG(0, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc1: /* SET (IY+d),C 0 */ + SETXXREG(0, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc2: /* SET (IY+d),D 0 */ + SETXXREG(0, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc3: /* SET (IY+d),E 0 */ + SETXXREG(0, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc4: /* SET (IY+d),H 0 */ + SETXXREG(0, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc5: /* SET (IY+d),L 0 */ + SETXXREG(0, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc6: /* SET (IY+d) 0 */ + SETXX(0, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc7: /* SET (IY+d),A 0 */ + SETXXREG(0, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc8: /* SET (IY+d),B 1 */ + SETXXREG(1, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xc9: /* SET (IY+d),C 1 */ + SETXXREG(1, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xca: /* SET (IY+d),D 1 */ + SETXXREG(1, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcb: /* SET (IY+d),E 1 */ + SETXXREG(1, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcc: /* SET (IY+d),H 1 */ + SETXXREG(1, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcd: /* SET (IY+d),L 1 */ + SETXXREG(1, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xce: /* SET (IY+d) 1 */ + SETXX(1, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xcf: /* SET (IY+d),A 1 */ + SETXXREG(1, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd0: /* SET (IY+d),B 2 */ + SETXXREG(2, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd1: /* SET (IY+d),C 2 */ + SETXXREG(2, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd2: /* SET (IY+d),D 2 */ + SETXXREG(2, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd3: /* SET (IY+d),E 2 */ + SETXXREG(2, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd4: /* SET (IY+d),H 2 */ + SETXXREG(2, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd5: /* SET (IY+d),L 2 */ + SETXXREG(2, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd6: /* SET (IY+d) 2 */ + SETXX(2, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd7: /* SET (IY+d),A 2 */ + SETXXREG(2, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd8: /* SET (IY+d),B 3 */ + SETXXREG(3, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xd9: /* SET (IY+d),C 3 */ + SETXXREG(3, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xda: /* SET (IY+d),D 3 */ + SETXXREG(3, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdb: /* SET (IY+d),E 3 */ + SETXXREG(3, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdc: /* SET (IY+d),H 3 */ + SETXXREG(3, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdd: /* SET (IY+d),L 3 */ + SETXXREG(3, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xde: /* SET (IY+d) 3 */ + SETXX(3, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xdf: /* SET (IY+d),A 3 */ + SETXXREG(3, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe0: /* SET (IY+d),B 4 */ + SETXXREG(4, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe1: /* SET (IY+d),C 4 */ + SETXXREG(4, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe2: /* SET (IY+d),D 4 */ + SETXXREG(4, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe3: /* SET (IY+d),E 4 */ + SETXXREG(4, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe4: /* SET (IY+d),H 4 */ + SETXXREG(4, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe5: /* SET (IY+d),L 4 */ + SETXXREG(4, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe6: /* SET (IY+d) 4 */ + SETXX(4, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe7: /* SET (IY+d),A 4 */ + SETXXREG(4, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe8: /* SET (IY+d),B 5 */ + SETXXREG(5, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xe9: /* SET (IY+d),C 5 */ + SETXXREG(5, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xea: /* SET (IY+d),D 5 */ + SETXXREG(5, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xeb: /* SET (IY+d),E 5 */ + SETXXREG(5, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xec: /* SET (IY+d),H 5 */ + SETXXREG(5, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xed: /* SET (IY+d),L 5 */ + SETXXREG(5, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xee: /* SET (IY+d) 5 */ + SETXX(5, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xef: /* SET (IY+d),A 5 */ + SETXXREG(5, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf0: /* SET (IY+d),B 6 */ + SETXXREG(6, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf1: /* SET (IY+d),C 6 */ + SETXXREG(6, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf2: /* SET (IY+d),D 6 */ + SETXXREG(6, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf3: /* SET (IY+d),E 6 */ + SETXXREG(6, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf4: /* SET (IY+d),H 6 */ + SETXXREG(6, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf5: /* SET (IY+d),L 6 */ + SETXXREG(6, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf6: /* SET (IY+d) 6 */ + SETXX(6, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf7: /* SET (IY+d),A 6 */ + SETXXREG(6, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf8: /* SET (IY+d),B 7 */ + SETXXREG(7, reg_b, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xf9: /* SET (IY+d),C 7 */ + SETXXREG(7, reg_c, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfa: /* SET (IY+d),D 7 */ + SETXXREG(7, reg_d, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfb: /* SET (IY+d),E 7 */ + SETXXREG(7, reg_e, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfc: /* SET (IY+d),H 7 */ + SETXXREG(7, reg_h, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfd: /* SET (IY+d),L 7 */ + SETXXREG(7, reg_l, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xfe: /* SET (IY+d) 7 */ + SETXX(7, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + case 0xff: /* SET (IY+d),A 7 */ + SETXXREG(7, reg_a, IY_WORD_OFF(iip2), 4, 4, 15, 4); + break; + default: + INC_PC(4); + } +} + + +static void opcode_fd(BYTE ip1, BYTE ip2, BYTE ip3, WORD ip12, WORD ip23) +{ + switch (ip1) { + case 0x00: /* NOP */ + NOP(8, 2); + break; + case 0x01: /* LD BC # */ + LDW(ip23, reg_b, reg_c, 10, 0, 4); + break; + case 0x02: /* LD (BC) A */ + STREG(BC_WORD(), reg_a, 8, 3, 2); + break; + case 0x03: /* INC BC */ + DECINC(INC_BC_WORD(), 10, 2); + break; + case 0x04: /* INC B */ + INCREG(reg_b, 7, 2); + break; + case 0x05: /* DEC B */ + DECREG(reg_b, 7, 2); + break; + case 0x06: /* LD B # */ + LDREG(reg_b, ip2, 4, 5, 3); + break; + case 0x07: /* RLCA */ + RLCA(8, 2); + break; + case 0x08: /* EX AF AF' */ + EXAFAF(12, 2); + break; + case 0x09: /* ADD IY BC */ + ADDXXREG(reg_iyh, reg_iyl, reg_b, reg_c, 15, 2); + break; + case 0x0a: /* LD A (BC) */ + LDREG(reg_a, LOAD(BC_WORD()), 8, 3, 2); + break; + case 0x0b: /* DEC BC */ + DECINC(DEC_BC_WORD(), 10, 2); + break; + case 0x0c: /* INC C */ + INCREG(reg_c, 7, 2); + break; + case 0x0d: /* DEC C */ + DECREG(reg_c, 7, 2); + break; + case 0x0e: /* LD C # */ + LDREG(reg_c, ip2, 4, 5, 3); + break; + case 0x0f: /* RRCA */ + RRCA(8, 2); + break; + case 0x10: /* DJNZ */ + DJNZ(ip2, 3); + break; + case 0x11: /* LD DE # */ + LDW(ip23, reg_d, reg_e, 10, 0, 4); + break; + case 0x12: /* LD (DE) A */ + STREG(DE_WORD(), reg_a, 8, 3, 2); + break; + case 0x13: /* INC DE */ + DECINC(INC_DE_WORD(), 10, 2); + break; + case 0x14: /* INC D */ + INCREG(reg_d, 7, 2); + break; + case 0x15: /* DEC D */ + DECREG(reg_d, 7, 2); + break; + case 0x16: /* LD D # */ + LDREG(reg_d, ip2, 4, 5, 3); + break; + case 0x17: /* RLA */ + RLA(8, 2); + break; + case 0x19: /* ADD IY DE */ + ADDXXREG(reg_iyh, reg_iyl, reg_d, reg_e, 15, 2); + break; + case 0x1a: /* LD A (DE) */ + LDREG(reg_a, LOAD(DE_WORD()), 8, 3, 2); + break; + case 0x1b: /* DEC DE */ + DECINC(DEC_DE_WORD(), 10, 2); + break; + case 0x1c: /* INC E */ + INCREG(reg_e, 7, 2); + break; + case 0x1d: /* DEC E */ + DECREG(reg_e, 7, 2); + break; + case 0x1e: /* LD E # */ + LDREG(reg_e, ip2, 4, 5, 3); + break; + case 0x1f: /* RRA */ + RRA(8, 2); + break; + case 0x20: /* JR NZ */ + BRANCH(!LOCAL_ZERO(), ip2, 3); + break; + case 0x21: /* LD IY # */ + LDW(ip23, reg_iyh, reg_iyl, 10, 4, 4); + break; + case 0x22: /* LD (WORD) IY */ + STW(ip23, reg_iyh, reg_iyl, 4, 9, 7, 4); + break; + case 0x23: /* INC IY */ + DECINC(INC_IY_WORD(), 10, 2); + break; + case 0x24: /* INC IYH */ + INCREG(reg_iyh, 7, 2); + break; + case 0x25: /* DEC IYH */ + DECREG(reg_iyh, 7, 2); + break; + case 0x26: /* LD IYH # */ + LDREG(reg_iyh, ip2, 4, 5, 3); + break; + case 0x27: /* DAA */ + DAA(8, 2); + break; + case 0x28: /* JR Z */ + BRANCH(LOCAL_ZERO(), ip2, 3); + break; + case 0x29: /* ADD IY IY */ + ADDXXREG(reg_iyh, reg_iyl, reg_iyh, reg_iyl, 15, 2); + break; + case 0x2a: /* LD IY (WORD) */ + LDIND(ip23, reg_iyh, reg_iyl, 4, 4, 12, 4); + break; + case 0x2b: /* DEC IY */ + DECINC(DEC_IY_WORD(), 10, 2); + break; + case 0x2c: /* INC IYL */ + INCREG(reg_iyl, 7, 2); + break; + case 0x2d: /* DEC IYL */ + DECREG(reg_iyl, 7, 2); + break; + case 0x2e: /* LD IYL # */ + LDREG(reg_iyl, ip2, 4, 5, 3); + break; + case 0x2f: /* CPL */ + CPL(8, 2); + break; + case 0x30: /* JR NC */ + BRANCH(!LOCAL_CARRY(), ip2, 3); + break; + case 0x31: /* LD SP # */ + LDSP(ip23, 10, 0, 4); + break; + case 0x32: /* LD (WORD) A */ + STREG(ip23, reg_a, 10, 7, 4); + break; + case 0x33: /* INC SP */ + DECINC(reg_sp++, 10, 2); + break; + case 0x34: /* INC (IY+d) */ + INCXXIND(IY_WORD_OFF(ip2), 4, 7, 12, 3); + break; + case 0x35: /* DEC (IY+d) */ + DECXXIND(IY_WORD_OFF(ip2), 4, 7, 12, 3); + break; + case 0x36: /* LD (IY+d) # */ + STREG(IY_WORD_OFF(ip2), ip3, 8, 11, 4); + break; + case 0x37: /* SCF */ + SCF(8, 2); + break; + case 0x38: /* JR C */ + BRANCH(LOCAL_CARRY(), ip2, 3); + break; + case 0x39: /* ADD IY SP */ + ADDXXSP(reg_iyh, reg_iyl, 15, 2); + break; + case 0x3a: /* LD A (WORD) */ + LDREG(reg_a, LOAD(ip23), 10, 7, 4); + break; + case 0x3b: /* DEC SP */ + DECINC(reg_sp--, 10, 2); + break; + case 0x3c: /* INC A */ + INCREG(reg_a, 7, 2); + break; + case 0x3d: /* DEC A */ + DECREG(reg_a, 7, 2); + break; + case 0x3e: /* LD A # */ + LDREG(reg_a, ip2, 4, 5, 3); + break; + case 0x3f: /* CCF */ + CCF(8, 2); + break; + case 0x40: /* LD B B */ + LDREG(reg_b, reg_b, 0, 4, 2); + break; + case 0x41: /* LD B C */ + LDREG(reg_b, reg_c, 0, 4, 2); + break; + case 0x42: /* LD B D */ + LDREG(reg_b, reg_d, 0, 4, 2); + break; + case 0x43: /* LD B E */ + LDREG(reg_b, reg_e, 0, 4, 2); + break; + case 0x44: /* LD B IYH */ + LDREG(reg_b, reg_iyh, 0, 4, 2); + break; + case 0x45: /* LD B IYL */ + LDREG(reg_b, reg_iyl, 0, 4, 2); + break; + case 0x46: /* LD B (IY+d) */ + LDREG(reg_b, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x47: /* LD B A */ + LDREG(reg_b, reg_a, 0, 4, 2); + break; + case 0x48: /* LD C B */ + LDREG(reg_c, reg_b, 0, 4, 2); + break; + case 0x49: /* LD C C */ + LDREG(reg_c, reg_c, 0, 4, 2); + break; + case 0x4a: /* LD C D */ + LDREG(reg_c, reg_d, 0, 4, 2); + break; + case 0x4b: /* LD C E */ + LDREG(reg_c, reg_e, 0, 4, 2); + break; + case 0x4c: /* LD C IYH */ + LDREG(reg_c, reg_iyh, 0, 4, 2); + break; + case 0x4d: /* LD C IYL */ + LDREG(reg_c, reg_iyl, 0, 4, 2); + break; + case 0x4e: /* LD C (IY+d) */ + LDREG(reg_c, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x4f: /* LD C A */ + LDREG(reg_c, reg_a, 0, 4, 2); + break; + case 0x50: /* LD D B */ + LDREG(reg_d, reg_b, 0, 4, 2); + break; + case 0x51: /* LD D C */ + LDREG(reg_d, reg_c, 0, 4, 2); + break; + case 0x52: /* LD D D */ + LDREG(reg_d, reg_d, 0, 4, 2); + break; + case 0x53: /* LD D E */ + LDREG(reg_d, reg_e, 0, 4, 2); + break; + case 0x54: /* LD D IYH */ + LDREG(reg_d, reg_iyh, 0, 4, 2); + break; + case 0x55: /* LD D IYL */ + LDREG(reg_d, reg_iyl, 0, 4, 2); + break; + case 0x56: /* LD D (IY+d) */ + LDREG(reg_d, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x57: /* LD D A */ + LDREG(reg_d, reg_a, 0, 4, 2); + break; + case 0x58: /* LD E B */ + LDREG(reg_e, reg_b, 0, 4, 2); + break; + case 0x59: /* LD E C */ + LDREG(reg_e, reg_c, 0, 4, 2); + break; + case 0x5a: /* LD E D */ + LDREG(reg_e, reg_d, 0, 4, 2); + break; + case 0x5b: /* LD E E */ + LDREG(reg_e, reg_e, 0, 4, 2); + break; + case 0x5c: /* LD E IYH */ + LDREG(reg_e, reg_iyh, 0, 4, 2); + break; + case 0x5d: /* LD E IYL */ + LDREG(reg_e, reg_iyl, 0, 4, 2); + break; + case 0x5e: /* LD E (IY+d) */ + LDREG(reg_e, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x5f: /* LD E A */ + LDREG(reg_e, reg_a, 0, 4, 2); + break; + case 0x60: /* LD IYH B */ + LDREG(reg_iyh, reg_b, 0, 4, 2); + break; + case 0x61: /* LD IYH C */ + LDREG(reg_iyh, reg_c, 0, 4, 2); + break; + case 0x62: /* LD IYH D */ + LDREG(reg_iyh, reg_d, 0, 4, 2); + break; + case 0x63: /* LD IYH E */ + LDREG(reg_iyh, reg_e, 0, 4, 2); + break; + case 0x64: /* LD IYH IYH */ + LDREG(reg_iyh, reg_iyh, 0, 4, 2); + break; + case 0x65: /* LD IYH IYL */ + LDREG(reg_iyh, reg_iyl, 0, 4, 2); + break; + case 0x66: /* LD H (IY+d) */ + LDREG(reg_h, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x67: /* LD IYH A */ + LDREG(reg_iyh, reg_a, 0, 4, 2); + break; + case 0x68: /* LD IYL B */ + LDREG(reg_iyl, reg_b, 0, 4, 2); + break; + case 0x69: /* LD IYL C */ + LDREG(reg_iyl, reg_c, 0, 4, 2); + break; + case 0x6a: /* LD IYL D */ + LDREG(reg_iyl, reg_d, 0, 4, 2); + break; + case 0x6b: /* LD IYL E */ + LDREG(reg_iyl, reg_e, 0, 4, 2); + break; + case 0x6c: /* LD IYL IYH */ + LDREG(reg_iyl, reg_iyh, 0, 4, 2); + break; + case 0x6d: /* LD IYL IYL */ + LDREG(reg_iyl, reg_iyl, 0, 4, 2); + break; + case 0x6e: /* LD L (IY+d) */ + LDREG(reg_l, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x6f: /* LD IYL A */ + LDREG(reg_iyl, reg_a, 0, 4, 2); + break; + case 0x70: /* LD (IY+d) B */ + STREG(IY_WORD_OFF(ip2), reg_b, 8, 11, 3); + break; + case 0x71: /* LD (IY+d) C */ + STREG(IY_WORD_OFF(ip2), reg_c, 8, 11, 3); + break; + case 0x72: /* LD (IY+d) D */ + STREG(IY_WORD_OFF(ip2), reg_d, 8, 11, 3); + break; + case 0x73: /* LD (IY+d) E */ + STREG(IY_WORD_OFF(ip2), reg_e, 8, 11, 3); + break; + case 0x74: /* LD (IY+d) H */ + STREG(IY_WORD_OFF(ip2), reg_h, 8, 11, 3); + break; + case 0x75: /* LD (IY+d) L */ + STREG(IY_WORD_OFF(ip2), reg_l, 8, 11, 3); + break; + case 0x76: /* HALT */ + HALT(); + break; + case 0x77: /* LD (IY+d) A */ + STREG(IY_WORD_OFF(ip2), reg_a, 8, 11, 3); + break; + case 0x78: /* LD A B */ + LDREG(reg_a, reg_b, 0, 4, 2); + break; + case 0x79: /* LD A C */ + LDREG(reg_a, reg_c, 0, 4, 2); + break; + case 0x7a: /* LD A D */ + LDREG(reg_a, reg_d, 0, 4, 2); + break; + case 0x7b: /* LD A E */ + LDREG(reg_a, reg_e, 0, 4, 2); + break; + case 0x7c: /* LD A IYH */ + LDREG(reg_a, reg_iyh, 0, 4, 2); + break; + case 0x7d: /* LD A IYL */ + LDREG(reg_a, reg_iyl, 0, 4, 2); + break; + case 0x7e: /* LD A (IY+d) */ + LDREG(reg_a, LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x7f: /* LD A A */ + LDREG(reg_a, reg_a, 0, 4, 2); + break; + case 0x80: /* ADD B */ + ADD(reg_b, 0, 4, 2); + break; + case 0x81: /* ADD C */ + ADD(reg_c, 0, 4, 2); + break; + case 0x82: /* ADD D */ + ADD(reg_d, 0, 4, 2); + break; + case 0x83: /* ADD E */ + ADD(reg_e, 0, 4, 2); + break; + case 0x84: /* ADD IYH */ + ADD(reg_iyh, 0, 4, 2); + break; + case 0x85: /* ADD IYL */ + ADD(reg_iyl, 0, 4, 2); + break; + case 0x86: /* ADD (IY+d) */ + ADD(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x87: /* ADD A */ + ADD(reg_a, 0, 4, 2); + break; + case 0x88: /* ADC B */ + ADC(reg_b, 0, 4, 2); + break; + case 0x89: /* ADC C */ + ADC(reg_c, 0, 4, 2); + break; + case 0x8a: /* ADC D */ + ADC(reg_d, 0, 4, 2); + break; + case 0x8b: /* ADC E */ + ADC(reg_e, 0, 4, 2); + break; + case 0x8c: /* ADC IYH */ + ADC(reg_iyh, 0, 4, 2); + break; + case 0x8d: /* ADC IYL */ + ADC(reg_iyl, 0, 4, 2); + break; + case 0x8e: /* ADC (IY+d) */ + ADC(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x8f: /* ADC A */ + ADC(reg_a, 0, 4, 2); + break; + case 0x90: /* SUB B */ + SUB(reg_b, 0, 4, 2); + break; + case 0x91: /* SUB C */ + SUB(reg_c, 0, 4, 2); + break; + case 0x92: /* SUB D */ + SUB(reg_d, 0, 4, 2); + break; + case 0x93: /* SUB E */ + SUB(reg_e, 0, 4, 2); + break; + case 0x94: /* SUB IYH */ + SUB(reg_iyh, 0, 4, 2); + break; + case 0x95: /* SUB IYL */ + SUB(reg_iyl, 0, 4, 2); + break; + case 0x96: /* SUB (IY+d) */ + SUB(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x97: /* SUB A */ + SUB(reg_a, 0, 4, 2); + break; + case 0x98: /* SBC B */ + SBC(reg_b, 0, 4, 2); + break; + case 0x99: /* SBC C */ + SBC(reg_c, 0, 4, 2); + break; + case 0x9a: /* SBC D */ + SBC(reg_d, 0, 4, 2); + break; + case 0x9b: /* SBC E */ + SBC(reg_e, 0, 4, 2); + break; + case 0x9c: /* SBC IYH */ + SBC(reg_iyh, 0, 4, 2); + break; + case 0x9d: /* SBC IYL */ + SBC(reg_iyl, 0, 4, 2); + break; + case 0x9e: /* SBC (IY+d) */ + SBC(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0x9f: /* SBC A */ + SBC(reg_a, 0, 4, 2); + break; + case 0xa0: /* AND B */ + AND(reg_b, 0, 4, 2); + break; + case 0xa1: /* AND C */ + AND(reg_c, 0, 4, 2); + break; + case 0xa2: /* AND D */ + AND(reg_d, 0, 4, 2); + break; + case 0xa3: /* AND E */ + AND(reg_e, 0, 4, 2); + break; + case 0xa4: /* AND IYH */ + AND(reg_iyh, 0, 4, 2); + break; + case 0xa5: /* AND IYL */ + AND(reg_iyl, 0, 4, 2); + break; + case 0xa6: /* AND (IY+d) */ + AND(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xa7: /* AND A */ + AND(reg_a, 0, 4, 2); + break; + case 0xa8: /* XOR B */ + XOR(reg_b, 0, 4, 2); + break; + case 0xa9: /* XOR C */ + XOR(reg_c, 0, 4, 2); + break; + case 0xaa: /* XOR D */ + XOR(reg_d, 0, 4, 2); + break; + case 0xab: /* XOR E */ + XOR(reg_e, 0, 4, 2); + break; + case 0xac: /* XOR IYH */ + XOR(reg_iyh, 0, 4, 2); + break; + case 0xad: /* XOR IYL */ + XOR(reg_iyl, 0, 4, 2); + break; + case 0xae: /* XOR (IY+d) */ + XOR(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xaf: /* XOR A */ + XOR(reg_a, 0, 4, 2); + break; + case 0xb0: /* OR B */ + OR(reg_b, 0, 4, 2); + break; + case 0xb1: /* OR C */ + OR(reg_c, 0, 4, 2); + break; + case 0xb2: /* OR D */ + OR(reg_d, 0, 4, 2); + break; + case 0xb3: /* OR E */ + OR(reg_e, 0, 4, 2); + break; + case 0xb4: /* OR IYH */ + OR(reg_iyh, 0, 4, 2); + break; + case 0xb5: /* OR IYL */ + OR(reg_iyl, 0, 4, 2); + break; + case 0xb6: /* OR (IY+d) */ + OR(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xb7: /* OR A */ + OR(reg_a, 0, 4, 2); + break; + case 0xb8: /* CP B */ + CP(reg_b, 0, 4, 2); + break; + case 0xb9: /* CP C */ + CP(reg_c, 0, 4, 2); + break; + case 0xba: /* CP D */ + CP(reg_d, 0, 4, 2); + break; + case 0xbb: /* CP E */ + CP(reg_e, 0, 4, 2); + break; + case 0xbc: /* CP IYH */ + CP(reg_iyh, 0, 4, 2); + break; + case 0xbd: /* CP IYL */ + CP(reg_iyl, 0, 4, 2); + break; + case 0xbe: /* CP (IY+d) */ + CP(LOAD(IY_WORD_OFF(ip2)), 8, 11, 3); + break; + case 0xbf: /* CP A */ + CP(reg_a, 0, 4, 2); + break; + case 0xc1: /* POP BC */ + POP(reg_b, reg_c, 2); + break; + case 0xc5: /* PUSH BC */ + PUSH(reg_b, reg_c, 2); + break; + case 0xcb: /* OPCODE FD CB */ + opcode_fd_cb((BYTE)ip2, (BYTE)ip3, (WORD)ip23); + break; + case 0xd1: /* POP DE */ + POP(reg_d, reg_e, 2); + break; + case 0xd3: /* OUT A */ + OUTA(ip2, 8, 7, 3); + break; + case 0xd5: /* PUSH DE */ + PUSH(reg_d, reg_e, 2); + break; + case 0xd9: /* EXX */ + EXX(12, 2); + break; + case 0xdb: /* IN A */ + INA(ip2, 8, 7, 3); + break; + case 0xdd: /* Skip FD */ + NOP(4, 1); + break; + case 0xe1: /* POP IY */ + POP(reg_iyh, reg_iyl, 2); + break; + case 0xe3: /* EX IY (SP) */ + EXXXSP(reg_iyh, reg_iyl, 4, 4, 4, 4, 7, 2); + break; + case 0xe5: /* PUSH IY */ + PUSH(reg_iyh, reg_iyl, 2); + break; + case 0xe9: /* LD PC IY */ + JMP((IY_WORD()), 8); + break; + case 0xeb: + EXDEHL(8, 2); + break; + case 0xed: /* Skip FD */ + NOP(4, 1); + break; + case 0xf1: /* POP AF */ + POP(reg_a, reg_f, 2); + break; + case 0xf3: /* DI */ + DI(8, 2); + break; + case 0xf5: /* PUSH AF */ + PUSH(reg_a, reg_f, 2); + break; + case 0xf9: /* LD SP IY */ + LDSP(IY_WORD(), 4, 6, 2); + break; + case 0xfb: /* EI */ + EI(8, 2); + break; + case 0xfd: /* Skip FD */ + NOP(4, 1); + break; + default: +#ifdef DEBUG_Z80 + log_message(LOG_DEFAULT, + "%i PC %04x A%02x F%02x B%02x C%02x D%02x E%02x " + "H%02x L%02x SP%04x OP FD %02x %02x %02x.", + (int)(CLK), (unsigned int)z80_reg_pc, + reg_a, reg_f, reg_b, reg_c, reg_d, reg_e, + reg_h, reg_l, reg_sp, ip1, ip2, ip3); +#endif + INC_PC(2); + } +} + +/* ------------------------------------------------------------------------- */ + +/* Z80 mainloop. */ + +static const double uZ80ClockMultiplier = CLK_Z80 / CLK_6502; +inline static ULONG ConvertZ80TStatesTo6502Cycles(UINT uTStates) +{ + return (uTStates < 0) ? 0 : (ULONG) ((double)uTStates / uZ80ClockMultiplier); +} + +//void z80_mainloop(interrupt_cpu_status_t *cpu_int_status, +// alarm_context_t *cpu_alarm_context) + +DWORD z80_mainloop(ULONG uTotalCycles, ULONG uExecutedCycles) +{ + opcode_t opcode; + + import_registers(); + + //z80mem_set_bank_pointer(&z80_bank_base, &z80_bank_limit); // [AppleWin-TC] Not used + + //dma_request = 0; // [AppleWin-TC] Not used + + uTotalCycles = (ULONG) ((double)uTotalCycles * uZ80ClockMultiplier); + uExecutedCycles = (ULONG) ((double)uExecutedCycles * uZ80ClockMultiplier); + maincpu_clk = uExecutedCycles; // Must be signed int, as cycles can go -ve + + do { + + // [AppleWin-TC] Z80 IRQs not supported + //while (CLK >= alarm_context_next_pending_clk(cpu_alarm_context)) + // alarm_context_dispatch(cpu_alarm_context, CLK); + + //{ + // enum cpu_int pending_interrupt; + + // pending_interrupt = cpu_int_status->global_pending_int; + // if (pending_interrupt != IK_NONE) { + // DO_INTERRUPT(pending_interrupt); + // while (CLK >= alarm_context_next_pending_clk(cpu_alarm_context)) + // alarm_context_dispatch(cpu_alarm_context, CLK); + // } + //} + + FETCH_OPCODE(opcode); + +#ifdef DEBUG + if (debug.maincpu_traceflg) + log_message(LOG_DEFAULT, + ".%04x %i %-25s A%02x F%02x B%02x C%02x D%02x E%02x " + "H%02x L%02x S%04x", + (unsigned int)z80_reg_pc, /*CLK*/ 0, + mon_disassemble_to_string(e_comp_space, z80_reg_pc, + p0, p1, p2, p3, 1, "z80"), + reg_a, reg_f, reg_b, reg_c, + reg_d, reg_e, reg_h, reg_l, reg_sp); +#endif + + SET_LAST_OPCODE(p0); + + switch (p0) { + case 0x00: /* NOP */ + NOP(4, 1); + break; + case 0x01: /* LD BC # */ + LDW(p12, reg_b, reg_c, 10, 0, 3); + break; + case 0x02: /* LD (BC) A */ + STREG(BC_WORD(), reg_a, 4, 3, 1); + break; + case 0x03: /* INC BC */ + DECINC(INC_BC_WORD(), 6, 1); + break; + case 0x04: /* INC B */ + INCREG(reg_b, 4, 1); + break; + case 0x05: /* DEC B */ + DECREG(reg_b, 4, 1); + break; + case 0x06: /* LD B # */ + LDREG(reg_b, p1, 4, 3, 2); + break; + case 0x07: /* RLCA */ + RLCA(4, 1); + break; + case 0x08: /* EX AF AF' */ + EXAFAF(8, 1); + break; + case 0x09: /* ADD HL BC */ + ADDXXREG(reg_h, reg_l, reg_b, reg_c, 11, 1); + break; + case 0x0a: /* LD A (BC) */ + LDREG(reg_a, LOAD(BC_WORD()), 4, 3, 1); + break; + case 0x0b: /* DEC BC */ + DECINC(DEC_BC_WORD(), 6, 1); + break; + case 0x0c: /* INC C */ + INCREG(reg_c, 4, 1); + break; + case 0x0d: /* DEC C */ + DECREG(reg_c, 4, 1); + break; + case 0x0e: /* LD C # */ + LDREG(reg_c, p1, 4, 3, 2); + break; + case 0x0f: /* RRCA */ + RRCA(4, 1); + break; + case 0x10: /* DJNZ */ + DJNZ(p1, 2); + break; + case 0x11: /* LD DE # */ + LDW(p12, reg_d, reg_e, 10, 0, 3); + break; + case 0x12: /* LD (DE) A */ + STREG(DE_WORD(), reg_a, 4, 3, 1); + break; + case 0x13: /* INC DE */ + DECINC(INC_DE_WORD(), 6, 1); + break; + case 0x14: /* INC D */ + INCREG(reg_d, 4, 1); + break; + case 0x15: /* DEC D */ + DECREG(reg_d, 4, 1); + break; + case 0x16: /* LD D # */ + LDREG(reg_d, p1, 4, 3, 2); + break; + case 0x17: /* RLA */ + RLA(4, 1); + break; + case 0x18: /* JR */ + BRANCH(1, p1, 2); + break; + case 0x19: /* ADD HL DE */ + ADDXXREG(reg_h, reg_l, reg_d, reg_e, 11, 1); + break; + case 0x1a: /* LD A (DE) */ + LDREG(reg_a, LOAD(DE_WORD()), 4, 3, 1); + break; + case 0x1b: /* DEC DE */ + DECINC(DEC_DE_WORD(), 6, 1); + break; + case 0x1c: /* INC E */ + INCREG(reg_e, 4, 1); + break; + case 0x1d: /* DEC E */ + DECREG(reg_e, 4, 1); + break; + case 0x1e: /* LD E # */ + LDREG(reg_e, p1, 4, 3, 2); + break; + case 0x1f: /* RRA */ + RRA(4, 1); + break; + case 0x20: /* JR NZ */ + BRANCH(!LOCAL_ZERO(), p1, 2); + break; + case 0x21: /* LD HL # */ + LDW(p12, reg_h, reg_l, 10, 0, 3); + break; + case 0x22: /* LD (WORD) HL */ + STW(p12, reg_h, reg_l, 4, 9, 3, 3); + break; + case 0x23: /* INC HL */ + DECINC(INC_HL_WORD(), 6, 1); + break; + case 0x24: /* INC H */ + INCREG(reg_h, 4, 1); + break; + case 0x25: /* DEC H */ + DECREG(reg_h, 4, 1); + break; + case 0x26: /* LD H # */ + LDREG(reg_h, p1, 4, 3, 2); + break; + case 0x27: /* DAA */ + DAA(4, 1); + break; + case 0x28: /* JR Z */ + BRANCH(LOCAL_ZERO(), p1, 2); + break; + case 0x29: /* ADD HL HL */ + ADDXXREG(reg_h, reg_l, reg_h, reg_l, 11, 1); + break; + case 0x2a: /* LD HL (WORD) */ + LDIND(p12, reg_h, reg_l, 4, 4, 8, 3); + break; + case 0x2b: /* DEC HL */ + DECINC(DEC_HL_WORD(), 6, 1); + break; + case 0x2c: /* INC L */ + INCREG(reg_l, 4, 1); + break; + case 0x2d: /* DEC L */ + DECREG(reg_l, 4, 1); + break; + case 0x2e: /* LD L # */ + LDREG(reg_l, p1, 4, 3, 2); + break; + case 0x2f: /* CPL */ + CPL(4, 1); + break; + case 0x30: /* JR NC */ + BRANCH(!LOCAL_CARRY(), p1, 2); + break; + case 0x31: /* LD SP # */ + LDSP(p12, 10, 0, 3); + break; + case 0x32: /* LD (WORD) A */ + STREG(p12, reg_a, 10, 3, 3); + break; + case 0x33: /* INC SP */ + DECINC(reg_sp++, 6, 1); + break; + case 0x34: /* INC (HL) */ + INCXXIND(HL_WORD(), 4, 4, 3, 1); + break; + case 0x35: /* DEC (HL) */ + DECXXIND(HL_WORD(), 4, 4, 3, 1); + break; + case 0x36: /* LD (HL) # */ + STREG(HL_WORD(), p1, 8, 2, 2); + break; + case 0x37: /* SCF */ + SCF(4, 1); + break; + case 0x38: /* JR C */ + BRANCH(LOCAL_CARRY(), p1, 2); + break; + case 0x39: /* ADD HL SP */ + ADDXXSP(reg_h, reg_l, 11, 1); + break; + case 0x3a: /* LD A (WORD) */ + LDREG(reg_a, LOAD(p12), 10, 3, 3); + break; + case 0x3b: /* DEC SP */ + DECINC(reg_sp--, 6, 1); + break; + case 0x3c: /* INC A */ + INCREG(reg_a, 4, 1); + break; + case 0x3d: /* DEC A */ + DECREG(reg_a, 4, 1); + break; + case 0x3e: /* LD A # */ + LDREG(reg_a, p1, 4, 3, 2); + break; + case 0x3f: /* CCF */ + CCF(4, 1); + break; + case 0x40: /* LD B B */ + LDREG(reg_b, reg_b, 0, 4, 1); + break; + case 0x41: /* LD B C */ + LDREG(reg_b, reg_c, 0, 4, 1); + break; + case 0x42: /* LD B D */ + LDREG(reg_b, reg_d, 0, 4, 1); + break; + case 0x43: /* LD B E */ + LDREG(reg_b, reg_e, 0, 4, 1); + break; + case 0x44: /* LD B H */ + LDREG(reg_b, reg_h, 0, 4, 1); + break; + case 0x45: /* LD B L */ + LDREG(reg_b, reg_l, 0, 4, 1); + break; + case 0x46: /* LD B (HL) */ + LDREG(reg_b, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x47: /* LD B A */ + LDREG(reg_b, reg_a, 0, 4, 1); + break; + case 0x48: /* LD C B */ + LDREG(reg_c, reg_b, 0, 4, 1); + break; + case 0x49: /* LD C C */ + LDREG(reg_c, reg_c, 0, 4, 1); + break; + case 0x4a: /* LD C D */ + LDREG(reg_c, reg_d, 0, 4, 1); + break; + case 0x4b: /* LD C E */ + LDREG(reg_c, reg_e, 0, 4, 1); + break; + case 0x4c: /* LD C H */ + LDREG(reg_c, reg_h, 0, 4, 1); + break; + case 0x4d: /* LD C L */ + LDREG(reg_c, reg_l, 0, 4, 1); + break; + case 0x4e: /* LD C (HL) */ + LDREG(reg_c, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x4f: /* LD C A */ + LDREG(reg_c, reg_a, 0, 4, 1); + break; + case 0x50: /* LD D B */ + LDREG(reg_d, reg_b, 0, 4, 1); + break; + case 0x51: /* LD D C */ + LDREG(reg_d, reg_c, 0, 4, 1); + break; + case 0x52: /* LD D D */ + LDREG(reg_d, reg_d, 0, 4, 1); + break; + case 0x53: /* LD D E */ + LDREG(reg_d, reg_e, 0, 4, 1); + break; + case 0x54: /* LD D H */ + LDREG(reg_d, reg_h, 0, 4, 1); + break; + case 0x55: /* LD D L */ + LDREG(reg_d, reg_l, 0, 4, 1); + break; + case 0x56: /* LD D (HL) */ + LDREG(reg_d, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x57: /* LD D A */ + LDREG(reg_d, reg_a, 0, 4, 1); + break; + case 0x58: /* LD E B */ + LDREG(reg_e, reg_b, 0, 4, 1); + break; + case 0x59: /* LD E C */ + LDREG(reg_e, reg_c, 0, 4, 1); + break; + case 0x5a: /* LD E D */ + LDREG(reg_e, reg_d, 0, 4, 1); + break; + case 0x5b: /* LD E E */ + LDREG(reg_e, reg_e, 0, 4, 1); + break; + case 0x5c: /* LD E H */ + LDREG(reg_e, reg_h, 0, 4, 1); + break; + case 0x5d: /* LD E L */ + LDREG(reg_e, reg_l, 0, 4, 1); + break; + case 0x5e: /* LD E (HL) */ + LDREG(reg_e, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x5f: /* LD E A */ + LDREG(reg_e, reg_a, 0, 4, 1); + break; + case 0x60: /* LD H B */ + LDREG(reg_h, reg_b, 0, 4, 1); + break; + case 0x61: /* LD H C */ + LDREG(reg_h, reg_c, 0, 4, 1); + break; + case 0x62: /* LD H D */ + LDREG(reg_h, reg_d, 0, 4, 1); + break; + case 0x63: /* LD H E */ + LDREG(reg_h, reg_e, 0, 4, 1); + break; + case 0x64: /* LD H H */ + LDREG(reg_h, reg_h, 0, 4, 1); + break; + case 0x65: /* LD H L */ + LDREG(reg_h, reg_l, 0, 4, 1); + break; + case 0x66: /* LD H (HL) */ + LDREG(reg_h, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x67: /* LD H A */ + LDREG(reg_h, reg_a, 0, 4, 1); + break; + case 0x68: /* LD L B */ + LDREG(reg_l, reg_b, 0, 4, 1); + break; + case 0x69: /* LD L C */ + LDREG(reg_l, reg_c, 0, 4, 1); + break; + case 0x6a: /* LD L D */ + LDREG(reg_l, reg_d, 0, 4, 1); + break; + case 0x6b: /* LD L E */ + LDREG(reg_l, reg_e, 0, 4, 1); + break; + case 0x6c: /* LD L H */ + LDREG(reg_l, reg_h, 0, 4, 1); + break; + case 0x6d: /* LD L L */ + LDREG(reg_l, reg_l, 0, 4, 1); + break; + case 0x6e: /* LD L (HL) */ + LDREG(reg_l, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x6f: /* LD L A */ + LDREG(reg_l, reg_a, 0, 4, 1); + break; + case 0x70: /* LD (HL) B */ + STREG(HL_WORD(), reg_b, 4, 3, 1); + break; + case 0x71: /* LD (HL) C */ + STREG(HL_WORD(), reg_c, 4, 3, 1); + break; + case 0x72: /* LD (HL) D */ + STREG(HL_WORD(), reg_d, 4, 3, 1); + break; + case 0x73: /* LD (HL) E */ + STREG(HL_WORD(), reg_e, 4, 3, 1); + break; + case 0x74: /* LD (HL) H */ + STREG(HL_WORD(), reg_h, 4, 3, 1); + break; + case 0x75: /* LD (HL) L */ + STREG(HL_WORD(), reg_l, 4, 3, 1); + break; + case 0x76: /* HALT */ + HALT(); + break; + case 0x77: /* LD (HL) A */ + STREG(HL_WORD(), reg_a, 4, 3, 1); + break; + case 0x78: /* LD A B */ + LDREG(reg_a, reg_b, 0, 4, 1); + break; + case 0x79: /* LD A C */ + LDREG(reg_a, reg_c, 0, 4, 1); + break; + case 0x7a: /* LD A D */ + LDREG(reg_a, reg_d, 0, 4, 1); + break; + case 0x7b: /* LD A E */ + LDREG(reg_a, reg_e, 0, 4, 1); + break; + case 0x7c: /* LD A H */ + LDREG(reg_a, reg_h, 0, 4, 1); + break; + case 0x7d: /* LD A L */ + LDREG(reg_a, reg_l, 0, 4, 1); + break; + case 0x7e: /* LD A (HL) */ + LDREG(reg_a, LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x7f: /* LD A A */ + LDREG(reg_a, reg_a, 0, 4, 1); + break; + case 0x80: /* ADD B */ + ADD(reg_b, 0, 4, 1); + break; + case 0x81: /* ADD C */ + ADD(reg_c, 0, 4, 1); + break; + case 0x82: /* ADD D */ + ADD(reg_d, 0, 4, 1); + break; + case 0x83: /* ADD E */ + ADD(reg_e, 0, 4, 1); + break; + case 0x84: /* ADD H */ + ADD(reg_h, 0, 4, 1); + break; + case 0x85: /* ADD L */ + ADD(reg_l, 0, 4, 1); + break; + case 0x86: /* ADD (HL) */ + ADD(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x87: /* ADD A */ + ADD(reg_a, 0, 4, 1); + break; + case 0x88: /* ADC B */ + ADC(reg_b, 0, 4, 1); + break; + case 0x89: /* ADC C */ + ADC(reg_c, 0, 4, 1); + break; + case 0x8a: /* ADC D */ + ADC(reg_d, 0, 4, 1); + break; + case 0x8b: /* ADC E */ + ADC(reg_e, 0, 4, 1); + break; + case 0x8c: /* ADC H */ + ADC(reg_h, 0, 4, 1); + break; + case 0x8d: /* ADC L */ + ADC(reg_l, 0, 4, 1); + break; + case 0x8e: /* ADC (HL) */ + ADC(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x8f: /* ADC A */ + ADC(reg_a, 0, 4, 1); + break; + case 0x90: /* SUB B */ + SUB(reg_b, 0, 4, 1); + break; + case 0x91: /* SUB C */ + SUB(reg_c, 0, 4, 1); + break; + case 0x92: /* SUB D */ + SUB(reg_d, 0, 4, 1); + break; + case 0x93: /* SUB E */ + SUB(reg_e, 0, 4, 1); + break; + case 0x94: /* SUB H */ + SUB(reg_h, 0, 4, 1); + break; + case 0x95: /* SUB L */ + SUB(reg_l, 0, 4, 1); + break; + case 0x96: /* SUB (HL) */ + SUB(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x97: /* SUB A */ + SUB(reg_a, 0, 4, 1); + break; + case 0x98: /* SBC B */ + SBC(reg_b, 0, 4, 1); + break; + case 0x99: /* SBC C */ + SBC(reg_c, 0, 4, 1); + break; + case 0x9a: /* SBC D */ + SBC(reg_d, 0, 4, 1); + break; + case 0x9b: /* SBC E */ + SBC(reg_e, 0, 4, 1); + break; + case 0x9c: /* SBC H */ + SBC(reg_h, 0, 4, 1); + break; + case 0x9d: /* SBC L */ + SBC(reg_l, 0, 4, 1); + break; + case 0x9e: /* SBC (HL) */ + SBC(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0x9f: /* SBC A */ + SBC(reg_a, 0, 4, 1); + break; + case 0xa0: /* AND B */ + AND(reg_b, 0, 4, 1); + break; + case 0xa1: /* AND C */ + AND(reg_c, 0, 4, 1); + break; + case 0xa2: /* AND D */ + AND(reg_d, 0, 4, 1); + break; + case 0xa3: /* AND E */ + AND(reg_e, 0, 4, 1); + break; + case 0xa4: /* AND H */ + AND(reg_h, 0, 4, 1); + break; + case 0xa5: /* AND L */ + AND(reg_l, 0, 4, 1); + break; + case 0xa6: /* AND (HL) */ + AND(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0xa7: /* AND A */ + AND(reg_a, 0, 4, 1); + break; + case 0xa8: /* XOR B */ + XOR(reg_b, 0, 4, 1); + break; + case 0xa9: /* XOR C */ + XOR(reg_c, 0, 4, 1); + break; + case 0xaa: /* XOR D */ + XOR(reg_d, 0, 4, 1); + break; + case 0xab: /* XOR E */ + XOR(reg_e, 0, 4, 1); + break; + case 0xac: /* XOR H */ + XOR(reg_h, 0, 4, 1); + break; + case 0xad: /* XOR L */ + XOR(reg_l, 0, 4, 1); + break; + case 0xae: /* XOR (HL) */ + XOR(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0xaf: /* XOR A */ + XOR(reg_a, 0, 4, 1); + break; + case 0xb0: /* OR B */ + OR(reg_b, 0, 4, 1); + break; + case 0xb1: /* OR C */ + OR(reg_c, 0, 4, 1); + break; + case 0xb2: /* OR D */ + OR(reg_d, 0, 4, 1); + break; + case 0xb3: /* OR E */ + OR(reg_e, 0, 4, 1); + break; + case 0xb4: /* OR H */ + OR(reg_h, 0, 4, 1); + break; + case 0xb5: /* OR L */ + OR(reg_l, 0, 4, 1); + break; + case 0xb6: /* OR (HL) */ + OR(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0xb7: /* OR A */ + OR(reg_a, 0, 4, 1); + break; + case 0xb8: /* CP B */ + CP(reg_b, 0, 4, 1); + break; + case 0xb9: /* CP C */ + CP(reg_c, 0, 4, 1); + break; + case 0xba: /* CP D */ + CP(reg_d, 0, 4, 1); + break; + case 0xbb: /* CP E */ + CP(reg_e, 0, 4, 1); + break; + case 0xbc: /* CP H */ + CP(reg_h, 0, 4, 1); + break; + case 0xbd: /* CP L */ + CP(reg_l, 0, 4, 1); + break; + case 0xbe: /* CP (HL) */ + CP(LOAD(HL_WORD()), 4, 3, 1); + break; + case 0xbf: /* CP A */ + CP(reg_a, 0, 4, 1); + break; + case 0xc0: /* RET NZ */ + RET_COND(!LOCAL_ZERO(), 4, 4, 2, 5, 1); + break; + case 0xc1: /* POP BC */ + POP(reg_b, reg_c, 1); + break; + case 0xc2: /* JP NZ */ + JMP_COND(p12, !LOCAL_ZERO(), 10, 10); + break; + case 0xc3: /* JP */ + JMP(p12, 10); + break; + case 0xc4: /* CALL NZ */ + CALL_COND(p12, !LOCAL_ZERO(), 3, 3, 4, 10, 3); + break; + case 0xc5: /* PUSH BC */ + PUSH(reg_b, reg_c, 1); + break; + case 0xc6: /* ADD # */ + ADD(p1, 4, 3, 2); + break; + case 0xc7: /* RST 00 */ + CALL(0x00, 3, 3, 5, 1); + break; + case 0xc8: /* RET Z */ + RET_COND(LOCAL_ZERO(), 4, 4, 2, 5, 1); + break; + case 0xc9: /* RET */ + RET(4, 4, 2); + break; + case 0xca: /* JP Z */ + JMP_COND(p12, LOCAL_ZERO(), 10, 10); + break; + case 0xcb: /* OPCODE CB */ + opcode_cb((BYTE)p1, (BYTE)p2, (BYTE)p3, (WORD)p12, (WORD)p23); + break; + case 0xcc: /* CALL Z */ + CALL_COND(p12, LOCAL_ZERO(), 3, 3, 4, 10, 3); + break; + case 0xcd: /* CALL */ + CALL(p12, 3, 3, 11, 3); + break; + case 0xce: /* ADC # */ + ADC(p1, 4, 3, 2); + break; + case 0xcf: /* RST 08 */ + CALL(0x08, 3, 3, 5, 1); + break; + case 0xd0: /* RET NC */ + RET_COND(!LOCAL_CARRY(), 4, 4, 2, 5, 1); + break; + case 0xd1: /* POP DE */ + POP(reg_d, reg_e, 1); + break; + case 0xd2: /* JP NC */ + JMP_COND(p12, !LOCAL_CARRY(), 10, 10); + break; + case 0xd3: /* OUT A */ + OUTA(p1, 4, 7, 2); + break; + case 0xd4: /* CALL NC */ + CALL_COND(p12, !LOCAL_CARRY(), 3, 3, 4, 10, 3); + break; + case 0xd5: /* PUSH DE */ + PUSH(reg_d, reg_e, 1); + break; + case 0xd6: /* SUB # */ + SUB(p1, 4, 3, 2); + break; + case 0xd7: /* RST 10 */ + CALL(0x10, 3, 3, 5, 1); + break; + case 0xd8: /* RET C */ + RET_COND(LOCAL_CARRY(), 4, 4, 2, 5, 1); + break; + case 0xd9: /* EXX */ + EXX(8, 1); + break; + case 0xda: /* JP C */ + JMP_COND(p12, LOCAL_CARRY(), 10, 10); + break; + case 0xdb: /* IN A */ + INA(p1, 4, 7, 2); + break; + case 0xdc: /* CALL C */ + CALL_COND(p12, LOCAL_CARRY(), 3, 3, 4, 10, 3); + break; + case 0xdd: /* OPCODE DD */ + opcode_dd((BYTE)p1, (BYTE)p2, (BYTE)p3, (WORD)p12, (WORD)p23); + break; + case 0xde: /* SBC # */ + SBC(p1, 4, 3, 2); + break; + case 0xdf: /* RST 18 */ + CALL(0x18, 3, 3, 5, 1); + break; + case 0xe0: /* RET PO */ + RET_COND(!LOCAL_PARITY(), 4, 4, 2, 5, 1); + break; + case 0xe1: /* POP HL */ + POP(reg_h, reg_l, 1); + break; + case 0xe2: /* JP PO */ + JMP_COND(p12, !LOCAL_PARITY(), 10, 10); + break; + case 0xe3: /* EX HL (SP) */ + EXXXSP(reg_h, reg_l, 4, 4, 4, 4, 3, 1); + break; + case 0xe4: /* CALL PO */ + CALL_COND(p12, !LOCAL_PARITY(), 3, 3, 4, 10, 3); + break; + case 0xe5: /* PUSH HL */ + PUSH(reg_h, reg_l, 1); + break; + case 0xe6: /* AND # */ + AND(p1, 4, 3, 2); + break; + case 0xe7: /* RST 20 */ + CALL(0x20, 3, 3, 5, 1); + break; + case 0xe8: /* RET PE */ + RET_COND(LOCAL_PARITY(), 4, 4, 2, 5, 1); + break; + case 0xe9: /* LD PC HL */ + JMP((HL_WORD()), 4); + break; + case 0xea: /* JP PE */ + JMP_COND(p12, LOCAL_PARITY(), 10, 10); + break; + case 0xeb: /* EX DE HL */ + EXDEHL(4, 1); + break; + case 0xec: /* CALL PE */ + CALL_COND(p12, LOCAL_PARITY(), 3, 3, 4, 10, 3); + break; + case 0xed: /* OPCODE ED */ + opcode_ed((BYTE)p1, (BYTE)p2, (BYTE)p3, (WORD)p12, (WORD)p23); + break; + case 0xee: /* XOR # */ + XOR(p1, 4, 3, 2); + break; + case 0xef: /* RST 28 */ + CALL(0x28, 3, 3, 5, 1); + break; + case 0xf0: /* RET P */ + RET_COND(!LOCAL_SIGN(), 4, 4, 2, 5, 1); + break; + case 0xf1: /* POP AF */ + POP(reg_a, reg_f, 1); + break; + case 0xf2: /* JP P */ + JMP_COND(p12, !LOCAL_SIGN(), 10, 10); + break; + case 0xf3: /* DI */ + DI(4, 1); + break; + case 0xf4: /* CALL P */ + CALL_COND(p12, !LOCAL_SIGN(), 3, 3, 4, 10, 3); + break; + case 0xf5: /* PUSH AF */ + PUSH(reg_a, reg_f, 1); + break; + case 0xf6: /* OR # */ + OR(p1, 4, 3, 2); + break; + case 0xf7: /* RST 30 */ + CALL(0x30, 3, 3, 5, 1); + break; + case 0xf8: /* RET M */ + RET_COND(LOCAL_SIGN(), 4, 4, 2, 5, 1); + break; + case 0xf9: /* LD SP HL */ + LDSP(HL_WORD(), 4, 2, 1); + break; + case 0xfa: /* JP M */ + JMP_COND(p12, LOCAL_SIGN(), 10, 10); + break; + case 0xfb: /* EI */ + EI(4, 1); + break; + case 0xfc: /* CALL M */ + CALL_COND(p12, LOCAL_SIGN(), 3, 3, 4, 10, 3); + break; + case 0xfd: /* OPCODE FD */ + opcode_fd((BYTE)p1, (BYTE)p2, (BYTE)p3, (WORD)p12, (WORD)p23); + break; + case 0xfe: /* CP # */ + CP(p1, 4, 3, 2); + break; + case 0xff: /* RST 38 */ + CALL(0x38, 3, 3, 5, 1); + break; + } + + //cpu_int_status->num_dma_per_opcode = 0; // [AppleWin-TC] Not used + + if (g_ActiveCPU != CPU_Z80) // [AppleWin-TC] + break; + + //} while (!dma_request); + } while (maincpu_clk < uTotalCycles); // [AppleWin-TC] + + export_registers(); + + return ConvertZ80TStatesTo6502Cycles(maincpu_clk - uExecutedCycles); +} + +/****************************************************************************/ +/* Read a byte from given memory location */ +/****************************************************************************/ +BYTE z80_RDMEM(WORD Addr) +{ + WORD addr; + + switch (Addr / 0x1000) + { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + case 0xA: + addr = (WORD)Addr + 0x1000; + return CpuRead( addr, ConvertZ80TStatesTo6502Cycles(maincpu_clk) ); + break; + + case 0xB: + case 0xC: + case 0xD: + addr = (WORD)Addr + 0x2000; + return CpuRead( addr, ConvertZ80TStatesTo6502Cycles(maincpu_clk) ); + break; + + case 0xE: + addr = (WORD)Addr - 0x2000; + if ((addr & 0xF000) == 0xC000) + { + return IORead[(addr>>4) & 0xFF]( regs.pc, addr, 0, 0, ConvertZ80TStatesTo6502Cycles(maincpu_clk) ); + } + else + { + return *(mem+addr); + } + break; + + case 0xF: + addr = (WORD)Addr - 0xF000; + return CpuRead( addr, ConvertZ80TStatesTo6502Cycles(maincpu_clk) ); + break; + } + return 255; +} + +/****************************************************************************/ +/* Write a byte to given memory location */ +/****************************************************************************/ +void z80_WRMEM(WORD Addr, BYTE Value) +{ + unsigned int laddr; + WORD addr; + + laddr = Addr & 0x0FFF; + switch (Addr & 0xF000) + { + case 0x0000: addr = laddr+0x1000; break; + case 0x1000: addr = laddr+0x2000; break; + case 0x2000: addr = laddr+0x3000; break; + case 0x3000: addr = laddr+0x4000; break; + case 0x4000: addr = laddr+0x5000; break; + case 0x5000: addr = laddr+0x6000; break; + case 0x6000: addr = laddr+0x7000; break; + case 0x7000: addr = laddr+0x8000; break; + case 0x8000: addr = laddr+0x9000; break; + case 0x9000: addr = laddr+0xA000; break; + case 0xA000: addr = laddr+0xB000; break; + case 0xB000: addr = laddr+0xD000; break; + case 0xC000: addr = laddr+0xE000; break; + case 0xD000: addr = laddr+0xF000; break; + case 0xE000: addr = laddr+0xC000; break; + case 0xF000: addr = laddr+0x0000; break; + } + CpuWrite( addr, Value, ConvertZ80TStatesTo6502Cycles(maincpu_clk) ); +} diff --git a/AppleWin/source/Z80VICE/z80.h b/AppleWin/source/Z80VICE/z80.h new file mode 100644 index 00000000..4bb01fa6 --- /dev/null +++ b/AppleWin/source/Z80VICE/z80.h @@ -0,0 +1,47 @@ +/* + * z80.h + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _Z80_H +#define _Z80_H + +struct z80_regs_s; + +extern struct z80_regs_s z80_regs; + +//struct interrupt_cpu_status_s; +//struct alarm_context_s; + +extern void z80_reset(void); +//extern void z80_mainloop(struct interrupt_cpu_status_s *cpu_int_status, +// struct alarm_context_s *cpu_alarm_context); +DWORD z80_mainloop(ULONG uTotalCycles, ULONG uExecutedCycles); +//extern void z80_trigger_dma(void); + +BYTE z80_RDMEM(WORD Addr); +void z80_WRMEM(WORD Addr, BYTE Value); + +#endif + diff --git a/AppleWin/source/Z80VICE/z80mem.cpp b/AppleWin/source/Z80VICE/z80mem.cpp new file mode 100644 index 00000000..d9e21d1b --- /dev/null +++ b/AppleWin/source/Z80VICE/z80mem.cpp @@ -0,0 +1,452 @@ +/* + * z80mem.c + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +//#include "vice.h" + +#include +#include + +//#include "c128mem.h" // [AppleWin-TC] +//#include "c128mmu.h" +//#include "c64cia.h" +//#include "c64io.h" +//#include "cmdline.h" +//#include "log.h" +//#include "mem.h" +//#include "resources.h" +//#include "sid.h" +//#include "sysfile.h" +//#include "types.h" +//#include "vdc-mem.h" +//#include "vdc.h" +//#include "vicii-mem.h" +//#include "vicii.h" +#include "..\CommonVICE\types.h" // [AppleWin-TC] +#include "z80mem.h" +#include "z80.h" // [AppleWin-TC] Added for z80_RDMEM() & z80_WRMEM + + +/* Z80 boot BIOS. */ +BYTE z80bios_rom[0x1000]; + +/* Logging. */ +//static log_t z80mem_log = LOG_ERR; // [AppleWin-TC] + +/* Adjust this pointer when the MMU changes banks. */ +static BYTE **bank_base; +static int *bank_limit = NULL; +unsigned int z80_old_reg_pc; + +/* Pointers to the currently used memory read and write tables. */ +read_func_ptr_t *_z80mem_read_tab_ptr; +store_func_ptr_t *_z80mem_write_tab_ptr; +BYTE **_z80mem_read_base_tab_ptr; +int *z80mem_read_limit_tab_ptr; + +#define NUM_CONFIGS 8 + +/* Memory read and write tables. */ +static store_func_ptr_t mem_write_tab[NUM_CONFIGS][0x101]; +static read_func_ptr_t mem_read_tab[NUM_CONFIGS][0x101]; +static BYTE *mem_read_base_tab[NUM_CONFIGS][0x101]; +static int mem_read_limit_tab[NUM_CONFIGS][0x101]; + +store_func_ptr_t io_write_tab[0x101]; +read_func_ptr_t io_read_tab[0x101]; + +//static const resource_int_t resources_int[] = { // [AppleWin-TC] +// { NULL } +//}; +// +//int z80mem_resources_init(void) +//{ +// return resources_register_int(resources_int); +//} +// +//static const cmdline_option_t cmdline_options[] = +//{ +// { NULL } +//}; +// +//int z80mem_cmdline_options_init(void) +//{ +// return cmdline_register_options(cmdline_options); +//} + +/* ------------------------------------------------------------------------- */ + +/* Generic memory access. */ +#if 0 +static void REGPARM2 z80mem_store(WORD addr, BYTE value) +{ + _z80mem_write_tab_ptr[addr >> 8](addr, value); +} + +static BYTE REGPARM1 z80mem_read(WORD addr) +{ + return _z80mem_read_tab_ptr[addr >> 8](addr); +} +#endif + +BYTE REGPARM1 bios_read(WORD addr) +{ + return z80bios_rom[addr & 0x0fff]; +} + +void REGPARM2 bios_store(WORD addr, BYTE value) +{ + z80bios_rom[addr] = value; +} + +//static BYTE REGPARM1 z80_read_zero(WORD addr) // [AppleWin-TC] +//{ +// return mem_page_zero[addr]; +//} +// +//static void REGPARM2 z80_store_zero(WORD addr, BYTE value) +//{ +// mem_page_zero[addr] = value; +//} + +static BYTE REGPARM1 read_unconnected_io(WORD addr) +{ +// log_message(z80mem_log, "Read from unconnected IO %04x", addr); // [AppleWin-TC] + return 0; +} + +static void REGPARM2 store_unconnected_io(WORD addr, BYTE value) +{ +// log_message(z80mem_log, "Store to unconnected IO %04x %02x", addr, value); // [AppleWin-TC] +} + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + +void z80mem_initialize(void) +{ + int i, j; + + /* Memory addess space. */ + + for (j = 0; j < NUM_CONFIGS; j++) { + for (i = 0; i <= 0x100; i++) { + mem_read_base_tab[j][i] = NULL; + mem_read_limit_tab[j][i] = -1; + + mem_read_tab[j][i] = z80_RDMEM; // [AppleWin-TC] + mem_write_tab[j][i] = z80_WRMEM; // [AppleWin-TC] + } + } + + _z80mem_read_tab_ptr = mem_read_tab[0]; + _z80mem_write_tab_ptr = mem_write_tab[0]; + _z80mem_read_base_tab_ptr = mem_read_base_tab[0]; + z80mem_read_limit_tab_ptr = mem_read_limit_tab[0]; + + /* IO address space. */ + + /* At least we know what happens. */ + for (i = 0; i <= 0x100; i++) { + io_read_tab[i] = read_unconnected_io; + io_write_tab[i] = store_unconnected_io; + } + +#if 0 // [AppleWin-TC] + int i, j; + + /* Memory addess space. */ + + for (j = 0; j < NUM_CONFIGS; j++) { + for (i = 0; i <= 0x100; i++) { + mem_read_base_tab[j][i] = NULL; + mem_read_limit_tab[j][i] = -1; + } + } + + mem_read_tab[0][0] = bios_read; + mem_write_tab[0][0] = z80_store_zero; + mem_read_tab[1][0] = bios_read; + mem_write_tab[1][0] = z80_store_zero; + mem_read_tab[2][0] = z80_read_zero; + mem_write_tab[2][0] = z80_store_zero; + mem_read_tab[3][0] = z80_read_zero; + mem_write_tab[3][0] = z80_store_zero; + mem_read_tab[4][0] = z80_read_zero; + mem_write_tab[4][0] = z80_store_zero; + mem_read_tab[5][0] = z80_read_zero; + mem_write_tab[5][0] = z80_store_zero; + mem_read_tab[6][0] = z80_read_zero; + mem_write_tab[6][0] = z80_store_zero; + mem_read_tab[7][0] = z80_read_zero; + mem_write_tab[7][0] = z80_store_zero; + + mem_read_tab[0][1] = bios_read; + mem_write_tab[0][1] = one_store; + mem_read_tab[1][1] = bios_read; + mem_write_tab[1][1] = one_store; + mem_read_tab[2][1] = one_read; + mem_write_tab[2][1] = one_store; + mem_read_tab[3][1] = one_read; + mem_write_tab[3][1] = one_store; + mem_read_tab[4][1] = one_read; + mem_write_tab[4][1] = one_store; + mem_read_tab[5][1] = one_read; + mem_write_tab[5][1] = one_store; + mem_read_tab[6][1] = one_read; + mem_write_tab[6][1] = one_store; + mem_read_tab[7][1] = one_read; + mem_write_tab[7][1] = one_store; + + for (i = 2; i < 0x10; i++) { + mem_read_tab[0][i] = bios_read; + mem_write_tab[0][i] = ram_store; + mem_read_tab[1][i] = bios_read; + mem_write_tab[1][i] = ram_store; + mem_read_tab[2][i] = lo_read; + mem_write_tab[2][i] = lo_store; + mem_read_tab[3][i] = lo_read; + mem_write_tab[3][i] = lo_store; + mem_read_tab[4][i] = ram_read; + mem_write_tab[4][i] = ram_store; + mem_read_tab[5][i] = ram_read; + mem_write_tab[5][i] = ram_store; + mem_read_tab[6][i] = lo_read; + mem_write_tab[6][i] = lo_store; + mem_read_tab[7][i] = lo_read; + mem_write_tab[7][i] = lo_store; + } + + for (i = 0x10; i <= 0x13; i++) { + mem_read_tab[0][i] = ram_read; + mem_write_tab[0][i] = ram_store; + mem_read_tab[1][i] = colorram_read; + mem_write_tab[1][i] = colorram_store; + mem_read_tab[2][i] = lo_read; + mem_write_tab[2][i] = lo_store; + mem_read_tab[3][i] = colorram_read; + mem_write_tab[3][i] = colorram_store; + mem_read_tab[4][i] = ram_read; + mem_write_tab[4][i] = ram_store; + mem_read_tab[5][i] = colorram_read; + mem_write_tab[5][i] = colorram_store; + mem_read_tab[6][i] = lo_read; + mem_write_tab[6][i] = lo_store; + mem_read_tab[7][i] = colorram_read; + mem_write_tab[7][i] = colorram_store; + } + + for (i = 0x14; i <= 0x3f; i++) { + mem_read_tab[0][i] = ram_read; + mem_write_tab[0][i] = ram_store; + mem_read_tab[1][i] = ram_read; + mem_write_tab[1][i] = ram_store; + mem_read_tab[2][i] = lo_read; + mem_write_tab[2][i] = lo_store; + mem_read_tab[3][i] = lo_read; + mem_write_tab[3][i] = lo_store; + mem_read_tab[4][i] = ram_read; + mem_write_tab[4][i] = ram_store; + mem_read_tab[5][i] = ram_read; + mem_write_tab[5][i] = ram_store; + mem_read_tab[6][i] = lo_read; + mem_write_tab[6][i] = lo_store; + mem_read_tab[7][i] = lo_read; + mem_write_tab[7][i] = lo_store; + } + + for (j = 0; j < NUM_CONFIGS; j++) { + for (i = 0x40; i <= 0xbf; i++) { + mem_read_tab[j][i] = ram_read; + mem_write_tab[j][i] = ram_store; + } + } + + for (i = 0xc0; i <= 0xcf; i++) { + mem_read_tab[0][i] = ram_read; + mem_write_tab[0][i] = ram_store; + mem_read_tab[1][i] = ram_read; + mem_write_tab[1][i] = ram_store; + mem_read_tab[2][i] = top_shared_read; + mem_write_tab[2][i] = top_shared_store; + mem_read_tab[3][i] = top_shared_read; + mem_write_tab[3][i] = top_shared_store; + mem_read_tab[4][i] = ram_read; + mem_write_tab[4][i] = ram_store; + mem_read_tab[5][i] = ram_read; + mem_write_tab[5][i] = ram_store; + mem_read_tab[6][i] = top_shared_read; + mem_write_tab[6][i] = top_shared_store; + mem_read_tab[7][i] = top_shared_read; + mem_write_tab[7][i] = top_shared_store; + } + + for (i = 0xd0; i <= 0xdf; i++) { + mem_read_tab[0][i] = ram_read; + mem_write_tab[0][i] = ram_store; + mem_read_tab[1][i] = ram_read; + mem_write_tab[1][i] = ram_store; + mem_read_tab[2][i] = top_shared_read; + mem_write_tab[2][i] = top_shared_store; + mem_read_tab[3][i] = top_shared_read; + mem_write_tab[3][i] = top_shared_store; + mem_read_tab[4][i] = ram_read; + mem_write_tab[4][i] = ram_store; + mem_read_tab[5][i] = ram_read; + mem_write_tab[5][i] = ram_store; + mem_read_tab[6][i] = top_shared_read; + mem_write_tab[6][i] = top_shared_store; + mem_read_tab[7][i] = top_shared_read; + mem_write_tab[7][i] = top_shared_store; + } + + for (i = 0xe0; i <= 0xfe; i++) { + mem_read_tab[0][i] = ram_read; + mem_write_tab[0][i] = ram_store; + mem_read_tab[1][i] = ram_read; + mem_write_tab[1][i] = ram_store; + mem_read_tab[2][i] = top_shared_read; + mem_write_tab[2][i] = top_shared_store; + mem_read_tab[3][i] = top_shared_read; + mem_write_tab[3][i] = top_shared_store; + mem_read_tab[4][i] = ram_read; + mem_write_tab[4][i] = ram_store; + mem_read_tab[5][i] = ram_read; + mem_write_tab[5][i] = ram_store; + mem_read_tab[6][i] = top_shared_read; + mem_write_tab[6][i] = top_shared_store; + mem_read_tab[7][i] = top_shared_read; + mem_write_tab[7][i] = top_shared_store; + } + + for (j = 0; j < NUM_CONFIGS; j++) { + mem_read_tab[j][0xff] = mmu_ffxx_read_z80; + mem_write_tab[j][0xff] = mmu_ffxx_store; + + mem_read_tab[j][0x100] = mem_read_tab[j][0x0]; + mem_write_tab[j][0x100] = mem_write_tab[j][0x0]; + } + + _z80mem_read_tab_ptr = mem_read_tab[0]; + _z80mem_write_tab_ptr = mem_write_tab[0]; + _z80mem_read_base_tab_ptr = mem_read_base_tab[0]; + z80mem_read_limit_tab_ptr = mem_read_limit_tab[0]; + + /* IO address space. */ + + /* At least we know what happens. */ + for (i = 0; i <= 0x100; i++) { + io_read_tab[i] = read_unconnected_io; + io_write_tab[i] = store_unconnected_io; + } +/* + io_read_tab[0x10] = colorram_read; + io_write_tab[0x10] = colorram_store; + io_read_tab[0x11] = colorram_read; + io_write_tab[0x11] = colorram_store; + io_read_tab[0x12] = colorram_read; + io_write_tab[0x12] = colorram_store; + io_read_tab[0x13] = colorram_read; + io_write_tab[0x13] = colorram_store; +*/ + io_read_tab[0xd0] = vicii_read; + io_write_tab[0xd0] = vicii_store; + io_read_tab[0xd1] = vicii_read; + io_write_tab[0xd1] = vicii_store; + io_read_tab[0xd2] = vicii_read; + io_write_tab[0xd2] = vicii_store; + io_read_tab[0xd3] = vicii_read; + io_write_tab[0xd3] = vicii_store; + + io_read_tab[0xd4] = sid_read; + io_write_tab[0xd4] = sid_store; + + io_read_tab[0xd5] = mmu_read; + io_write_tab[0xd5] = mmu_store; + + io_read_tab[0xd6] = vdc_read; + io_write_tab[0xd6] = vdc_store; + io_read_tab[0xd7] = d7xx_read; + io_write_tab[0xd7] = d7xx_store; + + io_read_tab[0xd8] = colorram_read; + io_write_tab[0xd8] = colorram_store; + io_read_tab[0xd9] = colorram_read; + io_write_tab[0xd9] = colorram_store; + io_read_tab[0xda] = colorram_read; + io_write_tab[0xda] = colorram_store; + io_read_tab[0xdb] = colorram_read; + io_write_tab[0xdb] = colorram_store; + + io_read_tab[0xdc] = cia1_read; + io_write_tab[0xdc] = cia1_store; + io_read_tab[0xdd] = cia2_read; + io_write_tab[0xdd] = cia2_store; + + io_read_tab[0xde] = c64io1_read; + io_write_tab[0xde] = c64io1_store; + io_read_tab[0xdf] = c64io2_read; + io_write_tab[0xdf] = c64io2_store; +#endif +} + +#ifdef _MSC_VER +#pragma optimize("",on) +#endif + +void z80mem_set_bank_pointer(BYTE **base, int *limit) +{ + bank_base = base; + bank_limit = limit; +} + +void z80mem_update_config(int config) +{ + _z80mem_read_tab_ptr = mem_read_tab[config]; + _z80mem_write_tab_ptr = mem_write_tab[config]; + _z80mem_read_base_tab_ptr = mem_read_base_tab[config]; + z80mem_read_limit_tab_ptr = mem_read_limit_tab[config]; +/* + if (bank_limit != NULL) { + *bank_base = _z80mem_read_base_tab_ptr[z80_old_reg_pc >> 8]; + if (*bank_base != 0) + *bank_base = _z80mem_read_base_tab_ptr[z80_old_reg_pc >> 8] + - (z80_old_reg_pc & 0xff00); + *bank_limit = z80mem_read_limit_tab_ptr[z80_old_reg_pc >> 8]; + } +*/ +} + +int z80mem_load(void) +{ +// if (z80mem_log == LOG_ERR) // [AppleWin-TC] +// z80mem_log = log_open("Z80MEM"); + + z80mem_initialize(); + + return 0; +} + diff --git a/AppleWin/source/Z80VICE/z80mem.h b/AppleWin/source/Z80VICE/z80mem.h new file mode 100644 index 00000000..fc374d7f --- /dev/null +++ b/AppleWin/source/Z80VICE/z80mem.h @@ -0,0 +1,64 @@ +/* + * z80mem.h + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _Z80MEM_H +#define _Z80MEM_H + +#ifdef WATCOM_COMPILE +#include "../mem.h" +#else +#include "..\CommonVICE\mem.h" // [AppleWin-TC] +#endif + +#include "..\CommonVICE\types.h" // [AppleWin-TC] + +extern int z80mem_resources_init(void); +extern int z80mem_cmdline_options_init(void); + +extern void z80mem_set_bank_pointer(BYTE **base, int *limit); +extern void z80mem_update_config(int config); + +extern int z80mem_load(void); +extern BYTE z80bios_rom[0x1000]; + +extern void z80mem_initialize(void); + +/* Pointers to the currently used memory read and write tables. */ +extern read_func_ptr_t *_z80mem_read_tab_ptr; +extern store_func_ptr_t *_z80mem_write_tab_ptr; +extern BYTE **_z80mem_read_base_tab_ptr; +extern int *z80mem_read_limit_tab_ptr; + +extern BYTE REGPARM1 bios_read(WORD addr); +extern void REGPARM2 bios_store(WORD addr, BYTE value); + +extern store_func_ptr_t io_write_tab[]; +extern read_func_ptr_t io_read_tab[]; + +extern unsigned int z80_old_reg_pc; + +#endif + diff --git a/AppleWin/source/Z80VICE/z80regs.h b/AppleWin/source/Z80VICE/z80regs.h new file mode 100644 index 00000000..025d08fc --- /dev/null +++ b/AppleWin/source/Z80VICE/z80regs.h @@ -0,0 +1,80 @@ +/* + * z80regs.h + * + * Written by + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _Z80REGS_H +#define _Z80REGS_H + +#include "..\CommonVICE\types.h" // [AppleWin-TC] + +typedef struct z80_regs_s { + WORD reg_af; + WORD reg_bc; + WORD reg_de; + WORD reg_hl; + WORD reg_ix; + WORD reg_iy; + WORD reg_sp; + WORD reg_pc; + BYTE reg_i; + BYTE reg_r; + WORD reg_af2; + WORD reg_bc2; + WORD reg_de2; + WORD reg_hl2; +} z80_regs_t; + +#define Z80_REGS_GET_AF(reg_ptr) ((reg_ptr)->reg_af) +#define Z80_REGS_GET_BC(reg_ptr) ((reg_ptr)->reg_bc) +#define Z80_REGS_GET_DE(reg_ptr) ((reg_ptr)->reg_de) +#define Z80_REGS_GET_HL(reg_ptr) ((reg_ptr)->reg_hl) +#define Z80_REGS_GET_IX(reg_ptr) ((reg_ptr)->reg_ix) +#define Z80_REGS_GET_IY(reg_ptr) ((reg_ptr)->reg_iy) +#define Z80_REGS_GET_SP(reg_ptr) ((reg_ptr)->reg_sp) +#define Z80_REGS_GET_PC(reg_ptr) ((reg_ptr)->reg_pc) +#define Z80_REGS_GET_I(reg_ptr) ((reg_ptr)->reg_i) +#define Z80_REGS_GET_R(reg_ptr) ((reg_ptr)->reg_r) +#define Z80_REGS_GET_AF2(reg_ptr) ((reg_ptr)->reg_af2) +#define Z80_REGS_GET_BC2(reg_ptr) ((reg_ptr)->reg_bc2) +#define Z80_REGS_GET_DE2(reg_ptr) ((reg_ptr)->reg_de2) +#define Z80_REGS_GET_HL2(reg_ptr) ((reg_ptr)->reg_hl2) + +#define Z80_REGS_SET_AF(reg_ptr, val) ((reg_ptr)->reg_af = (val)) +#define Z80_REGS_SET_BC(reg_ptr, val) ((reg_ptr)->reg_bc = (val)) +#define Z80_REGS_SET_DE(reg_ptr, val) ((reg_ptr)->reg_de = (val)) +#define Z80_REGS_SET_HL(reg_ptr, val) ((reg_ptr)->reg_hl = (val)) +#define Z80_REGS_SET_IX(reg_ptr, val) ((reg_ptr)->reg_ix = (val)) +#define Z80_REGS_SET_IY(reg_ptr, val) ((reg_ptr)->reg_iy = (val)) +#define Z80_REGS_SET_SP(reg_ptr, val) ((reg_ptr)->reg_sp = (val)) +#define Z80_REGS_SET_PC(reg_ptr, val) ((reg_ptr)->reg_pc = (val)) +#define Z80_REGS_SET_I(reg_ptr, val) ((reg_ptr)->reg_i = (val)) +#define Z80_REGS_SET_R(reg_ptr, val) ((reg_ptr)->reg_r = (val)) +#define Z80_REGS_SET_AF2(reg_ptr, val) ((reg_ptr)->reg_af2 = (val)) +#define Z80_REGS_SET_BC2(reg_ptr, val) ((reg_ptr)->reg_bc2 = (val)) +#define Z80_REGS_SET_DE2(reg_ptr, val) ((reg_ptr)->reg_de2 = (val)) +#define Z80_REGS_SET_HL2(reg_ptr, val) ((reg_ptr)->reg_hl2 = (val)) + +#endif + diff --git a/AppleWin/source/Z80/z80emu.cpp b/AppleWin/source/z80emu.cpp similarity index 72% rename from AppleWin/source/Z80/z80emu.cpp rename to AppleWin/source/z80emu.cpp index 0577b8f6..46e504b9 100644 --- a/AppleWin/source/Z80/z80emu.cpp +++ b/AppleWin/source/z80emu.cpp @@ -13,12 +13,12 @@ // Emula a CPU Z80 -#include "..\StdAfx.h" +#include "StdAfx.h" #include "z80emu.h" // Variaveis -int CPMZ80Slot = 0; -int Z80_IRQ = 0; +static int CPMZ80Slot = 0; +int Z80_IRQ = 0; // Used by Z80Em BYTE __stdcall CPMZ80_IONull(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft) { @@ -37,16 +37,7 @@ BYTE __stdcall CPMZ80_IOWrite(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULO //=========================================================================== void ConfigureSoftcard(LPBYTE pCxRomPeripheral, int Slot, UINT addOrRemove) { - //LPBYTE pCxRomPeripheral = MemGetCxRomPeripheral(); - //if (pCxRomPeripheral == NULL) - // return; - - //UINT uOffset = (m_by6821B << 7) & 0x0700; - //memcpy(pCxRomPeripheral+m_uSlot*256, m_pSlotRom+uOffset, 256); - //if (mem) - // memcpy(mem+0xC000+m_uSlot*256, m_pSlotRom+uOffset, 256); - - memset(pCxRomPeripheral + (Slot << 8), 0xFF, 256); + memset(pCxRomPeripheral + (Slot << 8), 0xFF, APPLE_SLOT_SIZE); CPMZ80Slot = Slot; diff --git a/AppleWin/source/Z80/z80emu.h b/AppleWin/source/z80emu.h similarity index 100% rename from AppleWin/source/Z80/z80emu.h rename to AppleWin/source/z80emu.h