; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
;
; Super FX assembler emulator code
; (c) Copyright 1998 zsKnight and _Demo_.
;
; Permission to use, copy, modify and distribute Snes9x in both binary and
; source form, for non-commercial purposes, is hereby granted without fee,
; providing that this license information and copyright notice appear with
; all copies and any derived work.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event shall the authors be held liable for any damages
; arising from the use of this software.
;
; Snes9x is freeware for PERSONAL USE only. Commercial users should
; seek permission of the copyright holders first. Commercial use includes
; charging money for Snes9x or software derived from Snes9x.
;
; The copyright holders request that bug fixes and improvements to the code
; should be forwarded to them so everyone can benefit from the modifications
; in future versions.
;
; Super NES and Super Nintendo Entertainment System are trademarks of
; Nintendo Co., Limited and its subsidiary companies.
;

; Optimisation : Last checked = LINK

;       - Added SFX support! (Bugs left here and there and 85% optimised)
;         Special thanks to the snes9x team for all the info and help!
;
;For SFX emulation, 9 megabytes of free memory is required to run.
;
;Zsnes auto-detects the SFX emulation from the header and enables it when
;   found.  Also, take note that the SFX is an additional 10Mhz(Ver1) or
;   20Mhz(Ver2) chip which also has to be emulated with the snes and will
;   most likely produce a very noticeable slow down in emulation.
;Recommended System for SFX support :
;
;- Fast Pentium processor (P200 or higher)
;- 12MB of RAM (min 9.3MB free)
;- VGA card
;- Sound Blaster 16 or 100% compatible

; IMPLEMENT SRAM BEFORE RELEASE!

; LMS/SMS might be incorrect
; Try to use LEA in umult

; * Optimise PLOT, COLOR
; *** Check all R15 increment locations


; Problem : Merge instruction can have both N & Z flags set
; Solution : Use bit 16 of flags as an 'extra' sign bit.  If set, it is sign
;            Also have to make sure everything else clears that bit
; Fixed!

; Maybe SBK requires the previous Bank value as well as the address

; Work on GETC, COLOR, PLOT, RPIX
; Last read 2-9-92

FlushCache:
   ; Copy 512 bytes from pb:eax to SfxCACHERAM
   ret

; BUG FIX REPORTS :

; (yy) addressing mode (lms/sms) should be shl 1 instead of shl 8
; Getbh - Supposed to take bits 0..7 of SfxRomBuffer and put it in bits
;         8..15 of the destination (was bits 8..15 to 0..7 of destination)
; ROR - Using ROR instead of RCR
; DIV2 - Needed to be a signed value
; BNE/BEQ - Z flag is tested by 0xFFFF instead of 0x7FFF
; HIB - Didn't write to destination register
; IBT - Needed to be sign extended
; IWT - When address is odd, (address-1) = high byte of destination
; LM  - When address is odd, (address-1) = high byte of destination
; LOOP - Z flag is tested by 0xFFFF instead of 0x7FFF
; IWT RN,#14 - Didn't call UpdateR14
; LM - Was using DReg instead of immediate Reg
;-------------------TODO-------------------------------

; FlushCache

;Do the FETCHPIPE macro
;Modify all opcodes that use DREG in case R15 is updated so that R15
;is increased before setting R15...
; (I checked most of those)

;modify ALT1,ALT2,ALT3 for the call table... (op 3d-3f)

;Pixel opcodes, op4c (maybe zsknight could do that)
;must be done for 2,4 and 8 bit color...
;Finish Opcode 4E and 4EA1

;Check add if the flags are ok (op 50-5f)

;Check if the subtract with carry are ok...

;Check merge, maybe it should merge the lower part...

;Update the opcodes for the smc memory...

;DO IBTRN...

;------------------------------------------------------

tempsfx db 0,0,0

ALIGN32

; FxChip emulation by _Demo_
; Optimised by zsKnight
; based on fxemu by lestat

SfxR0    dd 0     ; default source/destination register
SfxR1    dd 0     ; pixel plot X position register
SfxR2    dd 0     ; pixel plot Y position register
SfxR3    dd 0     ;
SfxR4    dd 0     ; lower 16 bit result of lmult
SfxR5    dd 0     ;
SfxR6    dd 0     ; multiplier for fmult and lmult
SfxR7    dd 0     ; fixed point texel X position for merge
SfxR8    dd 0     ; fixed point texel Y position for merge
SfxR9    dd 0     ;
SfxR10   dd 0     ; 
SfxR11   dd 0     ; return address set by link
SfxR12   dd 0     ; loop counter
SfxR13   dd 0     ; loop point address
SfxR14   dd 0     ; rom address for getb, getbh, getbl, getbs
SfxR15   dd 0     ; program counter 

SfxSFR   dd 0     ; status flag register (16bit)
;SFR status flag register bits:
; 0   - 
; 1   Z   Zero flag
; 2   CY  Carry flag
; 3   S   Sign flag
; 4   OV  Overflow flag
; 5   G   Go flag (set to 1 when the GSU is running)
; 6   R   Set to 1 when reading ROM using R14 address
; 7   - 
; 8   ALT1   Mode set-up flag for the next instruction
; 9   ALT2   Mode set-up flag for the next instruction
;10   IL  Immediate lower 8-bit flag
;11   IH  Immediate higher 8-bit flag
;12   B   Set to 1 when the WITH instruction is executed
;13   - 
;14   - 
;15   IRQ Set to 1 when GSU caused an interrupt
;                Set to 0 when read by 658c16

SfxBRAMR    dd 0  ; backup ram read only on/off (8bit)
SfxPBR      dd 0  ; program bank register (8bit)
SfxROMBR    dd 0  ; rom bank register (8bit)
SfxCFGR     dd 0  ; control flags register (8bit)
SfxSCBR     dd 0  ; screen bank register (8bit)
SfxCLSR     dd 0  ; clock speed register (8bit)
SfxSCMR     dd 0  ; screen mode register (8bit)
SfxVCR      dd 0  ; version code register (8bit)
SfxRAMBR    dd 0  ; ram bank register (8bit)
SfxCBR      dd 0  ; cache base register (16bit)

SfxCOLR     dd 0  ; Internal color register
SfxPOR      dd 0  ; Plot option register

SfxCacheFlags  dd 0  ; Saying what parts of the cache was written to
SfxLastRamAdr  dd 0  ; Last RAM address accessed
SfxDREG        dd 0  ; Current destination register index
SfxSREG        dd 0  ; Current source register index
SfxRomBuffer   dd 0  ; Current byte read by R14
SfxPIPE        dd 0  ; Instructionset pipe
SfxPipeAdr     dd 0  ; The address of where the pipe was read from

SfxnRamBanks   dd 4  ; Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!)
SfxnRomBanks   dd 0  ; Number of 32kb-banks in Cart-ROM

SfxvScreenHeight dd 0 ; 128, 160 or 192
SfxvScreenSize dd 0

SfxCacheActive dd 0  ; Cache Active

SfxCarry       dd 0  ; Carry flag
SfxSignZero    dd 0  ; Sign and Zero flag
SfxB           dd 0  ; B flag  (1 when with instruction executed)
SfxOverflow    dd 0  ; Overflow flag

SfxCACHERAM times 512 db 0    ; 512 bytes of GSU cache memory

num2writesfxreg  equ $-SfxR0

SfxCPB         dd 0
SfxCROM        dd 0
SfxRAMMem      dd 0
withr15sk      dd 0

;SfxRAM times 256*1024 db 0

; If we need this later...

%macro FETCHPIPE 0
;    mov edx,[SfxPBR]
;    mov edx,[SfxMemTable+edx*4]
;    mov edx,[SfxCPB]
;    mov edx,[SfxR15]
    mov cl,[ebp]
%endmacro

%macro UpdateR14 0
;    mov edx,[SfxROMBR]
;    mov edx,[SfxMemTable+edx*4]
    mov eax,[SfxCROM]
;    and dword[SfxR14],0FFFFh
    add eax,[SfxR14]
    mov [SfxRomBuffer],eax
%endmacro

%macro UpdateR15 0
    mov ebp,[SfxCPB]
    add ebp,[SfxR15]
%endmacro

%macro CLRFLAGS 0
  ;and dword [SfxSFR],0FFFFh-0100h-0200h-1000h  ; Clear ALT1,ALT2 and B Flags
;  xor ch,ch
;  mov dword [SfxB],0         ; Clear B Flag
;  mov esi,SfxR0
;  mov edi,SfxR0
%endmacro

FxOp00:     ; STOP   stop GSU execution (and maybe generate an IRQ)     ; Verified.
   FETCHPIPE
   and dword [SfxSFR],0FFFFh-32     ; Clear Go flag (set to 1 when the GSU is running)
   test dword [SfxCFGR],080h        ; Check if the interrupt generation is on
   jnz .NoIRQ
   or dword [SfxSFR],08000h         ; Set IRQ Flag
.NoIRQ
   CLRFLAGS
   inc ebp
   mov dword [NumberOfOpcodes],1
   xor cl,cl
   ret

FxOp01:     ; NOP    no operation       ; Verified.
   FETCHPIPE
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret

FxOp02:     ; CACHE  reintialize GSU cache
   mov eax,ebp
   FETCHPIPE
   sub eax,[SfxCPB]
   and eax,0FFF0h
   cmp dword [SfxCBR],eax
   je .SkipUpdate
   cmp byte [SfxCacheActive],1
   je .SkipUpdate
   mov dword [SfxCBR],eax
   mov dword [SfxCacheActive],1
   call FlushCache
.SkipUpdate
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret

FxOp03:     ; LSR    logic shift right  ; Verified.
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   mov [SfxCarry],al
   and byte[SfxCarry],1
   shr ax,1                      ; logic shift right
   inc ebp                ; Increase program counter
   mov [edi],eax            ; Write Destination
   mov dword [SfxSignZero],eax
   CLRFLAGS
   ret

FxOp04:     ; ROL    rotate left (RCL?) ; V
   shr byte[SfxCarry],1
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   rcl ax,1
   rcl byte[SfxCarry],1
   inc ebp                ; Increase program counter
   mov [edi],eax            ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

FxOp05:     ; BRA    branch always      ; Verified.
   movsx eax,byte[ebp]
   mov cl,[ebp+1]
   inc ebp
   add ebp,eax
   call [FxTable+ecx*4]
   ret

FxOp06:     ; BGE    branch on greater or equals        ; Verified.
   movsx eax,byte[ebp]
   mov ebx,[SfxSignZero]
   shr ebx,15
   inc ebp
   xor bl,[SfxOverflow]
   mov cl,[ebp]
   test bl,01h
   jnz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp07:     ; BLT    branch on lesss than       ; Verified.
   movsx eax,byte[ebp]
   mov ebx,[SfxSignZero]
   shr ebx,15
   inc ebp
   xor bl,[SfxOverflow]
   mov cl,[ebp]
   test bl,01h
   jz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp08:     ; BNE    branch on not equal        ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test dword[SfxSignZero],0FFFFh
   mov cl,[ebp]
   jz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp09:     ; BEQ    branch on equal (z=1)      ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test dword[SfxSignZero],0FFFFh
   mov cl,[ebp]
   jnz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp0A:     ; BPL    branch on plus     ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test dword[SfxSignZero],088000h
   mov cl,[ebp]
   jnz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp0B:     ; BMI    branch on minus    ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test dword[SfxSignZero],088000h
   mov cl,[ebp]
   jz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp0C:     ; BCC    branch on carry clear      ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test byte[SfxCarry],01h
   mov cl,[ebp]
   jnz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp0D:     ; BCS    branch on carry set        ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test byte[SfxCarry],01h
   mov cl,[ebp]
   jz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp0E:     ; BVC    branch on overflow clear   ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test byte[SfxOverflow],01h
   mov cl,[ebp]
   jnz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

FxOp0F:     ; BVS    branch on overflow set     ; Verified.
   movsx eax,byte[ebp]
   inc ebp
   test byte[SfxOverflow],01h
   mov cl,[ebp]
   jz .nojump
   add ebp,eax
   call [FxTable+ecx*4]
   ret
.nojump
   inc ebp
   call [FxTable+ecx*4]
   ret

%macro TORN 1   ; V
   FETCHPIPE
   mov edi, SfxR0+%1*4
   inc ebp                ; Increase program counter
   call [FxTable+ecx*4]
   mov edi,SfxR0
   ret
%endmacro

FxOp10:     ; TO RN  set register n as destination register
   TORN 0
FxOp11:     ; TO RN  set register n as destination register
   TORN 1   
FxOp12:     ; TO RN  set register n as destination register
   TORN 2   
FxOp13:     ; TO RN  set register n as destination register
   TORN 3   
FxOp14:     ; TO RN  set register n as destination register
   TORN 4   
FxOp15:     ; TO RN  set register n as destination register
   TORN 5   
FxOp16:     ; TO RN  set register n as destination register
   TORN 6   
FxOp17:     ; TO RN  set register n as destination register
   TORN 7   
FxOp18:     ; TO RN  set register n as destination register
   TORN 8   
FxOp19:     ; TO RN  set register n as destination register
   TORN 9   
FxOp1A:     ; TO RN  set register n as destination register
   TORN 10   
FxOp1B:     ; TO RN  set register n as destination register
   TORN 11   
FxOp1C:     ; TO RN  set register n as destination register
   TORN 12   
FxOp1D:     ; TO RN  set register n as destination register
   TORN 13
FxOp1E:     ; TO RN  set register n as destination register
   FETCHPIPE
   mov edi,SfxR0+14*4
   inc ebp
   call [FxTable+ecx*4]
   mov edi,SfxR0
   UpdateR14
   ret
FxOp1F:     ; TO RN  set register n as destination register
   FETCHPIPE
   mov edi,SfxR0+15*4
   inc ebp
   call [FxTable+ecx*4]
   mov ebp,[SfxCPB]
   add ebp,[SfxR15]
   mov edi,SfxR0
   ret

%macro WITH 1  ; Verified.
   FETCHPIPE
   mov esi,SfxR0+%1*4
   mov edi,SfxR0+%1*4
   mov dword [SfxB],1
   inc ebp                ; Increase program counter
   call [FxTablec+ecx*4]
   mov esi,SfxR0
   mov edi,SfxR0
   mov dword [SfxB],0         ; Clear B Flag
   ret
%endmacro

FxOp20:     ; WITH  set register n as source and destination register
   WITH 0
FxOp21:     ; WITH  set register n as source and destination register
   WITH 1
FxOp22:     ; WITH  set register n as source and destination register
   WITH 2
FxOp23:     ; WITH  set register n as source and destination register
   WITH 3
FxOp24:     ; WITH  set register n as source and destination register
   WITH 4
FxOp25:     ; WITH  set register n as source and destination register
   WITH 5
FxOp26:     ; WITH  set register n as source and destination register
   WITH 6
FxOp27:     ; WITH  set register n as source and destination register
   WITH 7
FxOp28:     ; WITH  set register n as source and destination register
   WITH 8
FxOp29:     ; WITH  set register n as source and destination register
   WITH 9
FxOp2A:     ; WITH  set register n as source and destination register
   WITH 10
FxOp2B:     ; WITH  set register n as source and destination register
   WITH 11
FxOp2C:     ; WITH  set register n as source and destination register
   WITH 12
FxOp2D:     ; WITH  set register n as source and destination register
   WITH 13
FxOp2E:     ; WITH  set register n as source and destination register
   FETCHPIPE
   mov esi,SfxR0+14*4
   mov edi,SfxR0+14*4
   mov dword [SfxB],1
   inc ebp
   call [FxTablec+ecx*4]
   mov dword [SfxB],0         ; Clear B Flag
   mov esi,SfxR0
   mov edi,SfxR0
   UpdateR14
   ret
FxOp2F:     ; WITH  set register n as source and destination register
   FETCHPIPE
   mov esi,SfxR0+15*4
   mov edi,SfxR0+15*4
   mov dword [SfxB],1
   inc ebp
   mov eax,ebp
   sub eax,[SfxCPB]
   mov dword[withr15sk],0
   mov [SfxR15],eax
   call [FxTableb+ecx*4]
   cmp dword[withr15sk],1
   je .skip
   mov ebp,[SfxCPB]
   add ebp,[SfxR15]
.skip
   mov dword [SfxB],0         ; Clear B Flag
   mov esi,SfxR0
   mov edi,SfxR0
   ret

%macro STWRN 1  ; V
   mov eax,[SfxR0+%1*4]             ; Read register
   mov ebx,[SfxRAMMem]
   mov dword [SfxLastRamAdr],eax    ; Save last ram address
   add dword [SfxLastRamAdr],ebx    ; Save last ram address
   mov edx,[esi]            ; Read Source
   FETCHPIPE
   mov [ebx+eax],dl         ; Store Word
   xor eax,1
   inc ebp                ; Increase program counter
   mov [ebx+eax],dh         ; Store Word
   CLRFLAGS
   ret
%endmacro

FxOp30:     ; STW RN store word
   STWRN 0
FxOp31:     ; STW RN store word
   STWRN 1
FxOp32:     ; STW RN store word
   STWRN 2
FxOp33:     ; STW RN store word
   STWRN 3
FxOp34:     ; STW RN store word
   STWRN 4
FxOp35:     ; STW RN store word
   STWRN 5
FxOp36:     ; STW RN store word
   STWRN 6
FxOp37:     ; STW RN store word
   STWRN 7
FxOp38:     ; STW RN store word
   STWRN 8
FxOp39:     ; STW RN store word
   STWRN 9
FxOp3A:     ; STW RN store word
   STWRN 10
FxOp3B:     ; STW RN store word
   STWRN 11

%macro STBRN 1  ; V
   mov eax,[SfxR0+%1*4]             ; Read register
   FETCHPIPE
   add eax,[SfxRAMMem]
   mov dword [SfxLastRamAdr],eax    ; Save last ram address
   mov ebx,[esi]            ; Read Source
   mov byte [eax],bl         ; Store Byte
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret
%endmacro

FxOp30A1:   ; STB RN store byte
   STBRN 0
FxOp31A1:   ; STB RN store byte
   STBRN 1
FxOp32A1:   ; STB RN store byte
   STBRN 2
FxOp33A1:   ; STB RN store byte
   STBRN 3
FxOp34A1:   ; STB RN store byte
   STBRN 4
FxOp35A1:   ; STB RN store byte
   STBRN 5
FxOp36A1:   ; STB RN store byte
   STBRN 6
FxOp37A1:   ; STB RN store byte
   STBRN 7
FxOp38A1:   ; STB RN store byte
   STBRN 8
FxOp39A1:   ; STB RN store byte
   STBRN 9
FxOp3AA1:   ; STB RN store byte
   STBRN 10
FxOp3BA1:   ; STB RN store byte
   STBRN 11

FxOp3C:     ; LOOP   decrement loop counter, and branch on not zero ; V
   dec word [SfxR12]       ; decrement loop counter
   FETCHPIPE
   mov eax,[SfxR12]
   mov [SfxSignZero],eax
   or eax,eax
   jz .NoBranch
   mov eax,dword [SfxR13]
   mov ebp,[SfxCPB]
   add ebp,eax
   CLRFLAGS
   ret
.NoBranch
   inc ebp
   CLRFLAGS
   ret

FxOp3D:     ; ALT1   set alt1 mode      ; Verified.
   FETCHPIPE
   mov dword [SfxB],0
   or ch,01h
   inc ebp
   call [FxTable+ecx*4]
   xor ch,ch
   ret

FxOp3E:     ; ALT2   set alt1 mode      ; Verified.
   FETCHPIPE
   mov dword [SfxB],0
   or ch,02h
   inc ebp
   call [FxTable+ecx*4]
   xor ch,ch
   ret

FxOp3F:     ; ALT3   set alt3 mode      ; Verified.
   FETCHPIPE
   mov dword [SfxB],0
   or ch,03h
   inc ebp
   call [FxTable+ecx*4]
   xor ch,ch
   ret

%macro LDWRN 1  ; V
   mov eax,[SfxR0+%1*4]             ; Read register
   mov ebx,[SfxRAMMem]
   mov dword [SfxLastRamAdr],eax    ; Save last ram address
   FETCHPIPE
   mov dl,[ebx+eax]         ; Store Word
   add dword [SfxLastRamAdr],ebx    ; Save last ram address
   xor eax,1
   and edx,0FFFFh
   inc ebp                ; Increase program counter
   mov dh,[ebx+eax]         ; Store Word
   mov [edi],edx            ; Read Source
   CLRFLAGS
   ret
%endmacro

FxOp40:     ; LDW RN load word from RAM
   LDWRN 0
FxOp41:     ; LDW RN load word from RAM
   LDWRN 1
FxOp42:     ; LDW RN load word from RAM
   LDWRN 2
FxOp43:     ; LDW RN load word from RAM
   LDWRN 3
FxOp44:     ; LDW RN load word from RAM
   LDWRN 4
FxOp45:     ; LDW RN load word from RAM
   LDWRN 5
FxOp46:     ; LDW RN load word from RAM
   LDWRN 6
FxOp47:     ; LDW RN load word from RAM
   LDWRN 7
FxOp48:     ; LDW RN load word from RAM
   LDWRN 8
FxOp49:     ; LDW RN load word from RAM
   LDWRN 9
FxOp4A:     ; LDW RN load word from RAM
   LDWRN 10
FxOp4B:     ; LDW RN load word from RAM
   LDWRN 11

%macro LDBRN 1  ; V
   mov eax,[SfxR0+%1*4]             ; Read register
   FETCHPIPE
   add eax,[SfxRAMMem]
   xor ebx,ebx
   mov dword [SfxLastRamAdr],eax    ; Save last ram address
   mov bl,[eax]                     ; Read Byte
   inc ebp                ; Increase program counter
   mov [edi],ebx            ; Store Result
   CLRFLAGS
   ret
%endmacro

FxOp40A1:   ; LDB RN load byte from RAM
   LDBRN 0   
FxOp41A1:   ; LDB RN load byte from RAM
   LDBRN 1 
FxOp42A1:   ; LDB RN load byte from RAM
   LDBRN 2   
FxOp43A1:   ; LDB RN load byte from RAM
   LDBRN 3   
FxOp44A1:   ; LDB RN load byte from RAM
   LDBRN 4   
FxOp45A1:   ; LDB RN load byte from RAM
   LDBRN 5
FxOp46A1:   ; LDB RN load byte from RAM
   LDBRN 6   
FxOp47A1:   ; LDB RN load byte from RAM
   LDBRN 7   
FxOp48A1:   ; LDB RN load byte from RAM
   LDBRN 8
FxOp49A1:   ; LDB RN load byte from RAM
   LDBRN 9
FxOp4AA1:   ; LDB RN load byte from RAM
   LDBRN 10
FxOp4BA1:   ; LDB RN load byte from RAM
   LDBRN 11

plotshift db 0

FxOp4C:     ; PLOT   plot pixel with R1,R2 as x,y and the color register as the color
   FETCHPIPE
   inc ebp
   CLRFLAGS
   mov ebx,[SfxR2]
   mov bh,[SfxR1]
   test byte[SfxPOR],10h
   jnz .objmode
   mov al,[SfxSCMR]
   and al,00100100b     ; 4 + 32
   cmp al,4
   je .lines160
   cmp al,32
   je .lines192
   cmp al,36
   je .objmode
   mov eax,[sfx128lineloc]
   jmp .donelines
.lines160
   mov eax,[sfx160lineloc]
   jmp .donelines
.lines192
   mov eax,[sfx192lineloc]
   jmp .donelines
.objmode
   mov eax,[sfxobjlineloc]
.donelines
   mov ebx,[eax+ebx*4]
   cmp ebx,0FFFFFFFFh
   je near .nodraw
   xor eax,eax
   ; bits 5/2 : 00 = 128 pixels, 01 = 160 pixels, 10 = 192 pixels, 11 = obj
   ; bits 1/0 : 00 = 4 color, 01 = 16-color, 10 = not used, 11 = 256 color
   ; 192 pixels = 24 tiles, 160 pixels = 20 tiles, 128 pixels = 16 tiles
   ;              16+8(4/3)              16+4(4/2)              16(4/0)
   push ecx
   mov al,[SfxSCMR]
   and al,00000011b     ; 4 + 32
   cmp al,0
   je near .colors4
   cmp al,3
   je near .colors256

   shl ebx,5    ; x32 (16 colors)
   mov al,[SfxSCBR]
   shl eax,10   ; Get SFX address
   add eax,ebx
   add eax,[sfxramdata]
   mov ebx,[SfxR2]
   and ebx,07h
   shl ebx,1
   add eax,ebx
   mov cl,[SfxR1]
   and cl,07h
   xor cl,07h
   mov bl,1
   shl bl,cl
   mov bh,bl
   xor bh,0FFh
   pop ecx
   test byte[SfxPOR],01h
   jnz .nozerocheck_16
   test byte[SfxCOLR],0Fh
   jz .nodraw
.nozerocheck_16
   mov dl,[SfxCOLR]
   test byte[SfxPOR],02h
   jz .nodither4b
   mov dh,[SfxR1]
   xor dh,[SfxR2]
   test dh,01h
   jz .nodither4b
   shr dh,4
.nodither4b
   and byte[eax],bh
   and byte[eax+1],bh
   and byte[eax+16],bh
   and byte[eax+17],bh
   test dl,01h
   jz .nodraw_16
   or byte[eax],   bl
.nodraw_16
   test dl,02h
   jz .nodraw2_16
   or byte[eax+1], bl
.nodraw2_16
   test dl,04h
   jz .nodraw3_16
   or byte[eax+16],bl
.nodraw3_16
   test dl,08h
   jz .nodraw4_16
   or byte[eax+17],bl
.nodraw4_16
.nodraw
   inc word [SfxR1]
   ret

.colors4
   shl ebx,4    ; x16 (4 colors)
   mov al,[SfxSCBR]
   shl eax,10   ; Get SFX address
   add eax,ebx
   add eax,[sfxramdata]
   mov ebx,[SfxR2]
   and ebx,07h
   shl ebx,1
   add eax,ebx
   mov cl,[SfxR1]
   and cl,07h
   xor cl,07h
   mov bl,1
   shl bl,cl
   mov bh,bl
   xor bh,0FFh
   pop ecx
   test byte[SfxPOR],01h
   jnz .nozerocheck_4
   test byte[SfxCOLR],03h
   jz .noplot_4
.nozerocheck_4
   mov dl,[SfxCOLR]
   test byte[SfxPOR],02h
   jz .nodither2b
   mov dh,[SfxR1]
   xor dh,[SfxR2]
   test dh,01h
   jz .nodither2b
   shr dh,4
.nodither2b
   and byte[eax],bh
   and byte[eax+1],bh
   test dl,01h
   jz .nodraw_4
   or byte[eax],   bl
.nodraw_4
   test dl,02h
   jz .nodraw2_4
   or byte[eax+1], bl
.nodraw2_4
.noplot_4
   inc word [SfxR1]
   ret

.colors256
   shl ebx,6    ; x64 (256 colors)
   mov al,[SfxSCBR]
   shl eax,10   ; Get SFX address
   add eax,ebx
   add eax,[sfxramdata]
   mov ebx,[SfxR2]
   and ebx,07h
   shl ebx,1
   add eax,ebx
   mov cl,[SfxR1]
   and cl,07h
   xor cl,07h
   mov bl,1
   shl bl,cl
   mov bh,bl
   xor bh,0FFh
   pop ecx
   test byte[SfxPOR],01h
   jnz .nozerocheck_256
   mov dl,0FFh
   test byte[SfxPOR],08h
   jz .nozerocheckb_256
   mov dl,0Fh
.nozerocheckb_256
   test byte[SfxCOLR],dl
   jz .noplot_256
.nozerocheck_256
   mov dl,[SfxCOLR]
   and byte[eax],bh
   and byte[eax+1],bh
   and byte[eax+16],bh
   and byte[eax+17],bh
   and byte[eax+32],bh
   and byte[eax+33],bh
   and byte[eax+48],bh
   and byte[eax+49],bh
   test dl,01h
   jz .nodraw_256
   or byte[eax],   bl
.nodraw_256
   test dl,02h
   jz .nodraw2_256
   or byte[eax+1], bl
.nodraw2_256
   test dl,04h
   jz .nodraw3_256
   or byte[eax+16],bl
.nodraw3_256
   test dl,08h
   jz .nodraw4_256
   or byte[eax+17],bl
.nodraw4_256
   test dl,10h
   jz .nodraw5_256
   or byte[eax+32],   bl
.nodraw5_256
   test dl,20h
   jz .nodraw6_256
   or byte[eax+33], bl
.nodraw6_256
   test dl,40h
   jz .nodraw7_256
   or byte[eax+48],bl
.nodraw7_256
   test dl,80h
   jz .nodraw8_256
   or byte[eax+49],bl
.nodraw8_256
.noplot_256
   inc word [SfxR1]
   ret

.prevx dw 0
.prevy dw 0

sfxwarning db 0

FxOp4CA1:   ; RPIX   read color of the pixel with R1,R2 as x,y
   FETCHPIPE
   mov ebx,[SfxR2]
   mov bh,[SfxR1]
   test byte[SfxPOR],10h
   jnz .objmode
   mov al,[SfxSCMR]
   and al,00100100b     ; 4 + 32
   cmp al,4
   je .lines160
   cmp al,32
   je .lines192
   cmp al,36
   je .objmode
   mov eax,[sfx128lineloc]
   jmp .donelines
.lines160
   mov eax,[sfx160lineloc]
   jmp .donelines
.lines192
   mov eax,[sfx192lineloc]
   jmp .donelines
.objmode
   mov eax,[sfxobjlineloc]
.donelines
   mov ebx,[eax+ebx*4]
   cmp ebx,0FFFFFFFFh
   je near .nodraw
   xor eax,eax
   ; bits 5/2 : 00 = 128 pixels, 01 = 160 pixels, 10 = 192 pixels, 11 = obj
   ; bits 1/0 : 00 = 4 color, 01 = 16-color, 10 = not used, 11 = 256 color
   ; 192 pixels = 24 tiles, 160 pixels = 20 tiles, 128 pixels = 16 tiles
   ;              16+8(4/3)              16+4(4/2)              16(4/0)
   push ecx
   mov al,[SfxSCMR]
   and al,00000011b     ; 4 + 32

   cmp al,0
   je near .colors4
   cmp al,3
   je near .colors256

   shl ebx,5    ; x32 (16 colors)
   mov al,[SfxSCBR]
   shl eax,10   ; Get SFX address
   add eax,ebx
   add eax,[sfxramdata]
   mov ebx,[SfxR2]
   and ebx,07h
   shl ebx,1
   add eax,ebx
   mov cl,[SfxR1]
   and cl,07h
   xor cl,07h
   mov bl,1
   shl bl,cl
   pop ecx
   xor bh,bh
   test byte[eax],bl
   jz .nodraw_16
   or bh,01h
.nodraw_16
   test byte[eax+1],bl
   jz .nodraw2_16
   or bh,02h
.nodraw2_16
   test byte[eax+16],bl
   jz .nodraw3_16
   or bh,04h
.nodraw3_16
   test byte[eax+17],bl
   jz .nodraw4_16
   or bh,08h
.nodraw4_16
.nodraw
   mov bl,bh
   and ebx,0FFh
   inc ebp
;   UpdateR14
   CLRFLAGS
   mov [edi],ebx            ; Write Destination
   mov [flagnz],ebx
   ret

.colors4
   shl ebx,4    ; x16 (4 colors)
   mov al,[SfxSCBR]
   shl eax,10   ; Get SFX address
   add eax,ebx
   add eax,[sfxramdata]
   mov ebx,[SfxR2]
   and ebx,07h
   shl ebx,1
   add eax,ebx
   mov cl,[SfxR1]
   and cl,07h
   xor cl,07h
   mov bl,1
   shl bl,cl
   mov bh,bl
   xor bh,0FFh
   pop ecx
   xor bh,bh
   test byte[eax],bl
   jz .nodraw_4
   or bh,01h
.nodraw_4
   test byte[eax+1],bl
   jz .nodraw2_4
   or bh,02h
.nodraw2_4
   mov bl,bh
   and ebx,0FFh
   inc ebp
;   UpdateR14
   CLRFLAGS
   mov [edi],ebx            ; Write Destination
   mov [flagnz],ebx
   ret

.colors256
   shl ebx,6    ; x64 (256 colors)
   mov al,[SfxSCBR]
   shl eax,10   ; Get SFX address
   add eax,ebx
   add eax,[sfxramdata]
   mov ebx,[SfxR2]
   and ebx,07h
   shl ebx,1
   add eax,ebx
   mov cl,[SfxR1]
   and cl,07h
   xor cl,07h
   mov bl,1
   shl bl,cl
   mov bh,bl
   xor bh,0FFh
   pop ecx
   xor bh,bh
   test byte[eax],bl
   jz .nodraw_256
   or bh,01h
.nodraw_256
   test byte[eax+1],bl
   jz .nodraw2_256
   or bh,02h
.nodraw2_256
   test byte[eax+16],bl
   jz .nodraw3_256
   or bh,04h
.nodraw3_256
   test byte[eax+17],bl
   jz .nodraw4_256
   or bh,08h
.nodraw4_256
   test byte[eax+32],bl
   jz .nodraw5_256
   or bh,10h
.nodraw5_256
   test byte[eax+33],bl
   jz .nodraw6_256
   or bh,20h
.nodraw6_256
   test byte[eax+48],bl
   jz .nodraw7_256
   or bh,40h
.nodraw7_256
   test byte[eax+49],bl
   jz .nodraw8_256
   or bh,80h
.nodraw8_256
   mov bl,bh
   and ebx,0FFh
   inc ebp
;   UpdateR14
   CLRFLAGS
   mov [edi],ebx            ; Write Destination
   mov [flagnz],ebx
   ret

FxOp4D:     ; SWAP   swap upper and lower byte of a register    ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   ror ax,8   
   inc ebp                ; Increase program counter
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret

FxOp4E:     ; COLOR  copy source register to color register     ; V
   FETCHPIPE
   mov eax,[esi]            ; Read Source
   ; if bit 3 of SfxPOR is set, then don't modify the upper 4 bits
   test byte[SfxPOR],04h
   jz .nohighnibble
   mov bl,al
   shr bl,4
   and al,0F0h
   or al,bl
.nohighnibble
   test byte[SfxPOR],08h
   jnz .preserveupper
   mov [SfxCOLR],al
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret
.preserveupper
   mov bl,[SfxCOLR]
   and al,0Fh
   and bl,0F0h
   or al,bl
   mov [SfxCOLR],al
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret

FxOp4EA1:   ; CMODE  set plot option register ; V
   FETCHPIPE
   mov eax,[esi]            ; Read Source
   inc ebp                ; Increase program counter
   mov dword [SfxPOR],eax
   CLRFLAGS
   ret

FxOp4F:     ; NOT    perform exclusive exor with 1 on all bits  ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   xor eax,0FFFFh
   inc ebp                ; Increase program counter
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret

%macro ADDRN 1  ; V
   mov eax, [esi]    ; Read Source
   mov ebx, [SfxR0+%1*4]
   FETCHPIPE
   add ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   mov [SfxSignZero],eax
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp50:     ; ADD RN add, register + register
   ADDRN 0
FxOp51:     ; ADD RN add, register + register
   ADDRN 1
FxOp52:     ; ADD RN add, register + register
   ADDRN 2
FxOp53:     ; ADD RN add, register + register
   ADDRN 3
FxOp54:     ; ADD RN add, register + register
   ADDRN 4
FxOp55:     ; ADD RN add, register + register
   ADDRN 5
FxOp56:     ; ADD RN add, register + register
   ADDRN 6
FxOp57:     ; ADD RN add, register + register
   ADDRN 7
FxOp58:     ; ADD RN add, register + register
   ADDRN 8
FxOp59:     ; ADD RN add, register + register
   ADDRN 9
FxOp5A:     ; ADD RN add, register + register
   ADDRN 10
FxOp5B:     ; ADD RN add, register + register
   ADDRN 11
FxOp5C:     ; ADD RN add, register + register
   ADDRN 12
FxOp5D:     ; ADD RN add, register + register
   ADDRN 13
FxOp5E:     ; ADD RN add, register + register
   ADDRN 14
FxOp5F:     ; ADD RN add, register + register
   FETCHPIPE
   mov eax, [esi]    ; Read Source
   mov ebx,ebp
   sub ebx,[SfxCPB]
   add ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   mov [SfxSignZero],eax
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   CLRFLAGS
   ret

%macro ADCRN 1  ; V
   FETCHPIPE
   mov eax, [esi]    ; Read Source
   mov ebx, [SfxR0+%1*4]
   shr byte[SfxCarry],1
   adc ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   mov [SfxSignZero],eax
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp50A1:   ; ADC RN add with carry, register + register
   ADCRN 0
FxOp51A1:   ; ADC RN add with carry, register + register
   ADCRN 1
FxOp52A1:   ; ADC RN add with carry, register + register
   ADCRN 2
FxOp53A1:   ; ADC RN add with carry, register + register
   ADCRN 3
FxOp54A1:   ; ADC RN add with carry, register + register
   ADCRN 4
FxOp55A1:   ; ADC RN add with carry, register + register
   ADCRN 5
FxOp56A1:   ; ADC RN add with carry, register + register
   ADCRN 6
FxOp57A1:   ; ADC RN add with carry, register + register
   ADCRN 7
FxOp58A1:   ; ADC RN add with carry, register + register
   ADCRN 8
FxOp59A1:   ; ADC RN add with carry, register + register
   ADCRN 9
FxOp5AA1:   ; ADC RN add with carry, register + register
   ADCRN 10
FxOp5BA1:   ; ADC RN add with carry, register + register
   ADCRN 11
FxOp5CA1:   ; ADC RN add with carry, register + register
   ADCRN 12
FxOp5DA1:   ; ADC RN add with carry, register + register
   ADCRN 13
FxOp5EA1:   ; ADC RN add with carry, register + register
   ADCRN 14
FxOp5FA1:   ; ADC RN add with carry, register + register
   FETCHPIPE
   mov eax, [esi]    ; Read Source
   mov ebx,ebp
   sub ebx,[SfxCPB]
   shr byte[SfxCarry],1
   adc ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   mov [SfxSignZero],eax
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   CLRFLAGS
   ret

%macro ADIRN 1  ; V
   mov eax, [esi]    ; Read Source
   FETCHPIPE
   add ax,%1
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   mov [SfxSignZero],eax
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   CLRFLAGS
   ret
%endmacro

; Weird opcode (FxOp50A2, add 0, wow!)
FxOp50A2:   ; ADI RN add, register + immediate
   ADIRN 0
FxOp51A2:   ; ADI RN add, register + immediate
   ADIRN 1
FxOp52A2:   ; ADI RN add, register + immediate
   ADIRN 2
FxOp53A2:   ; ADI RN add, register + immediate
   ADIRN 3
FxOp54A2:   ; ADI RN add, register + immediate
   ADIRN 4
FxOp55A2:   ; ADI RN add, register + immediate
   ADIRN 5
FxOp56A2:   ; ADI RN add, register + immediate
   ADIRN 6
FxOp57A2:   ; ADI RN add, register + immediate
   ADIRN 7
FxOp58A2:   ; ADI RN add, register + immediate
   ADIRN 8
FxOp59A2:   ; ADI RN add, register + immediate
   ADIRN 9
FxOp5AA2:   ; ADI RN add, register + immediate
   ADIRN 10
FxOp5BA2:   ; ADI RN add, register + immediate
   ADIRN 11
FxOp5CA2:   ; ADI RN add, register + immediate
   ADIRN 12
FxOp5DA2:   ; ADI RN add, register + immediate
   ADIRN 13
FxOp5EA2:   ; ADI RN add, register + immediate
   ADIRN 14
FxOp5FA2:   ; ADI RN add, register + immediate
   ADIRN 15

%macro ADCIRN 1 ; V
   FETCHPIPE
   mov eax, [esi]    ; Read Source
   shr byte[SfxCarry],1
   adc ax,%1
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   mov [SfxSignZero],eax
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   CLRFLAGS
   ret
%endmacro

; Another very useful opcode
FxOp50A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 0
FxOp51A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 1
FxOp52A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 2
FxOp53A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 3
FxOp54A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 4
FxOp55A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 5
FxOp56A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 6
FxOp57A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 7
FxOp58A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 8
FxOp59A3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 9
FxOp5AA3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 10
FxOp5BA3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 11
FxOp5CA3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 12
FxOp5DA3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 13
FxOp5EA3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 14
FxOp5FA3:   ; ADCIRN add with carry, register + immediate
   ADCIRN 15

%macro SUBRN 1  ; V
   mov eax,[esi]    ; Read Source
   mov ebx,[SfxR0+%1*4]
   FETCHPIPE
   sub ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   inc ebp                   ; Increase program counter
   mov [edi],eax                        ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOp60:     ; SUBRN  subtract, register - register
   SUBRN 0
FxOp61:     ; SUBRN  subtract, register - register
   SUBRN 1
FxOp62:     ; SUBRN  subtract, register - register
   SUBRN 2
FxOp63:     ; SUBRN  subtract, register - register
   SUBRN 3
FxOp64:     ; SUBRN  subtract, register - register
   SUBRN 4
FxOp65:     ; SUBRN  subtract, register - register
   SUBRN 5
FxOp66:     ; SUBRN  subtract, register - register
   SUBRN 6
FxOp67:     ; SUBRN  subtract, register - register
   SUBRN 7
FxOp68:     ; SUBRN  subtract, register - register
   SUBRN 8
FxOp69:     ; SUBRN  subtract, register - register
   SUBRN 9
FxOp6A:     ; SUBRN  subtract, register - register
   SUBRN 10
FxOp6B:     ; SUBRN  subtract, register - register
   SUBRN 11
FxOp6C:     ; SUBRN  subtract, register - register
   SUBRN 12
FxOp6D:     ; SUBRN  subtract, register - register
   SUBRN 13
FxOp6E:     ; SUBRN  subtract, register - register
   SUBRN 14
FxOp6F:     ; SUBRN  subtract, register - register
   FETCHPIPE
   mov eax,[esi]    ; Read Source
   mov ebx,ebp
   sub ebx,[SfxCPB]
   sub ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   inc ebp                   ; Increase program counter
   mov [edi],eax                        ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

%macro SBCRN 1  ; V
   FETCHPIPE
   mov eax,[esi]    ; Read Source
   mov ebx,[SfxR0+%1*4]
   cmp byte[SfxCarry],1
   sbb ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOp60A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 0
FxOp61A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 1
FxOp62A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 2
FxOp63A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 3
FxOp64A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 4
FxOp65A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 5
FxOp66A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 6
FxOp67A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 7
FxOp68A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 8
FxOp69A1:   ; SBCRN  subtract with carry, register - register
   SBCRN 9
FxOp6AA1:   ; SBCRN  subtract with carry, register - register
   SBCRN 10
FxOp6BA1:   ; SBCRN  subtract with carry, register - register
   SBCRN 11
FxOp6CA1:   ; SBCRN  subtract with carry, register - register
   SBCRN 12
FxOp6DA1:   ; SBCRN  subtract with carry, register - register
   SBCRN 13
FxOp6EA1:   ; SBCRN  subtract with carry, register - register
   SBCRN 14
FxOp6FA1:   ; SBCRN  subtract with carry, register - register
   mov eax,[esi]    ; Read Source
   mov ebx,ebp
   FETCHPIPE
   sub ebx,[SfxCPB]
   cmp byte[SfxCarry],1
   sbb ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

%macro SUBIRN 1 ; V
   mov eax,[esi]    ; Read Source
   FETCHPIPE
   sub ax,%1
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   inc ebp                ; Increase program counter
   mov [edi],eax      ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOp60A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 0
FxOp61A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 1
FxOp62A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 2
FxOp63A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 3
FxOp64A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 4
FxOp65A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 5
FxOp66A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 6
FxOp67A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 7
FxOp68A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 8
FxOp69A2:   ; SUBIRN subtract, register - immediate
   SUBIRN 9
FxOp6AA2:   ; SUBIRN subtract, register - immediate
   SUBIRN 10
FxOp6BA2:   ; SUBIRN subtract, register - immediate
   SUBIRN 11
FxOp6CA2:   ; SUBIRN subtract, register - immediate
   SUBIRN 12
FxOp6DA2:   ; SUBIRN subtract, register - immediate
   SUBIRN 13
FxOp6EA2:   ; SUBIRN subtract, register - immediate
   SUBIRN 14
FxOp6FA2:   ; SUBIRN subtract, register - immediate
   SUBIRN 15

%macro CMPRN 1  ; V
   mov eax,[esi]    ; Read Source
   mov ebx,[SfxR0+%1*4]
   FETCHPIPE
   sub ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   mov [SfxSignZero],eax
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret
%endmacro

FxOp60A3:   ; CMPRN  compare, register, register
   CMPRN 0
FxOp61A3:   ; CMPRN  compare, register, register
   CMPRN 1
FxOp62A3:   ; CMPRN  compare, register, register
   CMPRN 2
FxOp63A3:   ; CMPRN  compare, register, register
   CMPRN 3
FxOp64A3:   ; CMPRN  compare, register, register
   CMPRN 4
FxOp65A3:   ; CMPRN  compare, register, register
   CMPRN 5
FxOp66A3:   ; CMPRN  compare, register, register
   CMPRN 6
FxOp67A3:   ; CMPRN  compare, register, register
   CMPRN 7
FxOp68A3:   ; CMPRN  compare, register, register
   CMPRN 8
FxOp69A3:   ; CMPRN  compare, register, register
   CMPRN 9
FxOp6AA3:   ; CMPRN  compare, register, register
   CMPRN 10
FxOp6BA3:   ; CMPRN  compare, register, register
   CMPRN 11
FxOp6CA3:   ; CMPRN  compare, register, register
   CMPRN 12
FxOp6DA3:   ; CMPRN  compare, register, register
   CMPRN 13
FxOp6EA3:   ; CMPRN  compare, register, register
   CMPRN 14
FxOp6FA3:   ; CMPRN  compare, register, register
   FETCHPIPE
   mov eax,[esi]    ; Read Source
   mov ebx,ebp
   sub ebx,[SfxCPB]
   sub ax,bx
   seto byte[SfxOverflow]
   setc byte[SfxCarry]
   xor byte[SfxCarry],1
   mov [SfxSignZero],eax
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret

FxOp70:     ; MERGE  R7 as upper byte, R8 as lower byte (used for texture-mapping) */
            ; V
   xor eax,eax
   FETCHPIPE
   mov ah,byte [SfxR7+1]
   mov al,byte [SfxR8+1]
   inc ebp
   mov [edi],eax            ; Write Destination
   mov dword[SfxSignZero],0001h
   test eax,0F0F0h
   jz .nozero
   mov dword[SfxSignZero],0000h
.nozero
   test eax,08080h
   jz .nosign
   or dword [SfxSignZero],80000h
.nosign
   mov dword [SfxOverflow],1
   test ax,0c0c0h
   jnz .Overflow
   mov dword [SfxOverflow],0
.Overflow
   mov dword [SfxCarry],1
   test ax,0e0e0h
   jnz .Carry
   mov dword [SfxCarry],0
.Carry
   CLRFLAGS
   ret

%macro ANDRN 1  ; V
   mov eax,[esi]            ; Read Source
   mov ebx,[SfxR0+%1*4]             ; Read RN
   FETCHPIPE
   and eax,ebx
   inc ebp
   mov dword [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp71:     ; AND RN register & register
   ANDRN 1
FxOp72:     ; AND RN register & register
   ANDRN 2
FxOp73:     ; AND RN register & register
   ANDRN 3
FxOp74:     ; AND RN register & register
   ANDRN 4
FxOp75:     ; AND RN register & register
   ANDRN 5
FxOp76:     ; AND RN register & register
   ANDRN 6
FxOp77:     ; AND RN register & register
   ANDRN 7
FxOp78:     ; AND RN register & register
   ANDRN 8
FxOp79:     ; AND RN register & register
   ANDRN 9
FxOp7A:     ; AND RN register & register
   ANDRN 10
FxOp7B:     ; AND RN register & register
   ANDRN 11
FxOp7C:     ; AND RN register & register
   ANDRN 12
FxOp7D:     ; AND RN register & register
   ANDRN 13
FxOp7E:     ; AND RN register & register
   ANDRN 14
FxOp7F:     ; AND RN register & register
   FETCHPIPE
   mov eax,[esi]            ; Read Source
   mov ebx,ebp
   sub ebx,[SfxCPB]
   and eax,ebx
   inc ebp
   mov dword [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret

%macro BICRN 1  ; V
   mov ebx,[SfxR0+%1*4]             ; Read RN
   mov eax,[esi]            ; Read Source
   xor ebx,0FFFFh
   FETCHPIPE
   and eax,ebx
   inc ebp
   mov dword [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp71A1:   ; BIC RN register & ~register
   BICRN 1
FxOp72A1:   ; BIC RN register & ~register
   BICRN 2
FxOp73A1:   ; BIC RN register & ~register
   BICRN 3
FxOp74A1:   ; BIC RN register & ~register
   BICRN 4
FxOp75A1:   ; BIC RN register & ~register
   BICRN 5
FxOp76A1:   ; BIC RN register & ~register
   BICRN 6
FxOp77A1:   ; BIC RN register & ~register
   BICRN 7
FxOp78A1:   ; BIC RN register & ~register
   BICRN 8
FxOp79A1:   ; BIC RN register & ~register
   BICRN 9
FxOp7AA1:   ; BIC RN register & ~register
   BICRN 10
FxOp7BA1:   ; BIC RN register & ~register
   BICRN 11
FxOp7CA1:   ; BIC RN register & ~register
   BICRN 12
FxOp7DA1:   ; BIC RN register & ~register
   BICRN 13
FxOp7EA1:   ; BIC RN register & ~register
   BICRN 14
FxOp7FA1:   ; BIC RN register & ~register
   FETCHPIPE
   mov ebx,ebp
   sub ebx,[SfxCPB]
   mov eax,[esi]            ; Read Source
   xor ebx,0FFFFh
   and eax,ebx
   inc ebp
   mov dword [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret

%macro ANDIRN 1 ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   and eax,%1
   inc ebp
   mov dword [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp71A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 1
FxOp72A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 2
FxOp73A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 3
FxOp74A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 4
FxOp75A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 5
FxOp76A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 6
FxOp77A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 7
FxOp78A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 8
FxOp79A2:   ; ANDIRN and #n - register & immediate
   ANDIRN 9
FxOp7AA2:   ; ANDIRN and #n - register & immediate
   ANDIRN 10
FxOp7BA2:   ; ANDIRN and #n - register & immediate
   ANDIRN 11
FxOp7CA2:   ; ANDIRN and #n - register & immediate
   ANDIRN 12
FxOp7DA2:   ; ANDIRN and #n - register & immediate
   ANDIRN 13
FxOp7EA2:   ; ANDIRN and #n - register & immediate
   ANDIRN 14
FxOp7FA2:   ; ANDIRN and #n - register & immediate
   ANDIRN 15

%macro BICIRN 1 ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   and eax,%1
   inc ebp
   mov dword [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp71A3:   ; BICIRN register & ~immediate
   BICIRN 1 ^ 0FFFFh
FxOp72A3:   ; BICIRN register & ~immediate
   BICIRN 2 ^ 0FFFFh
FxOp73A3:   ; BICIRN register & ~immediate
   BICIRN 3 ^ 0FFFFh
FxOp74A3:   ; BICIRN register & ~immediate
   BICIRN 4 ^ 0FFFFh
FxOp75A3:   ; BICIRN register & ~immediate
   BICIRN 5 ^ 0FFFFh
FxOp76A3:   ; BICIRN register & ~immediate
   BICIRN 6 ^ 0FFFFh
FxOp77A3:   ; BICIRN register & ~immediate
   BICIRN 7 ^ 0FFFFh
FxOp78A3:   ; BICIRN register & ~immediate
   BICIRN 8 ^ 0FFFFh
FxOp79A3:   ; BICIRN register & ~immediate
   BICIRN 9 ^ 0FFFFh
FxOp7AA3:   ; BICIRN register & ~immediate
   BICIRN 10 ^ 0FFFFh
FxOp7BA3:   ; BICIRN register & ~immediate
   BICIRN 11 ^ 0FFFFh
FxOp7CA3:   ; BICIRN register & ~immediate
   BICIRN 12 ^ 0FFFFh
FxOp7DA3:   ; BICIRN register & ~immediate
   BICIRN 13 ^ 0FFFFh
FxOp7EA3:   ; BICIRN register & ~immediate
   BICIRN 14 ^ 0FFFFh
FxOp7FA3:   ; BICIRN register & ~immediate
   BICIRN 15 ^ 0FFFFh

%macro MULTRN 1 ; V
   mov al,byte [esi]     ; Read Source
   mov bl,byte [SfxR0+%1*4]      ; Read RN
   FETCHPIPE
   imul bl
   inc ebp
   and eax,0FFFFh
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp80:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 0 
FxOp81:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 1 
FxOp82:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 2 
FxOp83:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 3 
FxOp84:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 4 
FxOp85:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 5 
FxOp86:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 6 
FxOp87:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 7 
FxOp88:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 8 
FxOp89:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 9 
FxOp8A:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 10 
FxOp8B:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 11 
FxOp8C:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 12 
FxOp8D:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 13 
FxOp8E:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   MULTRN 14 
FxOp8F:     ; MULTRN 8 bit to 16 bit signed multiply, register * register
   FETCHPIPE
   mov ebx,ebp
   mov al,byte [esi]     ; Read Source
   sub ebx,[SfxCPB]
   imul bl
   inc ebp
   and eax,0FFFFh
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret

%macro UMULTRN 1        ; V
   mov al,byte [esi]     ; Read Source
   mov bl,byte [SfxR0+%1*4]      ; Read RN
   FETCHPIPE
   mul bl
   inc ebp
   and eax,0FFFFh
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp80A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 0
FxOp81A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 1
FxOp82A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 2
FxOp83A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 3
FxOp84A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 4
FxOp85A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 5
FxOp86A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 6
FxOp87A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 7
FxOp88A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 8
FxOp89A1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 9
FxOp8AA1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 10
FxOp8BA1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 11
FxOp8CA1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 12
FxOp8DA1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 13
FxOp8EA1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   UMULTRN 14
FxOp8FA1:   ; UMULRN 8 bit to 16 bit unsigned multiply, register * register
   FETCHPIPE
   mov ebx,ebp
   mov al,byte [esi]     ; Read Source
   sub ebx,[SfxCPB]
   mul bl
   inc ebp
   and eax,0FFFFh
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret

%macro MULTIRN 1        ; V
   mov al,byte [esi]     ; Read Source
   mov bl,%1                  ; Read RN
   FETCHPIPE
   imul bl
   inc ebp
   and eax,0FFFFh
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp80A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 0
FxOp81A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 1
FxOp82A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 2
FxOp83A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 3
FxOp84A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 4
FxOp85A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 5
FxOp86A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 6
FxOp87A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 7
FxOp88A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 8
FxOp89A2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 9
FxOp8AA2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 10
FxOp8BA2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 11
FxOp8CA2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 12
FxOp8DA2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 13
FxOp8EA2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 14
FxOp8FA2:   ; MULIRN 8 bit to 16 bit signed multiply, register * immediate
   MULTIRN 15

%macro UMULTIRN 1       ; V
   mov al,byte [esi]     ; Read Source
   mov bl,%1                  ; Read RN
   FETCHPIPE
   mul bl
   inc ebp
   and eax,0FFFFh
   mov [SfxSignZero],eax
   mov [edi],eax            ; Write Destination
   CLRFLAGS
   ret
%endmacro

FxOp80A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 0
FxOp81A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 1
FxOp82A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 2
FxOp83A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 3
FxOp84A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 4
FxOp85A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 5
FxOp86A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 6
FxOp87A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 7
FxOp88A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 8
FxOp89A3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 9
FxOp8AA3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 10
FxOp8BA3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 11
FxOp8CA3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 12
FxOp8DA3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 13
FxOp8EA3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 14
FxOp8FA3:   ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate
   UMULTIRN 15

FxOp90:     ; SBK    store word to last accessed RAM address    ; V
   mov ebx,[SfxLastRamAdr]   ; Load last ram address
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   mov [ebx],al         ; Store Word
   sub ebx,[SfxRAMMem]
   xor ebx,1
   add ebx,[SfxRAMMem]
   inc ebp                ; Increase program counter
   mov [ebx],ah         ; Store Word
   CLRFLAGS
   ret

%macro LINK 1   ; Verified.
   mov eax,ebp
   sub eax,[SfxCPB]
   add eax,%1
   FETCHPIPE
   mov word [SfxR11],ax
   CLRFLAGS
   inc ebp
   ret
%endmacro

FxOp91:     ; LINK#n R11 = R15 + immediate
   LINK 1
FxOp92:     ; LINK#n R11 = R15 + immediate
   LINK 2
FxOp93:     ; LINK#n R11 = R15 + immediate
   LINK 3
FxOp94:     ; LINK#n R11 = R15 + immediate
   LINK 4

FxOp95:     ; SEX    sign extend 8 bit to 16 bit        ; V
   movsx eax, byte [esi]     ; Read Source
   FETCHPIPE
   and eax,0FFFFh
   inc ebp
   mov [edi],eax            ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

FxOp96:     ; ASR    aritmethic shift right by one      ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   mov [SfxCarry],al
   and byte[SfxCarry],1
   sar ax,1                      ; logic shift right
   inc ebp                ; Increase program counter
   mov [edi],eax            ; Write Destination
   mov dword [SfxSignZero],eax
   CLRFLAGS
   ret

FxOp96A1:   ; DIV2   aritmethic shift right by one      ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   cmp ax,-1
   je .minusone
   mov [SfxCarry],al
   and byte[SfxCarry],1
   sar ax,1                      ; logic shift right
   inc ebp                ; Increase program counter
   mov [edi],eax            ; Write Destination
   mov dword [SfxSignZero],eax
   CLRFLAGS
   ret
.minusone
   mov byte[SfxCarry],1
   xor eax,eax
   inc ebp                ; Increase program counter
   mov [edi],eax            ; Write Destination
   mov dword [SfxSignZero],eax
   CLRFLAGS
   ret

FxOp97:     ; ROR    rotate right by one        ; V
   FETCHPIPE
   mov eax,[esi]            ; Read Source
   shr byte[SfxCarry],1
   rcr ax,1
   setc byte[SfxCarry]
   inc ebp                ; Increase program counter
   mov [edi],eax            ; Write Destination
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

%macro JMPRN 1  ; V
   FETCHPIPE
   mov eax,[SfxR0+%1*4]             ; Read RN
   mov ebp,[SfxCPB]
   add ebp,eax
   CLRFLAGS
   ret
%endmacro

FxOp98:     ; JMPRN  jump to address of register
   JMPRN 8
FxOp99:     ; JMPRN  jump to address of register
   JMPRN 9
FxOp9A:     ; JMPRN  jump to address of register
   JMPRN 10
FxOp9B:     ; JMPRN  jump to address of register
   JMPRN 11
FxOp9C:     ; JMPRN  jump to address of register
   JMPRN 12
FxOp9D:     ; JMPRN  jump to address of register
   JMPRN 13

%macro LJMPRN 1 ; V
   FETCHPIPE
   mov eax,[SfxR0+%1*4]
   and eax,07Fh
   mov byte[SfxPBR],al
;   mov byte[fxtrace+eax],1
   mov eax,[SfxMemTable+eax*4]
   mov [SfxCPB],eax
   mov ebp,eax
   add ebp,[esi]             ; Read RN
   mov dword [SfxCacheActive],0
   push ecx
   call FxOp02
   pop ecx
   dec ebp
   ret
%endmacro

FxOp98A1:   ; LJMPRN set program bank to source register and jump to address of register
   LJMPRN 8
FxOp99A1:   ; LJMPRN set program bank to source register and jump to address of register
   LJMPRN 9
FxOp9AA1:   ; LJMPRN set program bank to source register and jump to address of register
   LJMPRN 10
FxOp9BA1:   ; LJMPRN set program bank to source register and jump to address of register
   LJMPRN 11
FxOp9CA1:   ; LJMPRN set program bank to source register and jump to address of register
   LJMPRN 12
FxOp9DA1:   ; LJMPRN set program bank to source register and jump to address of register
   LJMPRN 13

FxOp9E:     ; LOB    set upper byte to zero (keep low byte) ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   and eax,0FFh
   inc ebp
   mov [edi],eax            ; Write Destination
   shl eax,8
   mov dword [SfxSignZero],eax
   CLRFLAGS
   ret

FxOp9F:     ; FMULT  16 bit to 32 bit signed multiplication, upper 16 bits only
            ; V
   mov eax,[esi]             ; Read Source
   mov ebx,[SfxR6]
   FETCHPIPE
   imul bx
   inc ebp
   and edx,0FFFFh
   mov [SfxSignZero],edx
   mov [edi],edx        ; Write Destination
   shr ax,15
   mov [SfxCarry],al
   CLRFLAGS
   ret

FxOp9FA1:   ; LMULT  16 bit to 32 bit signed multiplication     ; V
   mov eax,[esi]             ; Read Source
   mov ebx,[SfxR6]
   FETCHPIPE
   imul bx
   and edx,0FFFFh
   inc ebp
   mov [edi],edx        ; Write Destination
   mov [SfxR4],ax
   mov [SfxSignZero],edx
   shr ax,15
   mov [SfxCarry],al
   CLRFLAGS
   ret

%macro IBTRN 1  ; V
   movsx eax,byte[ebp]
   mov cl,[ebp+1]
   add ebp,2
   mov [SfxR0+%1*4],ax
   CLRFLAGS
   ret
%endmacro

FxOpA0:     ; IBTRN,#PP immediate byte transfer
   IBTRN 0
FxOpA1:     ; IBTRN,#PP immediate byte transfer
   IBTRN 1
FxOpA2:     ; IBTRN,#PP immediate byte transfer
   IBTRN 2
FxOpA3:     ; IBTRN,#PP immediate byte transfer
   IBTRN 3
FxOpA4:     ; IBTRN,#PP immediate byte transfer
   IBTRN 4
FxOpA5:     ; IBTRN,#PP immediate byte transfer
   IBTRN 5
FxOpA6:     ; IBTRN,#PP immediate byte transfer
   IBTRN 6
FxOpA7:     ; IBTRN,#PP immediate byte transfer
   IBTRN 7
FxOpA8:     ; IBTRN,#PP immediate byte transfer
   IBTRN 8
FxOpA9:     ; IBTRN,#PP immediate byte transfer
   IBTRN 9
FxOpAA:     ; IBTRN,#PP immediate byte transfer
   IBTRN 10
FxOpAB:     ; IBTRN,#PP immediate byte transfer
   IBTRN 11
FxOpAC:     ; IBTRN,#PP immediate byte transfer
   IBTRN 12
FxOpAD:     ; IBTRN,#PP immediate byte transfer
   IBTRN 13
FxOpAE:     ; IBTRN,#PP immediate byte transfer
   movsx eax,byte[ebp]
   mov cl,[ebp+1]
   add ebp,2
   mov [SfxR0+14*4],ax
   UpdateR14
   CLRFLAGS
   ret
FxOpAF:     ; IBTRN,#PP immediate byte transfer
   movsx eax,byte[ebp]
   mov cl,[ebp+1]
   and eax,0FFFFh
   mov ebp,[SfxCPB]
   add ebp,eax
   CLRFLAGS
   ret

%macro LMSRN 1  ; Verified.
   xor eax,eax
   mov al,[ebp]
   add eax,eax
   inc ebp
   add eax,[SfxRAMMem]
   mov cl,[ebp]
   mov dword [SfxLastRamAdr],eax
   mov ebx,[eax]              ; Read word from ram
   inc ebp
   mov [SfxR0+%1*4],bx              ; Write data
   CLRFLAGS
   ret
%endmacro

FxOpA0A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 0
FxOpA1A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 1
FxOpA2A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 2
FxOpA3A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 3
FxOpA4A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 4
FxOpA5A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 5
FxOpA6A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 6
FxOpA7A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 7
FxOpA8A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 8
FxOpA9A1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 9
FxOpAAA1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 10
FxOpABA1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 11
FxOpACA1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 12
FxOpADA1:   ; LMS rn,(yy)  load word from RAM (short address)
   LMSRN 13
FxOpAEA1:   ; LMS rn,(yy)  load word from RAM (short address)
   xor eax,eax
   mov al,[ebp]
   add eax,eax
   inc ebp
   add eax,[SfxRAMMem]
   mov cl,[ebp]
   mov dword [SfxLastRamAdr],eax
   mov ebx,[eax]              ; Read word from ram
   inc ebp
   mov [SfxR0+14*4],bx              ; Write data
   UpdateR14
   CLRFLAGS
   ret
FxOpAFA1:   ; LMS rn,(yy)  load word from RAM (short address)
   xor eax,eax
   mov al,[ebp]
   add eax,eax
   inc ebp
   add eax,[SfxRAMMem]
   mov cl,[ebp]
   mov dword [SfxLastRamAdr],eax
   mov ebx,[eax]              ; Read word from ram
   and ebx,0FFFFh
   mov ebp,[SfxCPB]
   add ebp,ebx
   CLRFLAGS
   ret

%macro SMSRN 1  ; Verified.
   xor eax,eax
   mov al,[ebp]
   inc ebp
   add eax,eax
   mov cl,[ebp]
   add eax,[SfxRAMMem]
   mov ebx,[SfxR0+%1*4]              ; Read data
   mov dword [SfxLastRamAdr],eax
   inc ebp
   mov [eax],bx              ; Write word to ram
   CLRFLAGS
   ret
%endmacro

FxOpA0A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 0
FxOpA1A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 1
FxOpA2A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 2
FxOpA3A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 3
FxOpA4A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 4
FxOpA5A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 5
FxOpA6A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 6
FxOpA7A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 7
FxOpA8A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 8
FxOpA9A2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 9
FxOpAAA2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 10
FxOpABA2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 11
FxOpACA2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 12
FxOpADA2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 13
FxOpAEA2:   ; SMS (yy),rn  store word in RAM (short address)
   SMSRN 14
FxOpAFA2:   ; SMS (yy),rn  store word in RAM (short address)
   xor eax,eax
   mov ebx,ebp
   sub ebx,[SfxCPB]
   mov al,[ebp]
   inc ebp
   add eax,eax
   FETCHPIPE
   add eax,[SfxRAMMem]
   mov dword [SfxLastRamAdr],eax
   inc ebp
   mov [eax],bx              ; Write word to ram
   CLRFLAGS
   ret

%macro FROMRN 1 ; V
   FETCHPIPE
   mov esi,SfxR0+%1*4
   inc ebp                ; Increase program counter
   call [FxTable+ecx*4]
   mov esi,SfxR0
   ret
%endmacro

FxOpB0:     ; FROM rn   set source register
   FROMRN 0
FxOpB1:     ; FROM rn   set source register
   FROMRN 1
FxOpB2:     ; FROM rn   set source register
   FROMRN 2
FxOpB3:     ; FROM rn   set source register
   FROMRN 3
FxOpB4:     ; FROM rn   set source register
   FROMRN 4
FxOpB5:     ; FROM rn   set source register
   FROMRN 5
FxOpB6:     ; FROM rn   set source register
   FROMRN 6
FxOpB7:     ; FROM rn   set source register
   FROMRN 7
FxOpB8:     ; FROM rn   set source register
   FROMRN 8
FxOpB9:     ; FROM rn   set source register
   FROMRN 9
FxOpBA:     ; FROM rn   set source register
   FROMRN 10
FxOpBB:     ; FROM rn   set source register
   FROMRN 11
FxOpBC:     ; FROM rn   set source register
   FROMRN 12
FxOpBD:     ; FROM rn   set source register
   FROMRN 13
FxOpBE:     ; FROM rn   set source register
   FROMRN 14
FxOpBF:     ; FROM rn   set source register
   FETCHPIPE
   mov esi,SfxR0+15*4
   inc ebp                ; Increase program counter
   mov eax,ebp
   sub eax,[SfxCPB]
   mov [SfxR15],eax
   call [FxTableb+ecx*4]
   mov esi,SfxR0
   ret

FxOpC0:     ; HIB       move high-byte to low-byte      ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   and eax,0FF00h
   mov dword [SfxSignZero],eax
   shr eax,8
   inc ebp
   mov [edi],eax
   CLRFLAGS
   ret

%macro ORRN 1   ; V
   mov eax,[esi]            ; Read Source
   mov ebx,[SfxR0+%1*4]             ; Read
   FETCHPIPE
   or eax,ebx
   inc ebp
   mov [edi],eax            ; Write DREG
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOpC1:     ; OR rn     or rn
   ORRN 1
FxOpC2:     ; OR rn     or rn
   ORRN 2
FxOpC3:     ; OR rn     or rn
   ORRN 3
FxOpC4:     ; OR rn     or rn
   ORRN 4
FxOpC5:     ; OR rn     or rn
   ORRN 5
FxOpC6:     ; OR rn     or rn
   ORRN 6
FxOpC7:     ; OR rn     or rn
   ORRN 7
FxOpC8:     ; OR rn     or rn
   ORRN 8
FxOpC9:     ; OR rn     or rn
   ORRN 9
FxOpCA:     ; OR rn     or rn
   ORRN 10
FxOpCB:     ; OR rn     or rn
   ORRN 11
FxOpCC:     ; OR rn     or rn
   ORRN 12
FxOpCD:     ; OR rn     or rn
   ORRN 13
FxOpCE:     ; OR rn     or rn
   ORRN 14
FxOpCF:     ; OR rn     or rn
   mov eax,[esi]            ; Read Source
   mov ebx,ebp
   FETCHPIPE
   sub ebx,[SfxCPB]
   or eax,ebx
   inc ebp
   mov [edi],eax            ; Write DREG
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

%macro XORRN 1  ; V
   mov eax,[esi]            ; Read Source
   mov ebx,[SfxR0+%1*4]             ; Read
   FETCHPIPE
   xor eax,ebx
   inc ebp
   mov [edi],eax            ; Write DREG
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOpC1A1:   ; XOR rn    xor rn
   XORRN 1
FxOpC2A1:   ; XOR rn    xor rn
   XORRN 2
FxOpC3A1:   ; XOR rn    xor rn
   XORRN 3
FxOpC4A1:   ; XOR rn    xor rn
   XORRN 4
FxOpC5A1:   ; XOR rn    xor rn
   XORRN 5
FxOpC6A1:   ; XOR rn    xor rn
   XORRN 6
FxOpC7A1:   ; XOR rn    xor rn
   XORRN 7
FxOpC8A1:   ; XOR rn    xor rn
   XORRN 8
FxOpC9A1:   ; XOR rn    xor rn
   XORRN 9
FxOpCAA1:   ; XOR rn    xor rn
   XORRN 10
FxOpCBA1:   ; XOR rn    xor rn
   XORRN 11
FxOpCCA1:   ; XOR rn    xor rn
   XORRN 12
FxOpCDA1:   ; XOR rn    xor rn
   XORRN 13
FxOpCEA1:   ; XOR rn    xor rn
   XORRN 14
FxOpCFA1:   ; XOR rn    xor rn
   FETCHPIPE
   mov eax,[esi]            ; Read Source
   mov ebx,ebp
   sub ebx,[SfxCPB]
   xor eax,ebx
   inc ebp
   mov [edi],eax            ; Write DREG
   mov [SfxSignZero],eax
   CLRFLAGS
   ret

%macro ORI 1    ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   or eax,%1
   inc ebp
   mov [edi],eax            ; Write DREG
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOpC1A2:   ; OR #n     OR #n
   ORI 1
FxOpC2A2:   ; OR #n     OR #n
   ORI 2
FxOpC3A2:   ; OR #n     OR #n
   ORI 3
FxOpC4A2:   ; OR #n     OR #n
   ORI 4
FxOpC5A2:   ; OR #n     OR #n
   ORI 5
FxOpC6A2:   ; OR #n     OR #n
   ORI 6
FxOpC7A2:   ; OR #n     OR #n
   ORI 7
FxOpC8A2:   ; OR #n     OR #n
   ORI 8
FxOpC9A2:   ; OR #n     OR #n
   ORI 9
FxOpCAA2:   ; OR #n     OR #n
   ORI 10
FxOpCBA2:   ; OR #n     OR #n
   ORI 11
FxOpCCA2:   ; OR #n     OR #n
   ORI 12
FxOpCDA2:   ; OR #n     OR #n
   ORI 13
FxOpCEA2:   ; OR #n     OR #n
   ORI 14
FxOpCFA2:   ; OR #n     OR #n
   ORI 15

%macro XORI 1   ; V
   mov eax,[esi]            ; Read Source
   FETCHPIPE
   xor eax,%1
   inc ebp
   mov [edi],eax            ; Write DREG
   mov [SfxSignZero],eax
   CLRFLAGS
   ret
%endmacro

FxOpC1A3:   ; XOR #n    xor #n
   XORI 1
FxOpC2A3:   ; XOR #n    xor #n
   XORI 2
FxOpC3A3:   ; XOR #n    xor #n
   XORI 3
FxOpC4A3:   ; XOR #n    xor #n
   XORI 4
FxOpC5A3:   ; XOR #n    xor #n
   XORI 5
FxOpC6A3:   ; XOR #n    xor #n
   XORI 6
FxOpC7A3:   ; XOR #n    xor #n
   XORI 7
FxOpC8A3:   ; XOR #n    xor #n
   XORI 8
FxOpC9A3:   ; XOR #n    xor #n
   XORI 9
FxOpCAA3:   ; XOR #n    xor #n
   XORI 10
FxOpCBA3:   ; XOR #n    xor #n
   XORI 11
FxOpCCA3:   ; XOR #n    xor #n
   XORI 12
FxOpCDA3:   ; XOR #n    xor #n
   XORI 13
FxOpCEA3:   ; XOR #n    xor #n
   XORI 14
FxOpCFA3:   ; XOR #n    xor #n
   XORI 15

%macro INCRN 1  ; Verified
   inc word[SfxR0+%1*4]
   FETCHPIPE
   mov eax,[SfxR0+%1*4]            ; Read Source
   mov [SfxSignZero],eax
   CLRFLAGS
   inc ebp
   ret
%endmacro

FxOpD0:     ; INC rn    increase by one
   INCRN 0
FxOpD1:     ; INC rn    increase by one
   INCRN 1
FxOpD2:     ; INC rn    increase by one
   INCRN 2
FxOpD3:     ; INC rn    increase by one
   INCRN 3
FxOpD4:     ; INC rn    increase by one
   INCRN 4
FxOpD5:     ; INC rn    increase by one
   INCRN 5
FxOpD6:     ; INC rn    increase by one
   INCRN 6
FxOpD7:     ; INC rn    increase by one
   INCRN 7
FxOpD8:     ; INC rn    increase by one
   INCRN 8
FxOpD9:     ; INC rn    increase by one
   INCRN 9
FxOpDA:     ; INC rn    increase by one
   INCRN 10
FxOpDB:     ; INC rn    increase by one
   INCRN 11
FxOpDC:     ; INC rn    increase by one
   INCRN 12
FxOpDD:     ; INC rn    increase by one
   INCRN 13
FxOpDE:     ; INC rn    increase by one
   FETCHPIPE
   mov eax,[SfxR0+14*4]            ; Read Source
   inc ax
   mov [SfxR0+14*4],eax
   mov [SfxSignZero],eax
   CLRFLAGS
   inc ebp
   UpdateR14
   ret

FxOpDF:     ; GETC      transfer ROM buffer to color register
   mov eax,[SfxRomBuffer]
   FETCHPIPE
   mov eax,[eax]
   test byte[SfxPOR],04h
   jz .nohighnibble
   mov bl,al
   shr bl,4
   and al,0F0h
   or al,bl
.nohighnibble
   test byte[SfxPOR],08h
   jnz .preserveupper
   mov [SfxCOLR],al
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret
.preserveupper
   mov bl,[SfxCOLR]
   and al,0Fh
   and bl,0F0h
   or al,bl
   mov [SfxCOLR],al
   CLRFLAGS
   inc ebp                ; Increase program counter
   ret

FxOpDFA2    ; RAMB      set current RAM bank    ; Verified
   mov eax,[esi]            ; Read Source
   mov ebx,[SfxnRamBanks]
   FETCHPIPE
   dec ebx
   and eax,ebx
   mov dword [SfxRAMBR],eax
   shl eax,16
   add eax,[sfxramdata]
   mov dword [SfxRAMMem],eax
   CLRFLAGS
   inc ebp
   ret

FxOpDFA3    ; ROMB      set current ROM bank    ; Verified
   mov eax,[esi]            ; Read Source
   and eax,07Fh
   FETCHPIPE
   mov dword [SfxROMBR],eax
   mov eax,[SfxMemTable+eax*4]
   mov [SfxCROM],eax
   CLRFLAGS
   inc ebp
   ret

%macro DECRN 1  ; Verified
   dec word[SfxR0+%1*4]
   FETCHPIPE
   mov eax,[SfxR0+%1*4]            ; Read Source
   mov [SfxR0+%1*4],eax
   mov [SfxSignZero],eax
   CLRFLAGS
   inc ebp
   ret
%endmacro

FxOpE0:     ; DEC rn    decrement by one
   DECRN 0
FxOpE1:     ; DEC rn    decrement by one
   DECRN 1
FxOpE2:     ; DEC rn    decrement by one
   DECRN 2
FxOpE3:     ; DEC rn    decrement by one
   DECRN 3
FxOpE4:     ; DEC rn    decrement by one
   DECRN 4
FxOpE5:     ; DEC rn    decrement by one
   DECRN 5
FxOpE6:     ; DEC rn    decrement by one
   DECRN 6
FxOpE7:     ; DEC rn    decrement by one
   DECRN 7
FxOpE8:     ; DEC rn    decrement by one
   DECRN 8
FxOpE9:     ; DEC rn    decrement by one
   DECRN 9
FxOpEA:     ; DEC rn    decrement by one
   DECRN 10
FxOpEB:     ; DEC rn    decrement by one
   DECRN 11
FxOpEC:     ; DEC rn    decrement by one
   DECRN 12
FxOpED:     ; DEC rn    decrement by one
   DECRN 13
FxOpEE:     ; DEC rn    decrement by one
   dec word[SfxR0+14*4]
   FETCHPIPE
   mov eax,[SfxR0+14*4]            ; Read Source
   mov [SfxSignZero],eax
   UpdateR14
   CLRFLAGS
   inc ebp
   ret

FxOpEF:     ; getb      get byte from ROM at address R14        ; V
   FETCHPIPE
   mov eax,[SfxRomBuffer]
   inc ebp
   mov eax,[eax]
   and eax,0FFh
   cmp edi,SfxR15
   je .nor15
   mov [edi],eax            ; Write DREG
   CLRFLAGS
   ret
.nor15
   mov eax,ebp
   sub eax,[SfxCPB]
   mov [SfxR15],eax
   CLRFLAGS
   ret

FxOpEFA1:   ; getbh     get high-byte from ROM at address R14   ; V
   mov eax,[esi]            ; Read Source
   mov ebx,[SfxRomBuffer]
   and eax,0FFh
   FETCHPIPE
   mov ah,[ebx]
   inc ebp
   mov [edi],eax            ; Write DREG
   CLRFLAGS
   ret

FxOpEFA2:   ; getbl     get low-byte from ROM at address R14    ; V
   mov eax,[esi]            ; Read Source
   mov ebx,[SfxRomBuffer]
   and eax,0FF00h
   FETCHPIPE
   mov al,[ebx]
   inc ebp
   mov [edi],eax            ; Write DREG
   CLRFLAGS
   ret

FxOpEFA3:   ; getbs     get sign extended byte from ROM at address R14  ; V
   mov ebx,[SfxRomBuffer]
   FETCHPIPE
   movsx eax,byte[ebx]
   inc ebp
   mov [edi],ax            ; Write DREG
   CLRFLAGS
   ret

%macro IWTRN 1  ; aka LEA       ; Verified.
   mov eax,[ebp]
   mov cl,[ebp+2]
   and eax,0FFFFh
   add ebp,3
   mov [SfxR0+%1*4],eax
   CLRFLAGS
   ret
%endmacro

FxOpF0:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 0
FxOpF1:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 1
FxOpF2:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 2
FxOpF3:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 3
FxOpF4:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 4
FxOpF5:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 5
FxOpF6:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 6
FxOpF7:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 7
FxOpF8:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 8
FxOpF9:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 9
FxOpFA:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 10
FxOpFB:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 11
FxOpFC:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 12
FxOpFD:     ; IWT RN,#xx   immediate word transfer to register
   IWTRN 13
FxOpFE:     ; IWT RN,#xx   immediate word transfer to register
   mov eax,[ebp]
   mov cl,[ebp+2]
   and eax,0FFFFh
   add ebp,3
   mov [SfxR0+14*4],eax
   UpdateR14
   CLRFLAGS
   ret
FxOpFF:     ; IWT RN,#xx   immediate word transfer to register
   mov eax,[ebp]
   mov cl,[ebp+2]
   and eax,0FFFFh
   mov ebp,[SfxCPB]
   add ebp,eax
   CLRFLAGS
   ret

%macro LMRN 1   ; Verified!
   xor eax,eax
   mov cl,[ebp+2]
   mov ax,[ebp]
   mov ebx,[SfxRAMMem]
   mov [SfxLastRamAdr],eax
   add [SfxLastRamAdr],ebx
   mov dl,[eax+ebx]
   xor eax,1
   add ebp,3
   mov dh,[eax+ebx]
   mov word [SfxR0+%1*4],dx         ; Store Word
   CLRFLAGS
   ret
%endmacro

FxOpF0A1:   ; LM RN,(XX)   load word from RAM
   LMRN 0
FxOpF1A1:   ; LM RN,(XX)   load word from RAM
   LMRN 1
FxOpF2A1:   ; LM RN,(XX)   load word from RAM
   LMRN 2
FxOpF3A1:   ; LM RN,(XX)   load word from RAM
   LMRN 3
FxOpF4A1:   ; LM RN,(XX)   load word from RAM
   LMRN 4
FxOpF5A1:   ; LM RN,(XX)   load word from RAM
   LMRN 5
FxOpF6A1:   ; LM RN,(XX)   load word from RAM
   LMRN 6
FxOpF7A1:   ; LM RN,(XX)   load word from RAM
   LMRN 7
FxOpF8A1:   ; LM RN,(XX)   load word from RAM
   LMRN 8
FxOpF9A1:   ; LM RN,(XX)   load word from RAM
   LMRN 9
FxOpFAA1:   ; LM RN,(XX)   load word from RAM
   LMRN 10
FxOpFBA1:   ; LM RN,(XX)   load word from RAM
   LMRN 11
FxOpFCA1:   ; LM RN,(XX)   load word from RAM
   LMRN 12
FxOpFDA1:   ; LM RN,(XX)   load word from RAM
   LMRN 13
FxOpFEA1:   ; LM RN,(XX)   load word from RAM
   xor eax,eax
   mov cl,[ebp+2]
   mov ax,[ebp]
   mov ebx,[SfxRAMMem]
   mov [SfxLastRamAdr],eax
   add [SfxLastRamAdr],ebx
   mov dl,[eax+ebx]
   xor eax,1
   add ebp,3
   mov dh,[eax+ebx]
   mov word [SfxR0+14*4],dx         ; Store Word
   UpdateR14
   CLRFLAGS
   ret
FxOpFFA1:   ; LM RN,(XX)   load word from RAM
   FETCHPIPE
   mov eax,ecx
   inc ebp
   FETCHPIPE
   inc ebp
   mov ah,cl
   FETCHPIPE
   mov ebx,[SfxRAMMem]
   mov [SfxLastRamAdr],eax
   add [SfxLastRamAdr],ebx
   mov dl,[eax+ebx]
   xor eax,1
   mov dh,[eax+ebx]
   and edx,0FFFFh
   mov ebp,[SfxCPB]
   add ebp,edx
   CLRFLAGS
   ret

%macro SMRN 1   ; Verified
   mov ebx,[SfxR0+%1*4]
   mov eax,[ebp]
   mov cl,[ebp+2]
   and eax,0FFFFh
   mov dx,bx
   mov ebx,[SfxRAMMem]
   mov [SfxLastRamAdr],eax
   add [SfxLastRamAdr],ebx
   mov [eax+ebx],dl
   xor eax,1
   add ebp,3
   mov [eax+ebx],dh
   CLRFLAGS
   ret
%endmacro

FxOpF0A2:   ; SM (XX),RN   store word in RAM
   SMRN 0
FxOpF1A2:   ; SM (XX),RN   store word in RAM
   SMRN 1
FxOpF2A2:   ; SM (XX),RN   store word in RAM
   SMRN 2
FxOpF3A2:   ; SM (XX),RN   store word in RAM
   SMRN 3
FxOpF4A2:   ; SM (XX),RN   store word in RAM
   SMRN 4
FxOpF5A2:   ; SM (XX),RN   store word in RAM
   SMRN 5
FxOpF6A2:   ; SM (XX),RN   store word in RAM
   SMRN 6
FxOpF7A2:   ; SM (XX),RN   store word in RAM
   SMRN 7
FxOpF8A2:   ; SM (XX),RN   store word in RAM
   SMRN 8
FxOpF9A2:   ; SM (XX),RN   store word in RAM
   SMRN 9
FxOpFAA2:   ; SM (XX),RN   store word in RAM
   SMRN 10
FxOpFBA2:   ; SM (XX),RN   store word in RAM
   SMRN 11
FxOpFCA2:   ; SM (XX),RN   store word in RAM
   SMRN 12
FxOpFDA2:   ; SM (XX),RN   store word in RAM
   SMRN 13
FxOpFEA2:   ; SM (XX),RN   store word in RAM
   SMRN 14
FxOpFFA2:   ; SM (XX),RN   store word in RAM
   FETCHPIPE
   mov ebx,ebp
   sub ebx,[SfxCPB]
   mov eax,ecx
   inc ebp
   FETCHPIPE
   inc ebp
   mov ah,cl
   FETCHPIPE
   mov dx,bx
   mov ebx,[SfxRAMMem]
   mov [SfxLastRamAdr],eax
   add [SfxLastRamAdr],ebx
   mov [eax+ebx],dl
   xor eax,1
   inc ebp
   mov [eax+ebx],dh
   CLRFLAGS
   ret

ALIGN32
NumberOfOpcodes dd 0    ; Number of opcodes to execute
NumberOfOpcodesBU dd 0  ; Number of opcodes to execute backup value
sfxwarningb db 0

%macro PackEsiEdi 0
   mov eax,[SfxSREG]
   shl eax,2
   add eax,SfxR0
   mov esi,eax
   mov eax,[SfxDREG]
   shl eax,2
   add eax,SfxR0
   mov edi,eax
   mov eax,[SfxRAMBR]
   shl eax,16
   add eax,[sfxramdata]
   mov dword [SfxRAMMem],eax
%endmacro

%macro UnPackEsiEdi 0
   mov eax,esi
   sub eax,SfxR0
   shr eax,2
   mov [SfxSREG],eax
   mov eax,edi
   sub eax,SfxR0
   shr eax,2
   mov [SfxDREG],eax
%endmacro

MainLoop:
   mov eax,[SfxPBR]
   and eax,0FFh
   mov byte[fxtrace+eax],1
   mov ebp,[SfxCPB]
   add ebp,[SfxR15]
   xor ecx,ecx
   mov cl,[SfxPIPE]
   mov ch,[SfxSFR+1]
   and ch,03h
   ; pack esi/edi
   PackEsiEdi
   jmp [FxTabled+ecx*4]
   jmp .LoopAgain
ALIGN16
.LoopAgain
   call [FxTable+ecx*4]
   dec dword [NumberOfOpcodes]
   jnz .LoopAgain
.EndLoop
FXEndLoop:
   sub ebp,[SfxCPB]
   mov [SfxR15],ebp
   mov [SfxPIPE],cl
   and byte[SfxSFR+1],0FFh-03h
   or [SfxSFR+1],ch
   UnPackEsiEdi
   ret

fxtrace db 0; times 65536 db 0

