home *** CD-ROM | disk | FTP | other *** search
- ;; dis.asm -- TI-86 Z80 disassembler by Dan Eble
- ;; Last modified 1997-8-7
- ;;
- ;; Do absolutely anything you want with this.
- ;;
- ;; May those who rip extensive amounts for
- ;; exclusive personal gain be tormented
- ;; accordingly by a guilty conscience.
- ;;
- ;; Have a nice day. <eble.2@osu.edu>
- ;;
-
- #INCLUDE "TI86ASM.INC"
-
- _busyOn .equ $4AAD
- _busyOff .equ $4AB1
-
- FlagBitChar .equ 0
- FlagMaskChar .equ 00000001b
-
- ;-----------------------------------------------------------------
- ; Temporary Data Equates
- ;-----------------------------------------------------------------
- __clrLCD .equ ProgramEnd+$00 ; 4-byte call
- __clrScrn .equ ProgramEnd+$04 ; 4-byte call
- __putmap .equ ProgramEnd+$08 ; 4-byte call
- __putc .equ ProgramEnd+$0C ; 4-byte call
- __puts .equ ProgramEnd+$10 ; 4-byte call
- __vputmap .equ ProgramEnd+$14 ; 4-byte call
- __vputs .equ ProgramEnd+$18 ; 4-byte call
- __busyOn .equ ProgramEnd+$1C ; 4-byte call
- __busyOff .equ ProgramEnd+$20 ; 4-byte call
- __getkey .equ ProgramEnd+$24 ; 4-byte call
- DisAddrBottom .equ ProgramEnd+$28 ;W:
- Port5Save .equ ProgramEnd+$2A ;B:
- Port6Save .equ ProgramEnd+$2B ;B:
- DD_FD_flags .equ ProgramEnd+$2C ;B:
- pArg1 .equ ProgramEnd+$2D ;W:
- pArg2 .equ ProgramEnd+$2F ;W:
- pArg3 .equ ProgramEnd+$31 ;W:
-
- ;-----------------------------------------------------------------
-
- .org _asm_exec_ram
-
- in a,(5)
- ld (Port5Save),a
- in a,(6)
- ld (Port6Save),a
-
- ld a,0 ; set up font pointer for menu font
- ld ($D2F0),a
- ld hl,SmallFont
- ld ($D2F1),hl
- set 1,(IY+$23) ; use user font!
-
- res 3,(iy+5) ; display black on white
- res 1,(iy+5) ; print only six rows of each character
-
- call SetUpCalls
-
- call DisScreen
-
- KeyLoop:
- call __getkey
-
- cp kRight
- jr nz,not_kRight
- ld hl,(DisAddrTop)
- inc hl
- ld (DisAddrTop),hl
- call DisScreen
- jr KeyLoop
- not_kRight:
- cp kLeft
- jr nz,not_kLeft
- is_kLeft:
- ld hl,(DisAddrTop)
- dec hl
- ld (DisAddrTop),hl
- call DisScreen
- jr KeyLoop
- not_kLeft:
- cp kF2 ; page up
- jr nz,not_kF2
- ld de,$FFF0 ; FFF0h = -10h
- ld hl,(DisAddrTop)
- add hl,de
- ld (DisAddrTop),hl
- call DisScreen
- jr KeyLoop
- not_kF2:
- cp kF1 ; page down
- jr nz,not_kF1
- ld hl,(DisAddrBottom) ; disassemble next page
- ld (DisAddrTop),hl
- call DisScreen
- jr KeyLoop
- not_kF1:
- cp kF3 ; toggle hex/char data display
- jr nz,not_kF3
- ld a,(DisFlags)
- xor FlagMaskChar
- ld (DisFlags),a
- call DisScreen
- jr KeyLoop
- not_kF3:
- cp kDecPnt ; goto specific address
- jr nz,not_kDecPnt
- call InputHex
- jr nc,kF5_no_entry
- ld (DisAddrTop),hl
- kF5_no_entry:
- call DisScreen
- jr KeyLoop
- not_kDecPnt:
- cp kF4
- jr nz,not_kF4
- in a,(5)
- ld b,a
- inc a
- and $0F
- ld c,a
- ld a,b
- and $F0
- or c
- out (5),a
- call DisScreen
- jp KeyLoop
- not_kF4:
- cp kF5 ; increment RAM page
- jr nz,not_kF5
- in a,(6)
- ld b,a
- inc a
- and $07
- ld c,a
- ld a,b
- and $F8
- or c
- out (6),a
- call DisScreen
- jp KeyLoop
- not_kF5:
- cp kUp
- jr nz,not_kUp
- jp is_kLeft
- jp KeyLoop
- not_kUp:
- cp kDown
- jr nz,not_kDown
- ld hl, $0000 ; put cursor in top left
- ld (_penCol),hl
- ld de,(DisAddrTop) ; disassemble top line to advance DE
- call DisLine
- ld (DisAddrTop),de ; store the new top line address
- call ScrollUp ; scroll screen up
- ld hl, $3000 ; put cursor on bottom line, left
- ld (_penCol),hl
- ld de,(DisAddrBottom) ; disassemble new bottom line to advance DE
- call DisLine
- ld (DisAddrBottom),de ; store new bottom
- jp KeyLoop
- not_kDown:
- cp kExit
- jp nz,KeyLoop
-
- ld a,(Port6Save)
- out (6),a
- ld a,(Port5Save)
- out (5),a
-
- res 1,(IY+$23) ; don't use user font anymore!
- call __clrScrn
- ret ; done with program
-
- ;-------------------------------------------------------------------
- ; Input a 4-digit hexadecimal value on the bottom line of the screen
- ; If Carry Flag is set, HL contains a useful value
- ; A, BC, and DE can be modified
- ;-------------------------------------------------------------------
-
- InputHex:
- ld a,7
- ld (_curRow),a ; go to bottom row of screen
- sub a
- ld (IH_InputLen),a ; so far no keys have been pressed
- IH_Loop:
- call __getkey
- cp kLeft ; Left = backspace
- jr z,IH_kLeft
- cp kEnter ; Enter = done
- jr z,IH_kEnter
- cp kClear ; Clear = never mind
- jr z,IH_kClear
- sub $1C ; if code < $1C, it's not in table
- jr c,IH_Loop
- cp $2D-$1C+1 ; if code > $2D, it's not in table
- jr nc,IH_Loop
-
- ld hl,XlateTable
- ld d,0
- ld e,a
- add hl,de
- ld a,(hl)
- or a ; if table[code] = 0, not valid
- jr z,IH_Loop
-
- push af
- ld a,(IH_InputLen)
- ld e,a ; (d = 0 from above)
- ld (_curCol),a
- inc a
- cp 5 ; 4 character maximum
- jr nc,IH_TooLong
- ld (IH_InputLen),a
- ld hl,IH_InputStr
- add hl,de
- pop af
- ld (hl),a
- call __putc ; print character
- jr IH_Loop
- IH_TooLong:
- pop af
- jr IH_Loop
-
- IH_kClear:
- or a ; this clears CF
- ret
-
- IH_kLeft:
- ld a,(IH_InputLen)
- or a
- jr z,IH_Loop ; only backspace if there are chars
- dec a
- ld (_curCol),a
- ld (IH_InputLen),a
- ld a,' '
- call __putc
- jr IH_Loop
-
- IH_kEnter:
- ld a,(IH_InputLen) ; enter invalid if no chars
- or a
- jr z,IH_Loop
-
- ld b,a ; B = length of input
- ld hl,IH_InputStr ; HL -> input
- ld de,0 ; DE will receive value
- IH_ValueLoop:
- ex de,hl ; multiply DE by 16
- add hl,hl
- add hl,hl
- add hl,hl
- add hl,hl
- ex de,hl
- ld a,(hl)
- sub '0'
- cp $0A
- jr c,IH_0to9
- sub 'A'-'9'-1
- IH_0to9:
- or e
- ld e,a
- inc hl
- djnz IH_ValueLoop
- ex de,hl ; put value in hl
- scf ; set CF (input is valid)
- ret
-
- IH_InputLen: .db 0
- IH_InputStr: .db 0,0,0,0
-
- XlateTable:
- ; ASCII ; scancode : key
- .db "0" ; 1C : k0
- .db "1" ; 1D : k1
- .db "2" ; 1E : k2
- .db "3" ; 1F : k3
- .db "4" ; 20 : k4
- .db "5" ; 21 : k5
- .db "6" ; 22 : k6
- .db "7" ; 23 : k7
- .db "8" ; 24 : k8
- .db "9" ; 25 : k9
- .db 0 ; 26 : kEE
- .db 0 ; 27 : kSpace
- .db "A" ; 28 : kCapA
- .db "B" ; 29 : kCapB
- .db "C" ; 2A : kCapC
- .db "D" ; 2B : kCapD
- .db "E" ; 2C : kCapE
- .db "F" ; 2D : kCapF
-
- ;------------------------------------------------------
- ; Clear Screen and Disassemble
- ; input: (DisAddrTop) = Disassembly address
- ; modifies A, HL, BC, DE, (DisAddrBottom)
- ;------------------------------------------------------
-
- DisScreen:
- call __clrLCD
-
- call __busyOn
-
- ld hl,$1007 ; print ROM page
- ld (_curRow),hl
- in a,(5)
- ld hl,ByteStr
- call PrintByte
- inc hl
- ld a,(hl)
- call __putmap
-
- ld hl,$1407 ; print RAM page
- ld (_curRow),hl
- in a,(6)
- and $0F
- add a,'0'
- call __putmap
-
- sub a ; go to top of screen
- ld (_penRow),a
-
- ld de,(DisAddrTop) ; de = disassembly address
-
- ld b, 9 ; dump 9 lines
- Line_loop:
- sub a ; go to BOL
- ld (_penCol), a
- push bc
- call DisLine
- pop bc
- ld a, (_penRow) ; move down a line
- add a, 6
- ld (_penRow), a
- djnz Line_loop
- ld (DisAddrBottom),de
-
- call __busyOff
-
- ret
-
- ;------------------------------------------------------
- ; Disassemble Line at cursor DE = address
- ; Modifies A,BC,DE,HL
- ;------------------------------------------------------
-
- DisLine:
- sub a ; zero flags
- ld (DD_FD_flags),a
-
- ld hl,$0000 ; zero argument pointers
- ld (pArg1),hl
- ld (pArg2),hl
- ld (pArg3),hl
-
- ld hl,Normal_s8ptrs
- ld (s8ptrs),hl
-
- ld hl,$4C48 ; "LH"
- ld (HLIXStr),hl ; stores as "HL"
- ld (1+_HLIX_Str),hl
-
- ld b,d
- ld c,e ; BC = current address
- ld hl,WordStr
- call PrintWord ; print BC to (HL)
- call __vputs ; print (HL) to screen
-
- ld a, 20 ; leave some space
- ld (_penCol), a
-
- DL_Fetch:
- call FetchByte ; fetch and print byte
-
- cp $DD
- jr nz,Not_DD
- ld hl,DD_FD_flags
- set 0,(hl) ; set DD flag
- ld a,'X' ; store X's to relevant strings
- ld hl,$5849 ; "XI" stores as "IX"
- DL_Store_XY:
- ld (HLIXStr),hl
- ld (1+_HLIX_Str),hl
- ld (IndexStr+2),a
- ld (1+IXStr),a
- ld (XHStr),a
- ld (XLStr),a
- jr DL_Fetch
- Not_DD:
- cp $FD
- jr nz,Not_FD
- ld hl,DD_FD_flags
- set 1,(hl) ; set FD flag
- ld a,'Y' ; store Y's to relevant strings
- ld hl,$5949 ; "YI" stores as "IY"
- jr DL_Store_XY
- Not_FD:
- cp $CB
- jr nz,Not_CB
- call Decode_CB_Inst
- call PrintInst
- ret
- Not_CB:
- cp $ED
- jr nz,Not_ED
- call Decode_ED_Inst
- call PrintInst
- ret
- Not_ED:
- call Decode_Inst
- call PrintInst
- ret
-
- ;------------------------------------------------------
- ; Decode Instructions without CB or ED Prefixes
- ;------------------------------------------------------
- Decode_Inst:
- push af
- ld a,(DD_FD_flags)
- or a
- jr z,No_DD_FD_Flags
- ld hl,Index_s8ptrs
- ld (s8ptrs),hl
-
- No_DD_FD_Flags:
- pop af
-
- cp $40 ; if >= 40h
- jp nc,GE_40 ; goto GE_40
-
- bit 2,a
- jp nz,DI_Misc8bit
-
- bit 0,a
- jp nz,DI_Misc16bit
-
- bit 1,a
- jr nz,DI_MiscLD
-
- bit 5,a
- jr nz,DI_JRc
-
- bit 4,a
- jr nz,DI_DJNZ_JR
-
- or a
- jr nz,DI_N_NOP
- ld hl,nopStr ; mnemonic = NOP
- ret
- DI_N_NOP: ; the only thing left is EX
- ld hl,AFStr
- ld (pArg1),hl
- ld hl,AFpStr
- ld (pArg2),hl
- ld hl,exStr
- ret ; mnemonic = EX
-
- DI_DJNZ_JR:
- ld hl,djnzStr
- bit 3,a
- jr z,DI_is_DJNZ
- ld hl,jrStr
- DI_is_DJNZ:
- push hl ; save mnemonic
- call FetchRelAddr
- ld (pArg1),hl ; get relative address
- pop hl ; restore mnemonic
- ret
-
- DI_JRc:
- ld h,00011000b ; bits 4-3 : condition
- ld bc,condptrs
- call LD_HL_From_Table
- ld (pArg1),hl
- call FetchRelAddr ; get relative address
- ld (pArg2),hl
- ld hl,jrStr ; mnemonic = JR
- ret
-
- DI_MiscLD:
- bit 5,a
- jr nz,DI_LD_A16
-
- ld hl,_BC_Str
- bit 4,a
- jr z,DI_MiscLD_BC
- ld hl,_DE_Str
- DI_MiscLD_BC:
- ld (pArg1),hl
- ld hl,AStr
- ld (pArg2),hl
- DI_MiscLD_ToSwap:
- bit 3,a
- jr z,DI_MiscLD_NoSwap
- call SwapArg1Arg2
- DI_MiscLD_NoSwap:
- ld hl,ldStr ; mnemonic = LD
- ret
-
- DI_LD_A16:
- push af
- call FetchAbsAddr ; fetch (XXXXh)
- ld (pArg1),hl
- pop af
-
- ld hl,HLIXStr
- bit 4,a
- jr z,DI_LD_A16_HL
- ld hl,AStr
- DI_LD_A16_HL:
- ld (pArg2),hl
- jr DI_MiscLD_ToSwap
-
- DI_Misc16bit:
- ld h,00110000b ; bits 5-4 : dest register
- ld bc,s16ptrs ; bc -> string pointer table
- call LD_HL_From_Table
- ld (pArg1),hl
-
- bit 1,a
- jr nz,DI_INCDEC16
-
- bit 3,a
- jr z,DI_LDimm16
-
- ld a,$02 ; force this to recall either HL,IX,or IY
- ld h,$03
- ld bc,s16ptrs
- call LD_HL_From_Table
- ld (pArg2),hl
- call SwapArg1Arg2
- ld hl,addStr ; mnemonic = ADD
- ret
-
- DI_LDimm16:
- call FetchImm16
- ld (pArg2),hl
- ld hl,ldStr ; mnemonic = LD
- ret
-
- DI_INCDEC16:
- ld hl,incStr
- bit 3,a
- ret z
- ld hl,decStr
- ret
-
- DI_Misc8bit: ; INC,DEC,LD,RxCA,RxA,DAA,CPL
- ld h,00111000b ; bits 5-3 = register
- ld bc,(s8ptrs)
- call LD_HL_From_Table
- ld (pArg1),hl
-
- bit 1,a
- jr z,DI_INCDEC8
-
- bit 0,a
- jr z,DI_LDimm8
-
- ld hl,$0000 ; don't need arg1 anymore
- ld (pArg1),hl
-
- bit 5,a
- jr z,DI_Rotate
-
- ld h,00011000b ; bits 4-3 : mnemonic index
- ld bc,op001xx111ptrs ; -> mnemonic pointer table
- call LD_HL_From_Table
- ret
-
- DI_LDimm8:
- call FIA_If_Needed ; fetch index byte, if needed
- call FetchByte ; get and print byte
- ld hl,imm8Str
- call PrintByte ; stuff byte in buffer
- ld (pArg2),hl
- ld hl,ldStr ; mnemonic = LD
- ret
-
- DI_Rotate:
- ld h,00011000b ; mask index to mnemonic table
- ld bc,rotptrs
- call LD_HL_From_Table
- ret
- DI_INCDEC8:
- call FIA_If_Needed ; fetch index byte, if needed
- ld hl,incStr
- bit 0,a
- ret z
- ld hl,decStr
- ret
- GE_40:
- cp $80 ; if >= 80h
- jr nc,GE_80 ; goto GE_80
-
- cp $76 ; exception to the rule is HALT
- jr nz,Not_76
- ld hl,haltStr ; mnemonic = "HALT"
- ret
-
- Not_76: ; load instruction
-
- ld bc,(s8ptrs) ; string pointer table for LD operands
- ld h,00111000b ; bits 5-3 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg1),hl
- call FIA_If_Needed ; fetch index byte, if needed
-
-
- ld bc,(s8ptrs) ; string pointer table for LD operands
- ld h,00000111b ; bits 2-0 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg2),hl
- call FIA_If_Needed ; fetch index byte, if needed
-
- ld hl,ldStr ; mnemonic = "LD"
- ret
- GE_80:
- cp $C0 ; if >= C0h
- jr nc,GE_C0 ; goto GE_C0
-
- ld hl,AStr ; arg1 is "A"
- ld (pArg1),hl
-
- ld bc,(s8ptrs) ; string pointer table for operands
- ld h,00000111b ; bits 2-0 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg2),hl
- call FIA_If_Needed ; fetch index byte, if needed
-
- ld bc,op80_BFptrs ; string pointer table for mnemonics
- ld h,00111000b ; bits 5-3 of A specify table offset
- call LD_HL_From_Table ; HL = table value
-
- ret
- GE_C0:
- bit 0,a
- jr nz,GE_C0_ODD
-
- push af
- and $06
- cp 6
- jr z,GE_C0_IMM8
- pop af
-
- ld h,00111000b ; bits 5-3 = condition
- ld bc,condptrs ; table of string pointers
- call LD_HL_From_Table
- ld (pArg1),hl
-
- ld h,00000110b ; bits 2-1 = mnemonic
- ld bc,opC0_evenptrs ; table of mnemonic pointers
- call LD_HL_From_Table ; HL = pointer to mnemonic string
-
- push hl
- and $06
- jr z,GE_C0_RETc ; RETc doesn't use imm16, JPc and CALLc do
- call FetchImm16
- ld (pArg2),hl ; pArg2->buffer
- GE_C0_RETc:
- pop hl
- ret
-
- GE_C0_IMM8:
- pop af
- ld hl,AStr ; arg1 = "A"
- ld (pArg1),hl
-
- ld h,00111000b ; bits 5-3 = mnemonic
- ld bc,op80_BFptrs ; BC -> mnemonic pointer table
- call LD_HL_From_Table
-
- push hl
- call FetchByte ; fetch a byte and print it
- ld hl,imm8Str
- call PrintByte ; stuff it in buffer
- ld (pArg2),hl ; pArg2 -> buffer
- pop hl
- ret
-
- GE_C0_ODD:
- push af
- and $0A
- jr nz,GE_C0_N_Stack
- pop af
-
- ld h,00110000b ; bits 5-4 = register
- ld bc,stack_s16ptrs ; bc -> string pointer table
- call LD_HL_From_Table
- ld (pArg1),hl
-
- ld hl,popStr
- and $04
- jr z,GE_C0_NotPush
- ld hl,pushStr
- GE_C0_NotPush:
- ret
-
- GE_C0_N_Stack:
- pop af
- push af
- and $07
- cp $07
- jr nz, GE_C0_N_RST
-
- pop af
- and $38 ; prepare argument
- ld hl,imm8Str
- ld (pArg1),hl
- call PrintByte
- ld hl,rstStr ; mnemonic = RST
- ret
-
- GE_C0_N_RST:
- pop af
-
- cp $C3 ; JP i16
- jr nz,GE_C0_N_JP_i16
- call FetchImm16
- ld (pArg1),hl ; pArg1->buffer
- ld hl,jpStr
- ret
-
- GE_C0_N_JP_i16:
- cp $C9
- jr nz,GE_C0_N_RET
- ld hl,retStr
- ret
- GE_C0_N_RET:
- cp $D9
- jr nz,GE_C0_N_EXX
- ld hl,exxStr
- ret
- GE_C0_N_EXX:
- cp $E9
- jr nz,GE_C0_N_JPHL
- ld hl,_HLIX_Str
- ld (pArg1),hl
- ld hl,jpStr
- ret
- GE_C0_N_JPHL:
- cp $F9
- jr nz,GE_C0_N_LDSPHL
- ld hl,SPStr
- ld (pArg1),hl
- ld hl,HLIXStr
- ld (pArg2),hl
- ld hl,ldStr
- ret
- GE_C0_N_LDSPHL:
- cp $CD
- jr nz,GE_C0_N_CALL_i16
- call FetchImm16
- ld (pArg1),hl ; pArg1->buffer
- ld hl,callStr
- ret
-
- GE_C0_N_CALL_i16:
- cp $F3
- jr nz,GE_C0_N_DI
- ld hl,diStr
- ret
- GE_C0_N_DI:
- cp $FB
- jr nz,GE_C0_N_EI
- ld hl,eiStr
- ret
- GE_C0_N_EI:
- cp $E3
- jr nz,GE_C0_N_EXSPHL
- ld hl,_SP_Str
- ld (pArg1),hl
- ld hl,HLIXStr
- ld (pArg2),hl
- ld hl,exStr
- ret
- GE_C0_N_EXSPHL:
- cp $EB
- jr nz,GE_C0_N_EXDEHL
- ld hl,DEStr
- ld (pArg1),hl
- ld hl,HLStr
- ld (pArg2),hl
- ld hl,exStr
- ret
- GE_C0_N_EXDEHL:
- cp $D3
- jr nz,GE_C0_N_OUTnA
- call FetchPort
- ld (pArg1),hl
- ld hl,AStr
- ld (pArg2),hl
- ld hl,outStr
- ret
- GE_C0_N_OUTnA:
- ld hl,AStr
- ld (pArg1),hl
- call FetchPort
- ld (pArg2),hl
- ld hl,inStr
- ret
-
- ;------------------------------------------------------
- ; Decode Instructions with CB Prefixes
- ;------------------------------------------------------
- Decode_CB_Inst:
- ld a,(DD_FD_flags)
- and $FF
- jr z,DCB_NoIndex1
- call FetchIndAddr
-
- DCB_NoIndex1:
-
- call FetchByte ; fetch and print a byte
-
- cp $40 ; if >= 40h
- jr nc,DCB_GE_40 ; goto DCB_GE_40
-
- ld bc,Normal_s8ptrs ; string pointer table for operands
- ld h,00000111b ; bits 2-0 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg1),hl
-
- push af ; arg2 is (IX+nn), if required
- ld a,(DD_FD_flags)
- and $FF
- jr z,DCB_NoIndex2
- ld hl,IndexStr
- ld (pArg2),hl
- pop af
- push af ; restore a
- and $07
- cp $06 ; if arg2 is (hl), replace it with
- jr nz,DCB_NotHL ; (IX+nn) and make arg2 null
- ld hl,$0000
- ld (pArg1),hl
- call SwapArg1Arg2
- DCB_NotHL:
- DCB_NoIndex2:
- pop af
-
- ld bc,opCB00_3Fptrs ; string pointer table RLC, etc
- ld h,00111000b ; bits 5-3 of A specify table offset
- call LD_HL_From_Table ; HL = table value
-
- ret
-
- DCB_GE_40:
- push af ; set up arg1
- rrca
- rrca
- rrca
- and $07
- add a,'0'
- ld hl,ByteStr
- ld (pArg1),hl
- ld (hl),a
- inc hl
- sub a
- ld (hl),a
- pop af
-
- ld bc,Normal_s8ptrs ; string pointer table for operands
- ld h,00000111b ; bits 2-0 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg2),hl
-
- push af ; arg3 is (IX+nn), if required
- ld a,(DD_FD_flags)
- and $FF
- jr z,DCB_NoIndex3
- ld hl,IndexStr
- ld (pArg3),hl
- pop af
- push af ; restore a
- cp $80
- jr c,DCB_ReplaceArg2 ; if A < $80, mnemonic is BIT
- and $07
- cp $06 ; if arg2 is (hl), replace it with
- jr nz,DCB_NotHL2 ; (IX+nn) and make arg3 null
- DCB_ReplaceArg2:
- ld hl,(pArg3)
- ld (pArg2),hl
- ld hl,$0000
- ld (pArg3),hl
- DCB_NotHL2:
- DCB_NoIndex3:
- pop af
-
- ld bc,opCB40_FFptrs ; address of mnemonic table
- ld h,11000000b ; bits 7-6 are index into mnemonic table
- call LD_HL_From_Table
-
- ret
-
- ;------------------------------------------------------
- ; Decode Instructions with ED Prefixes
- ;------------------------------------------------------
- Decode_ED_Inst:
- ld a,(DD_FD_flags)
- and $FF
- jr z,DED_NoIndex ; DD and FD not allowed w/ED
-
- ld hl,QuestionStr
- ret
-
- DED_NoIndex:
-
- call FetchByte ; fetch and print a byte
-
- cp $40 ; if >= 40h
- jr nc,DED_GE_40 ; goto DED_GE_40
-
- DED_NOP:
- ld hl,nopStr
- ret
-
- DED_GE_40:
- cp $80 ; if >= 80h,
- jr nc,DED_GE_80 ; goto DED_GE_80
-
- ld bc,DED_JumpPtrs ; bc -> jump table
- ld h,00000111b ; bits 2-0 hold index into table
- call LD_HL_From_Table
- jp (hl)
-
- ;; Embedded Data: Jump pointers
- DED_JumpPtrs: .dw DED_JP_0,DED_JP_1,DED_JP_2,DED_JP_3
- .dw DED_JP_4,DED_JP_5,DED_JP_6,DED_JP_7
-
- DED_GE_80:
-
- cp $A0 ; if < A0h,
- jr c,DED_NOP ; goto DED_NOP
- cp $C0 ; if >= C0h,
- jr nc,DED_NOP ; goto DED_NOP
- bit 2,a
- jr nz,DED_NOP
-
- ld h,00011011b ; significant bits
- ld bc,opEDA0_BFptrs ; -> opcode table
- call LD_HL_From_Table ; load string pointer
-
- ret
-
- DED_JP_0:
- ld bc,inCptrs ; string pointer table for operand
- ld h,00111000b ; bits 5-3 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg1),hl
-
- ld hl,PortCStr
- ld (pArg2),hl
-
- ld hl,inStr
- ret
-
- DED_JP_1:
- ld hl,PortCStr
- ld (pArg1),hl
-
- ld bc,outCptrs ; string pointer table for operand
- ld h,00111000b ; bits 5-3 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg2),hl
-
- ld hl,outStr
- ret
-
- DED_JP_2:
- ld hl,HLStr
- ld (pArg1),hl
-
- ld bc,s16ptrs ; string pointer table for operand
- ld h,00110000b ; bits 5-4 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg2),hl
-
- ld hl,sbcStr
- bit 3,a
- ret z
- ld hl,adcStr
- ret
-
- DED_JP_3:
- push af
- call FetchAbsAddr ; fetch (XXXXh)
- ld (pArg1),hl
- pop af
-
- ld bc,s16ptrs ; string pointer table for operand
- ld h,00110000b ; bits 5-4 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg2),hl
-
- bit 3,a
- jr z,DED_JP_3_NoSwap
- call SwapArg1Arg2
- DED_JP_3_NoSwap:
- ld hl,ldStr
- ret
-
- DED_JP_4:
- ld hl,negStr
- ret
-
- DED_JP_5:
- ld hl,retnStr
- bit 3,a
- ret z
- ld hl,retiStr
- ret
-
- DED_JP_6:
- ld bc,imptrs ; string pointer table for operand
- ld h,00011000b ; bits 4-3 of A specify table offset
- call LD_HL_From_Table ; HL = table value
- ld (pArg1),hl
- ld hl,imStr
- ret
-
- DED_JP_7:
- bit 5,a
- jr z,DED_JP_7_LD
-
- bit 4,a
- jr nz,DED_JP_7_NOP
-
- ld hl,rrdStr
- bit 3,a
- jr z,DED_JP_7_RRD
- ld hl,rldStr
- DED_JP_7_RRD:
- ret
-
- DED_JP_7_NOP:
- ld hl,nopStr
- ret
-
- DED_JP_7_LD: ; LD I,A ; LD A,I ; LD R,A ; LD A,R
- ld hl,IStr
- bit 3,a
- jr z,DED_JP_7_LD_I
- ld hl,RStr
- DED_JP_7_LD_I:
- ld (pArg1),hl
- ld hl,AStr
- ld (pArg2),hl
- bit 4,a
- jr z,DED_JP_7_LD_N
- call SwapArg1Arg2
- DED_JP_7_LD_N: ; No Swap
- ld hl,ldStr ; mnemonic = LD
- ret
-
- ;------------------------------------------------------
- ; Print Instruction and operands on current line
- ; input: HL->mnemonic string
- ; pArg1->argument 1 string (null if <1 arg)
- ; pArg2->argument 2 string (null if <2 args)
- ; pArg3->argument 3 string (null if <3 args)
- ;------------------------------------------------------
- PrintInst:
- push af
- push de
-
- ld a, 56 ; leave a large gap
- ld (_penCol), a
- call __vputs ; print mnemonic
- ld hl,(pArg1) ; see if there is one argument
- sub a
- or h
- or l
- jr z,PI_Done
- ld a, 75 ; leave a small gap
- ld (_penCol), a
- call __vputs ; print arg1
- ld hl,(pArg2) ; see if there are two arguments
- sub a
- or h
- or l
- jr z,PI_Done
- ld a,',' ; print a comma
- call __vputmap
- call __vputs ; print arg2
- ld hl,(pArg3) ; see if there are three arguments
- sub a
- or h
- or l
- jr z,PI_Done
- ld a,',' ; print a comma
- call __vputmap
- call __vputs ; print arg3
- PI_Done:
- pop de
- pop af
- ret
-
- ;------------------------------------------------------
- ; Fetch Byte and print it at current cursor location
- ;------------------------------------------------------
- FetchByte:
- ld a,(de) ; fetch a byte
- inc de
-
- push af
- ld hl,DisFlags
- bit FlagBitChar,(hl) ; hex/char
- jr nz,FB_Char
- ld hl,ByteStr ; print the byte
- call PrintByte
- call __vputs
- pop af
- ret
- FB_Char:
- dec a ; 0 -> FF
- cp $D5 ; if char < D5, print character
- inc a ; "inc" does not affect the carry flag
- jr c, FB_Char_GoAhead
- ld a, $D0 ; else print a square instead
- FB_Char_GoAhead:
- push de
- call __vputmap
- pop de
- pop af
- ret
-
- ;------------------------------------------------------
- ; Fetch Word into BC, print bytes at cursor
- ;------------------------------------------------------
- FetchWord:
- call FetchByte
- ld c,a
- call FetchByte
- ld b,a
- ret
-
- ;------------------------------------------------------
- ; Fetch port (nn) print byte at cursor
- ; A becomes port number, HL->PortStrSm or PortStrLg
- ;------------------------------------------------------
- FetchPort:
- call FetchByte ; fetch a byte and print it
- cp 10 ; if port >= 10, use large string
- jr nc, FP_LargeString
- ld hl,PortStrSm+1 ; else use small string
- add a,'0'
- ld (hl),a
- dec hl
- ret
- FP_LargeString:
- ld hl,PortStrLg+1
- call PrintByte
- dec hl
- ret
-
- ;------------------------------------------------------
- ; Call FetchIndAddr if HL -> IndexStr
- ; BC and HL are changed
- ;------------------------------------------------------
- FIA_If_Needed:
- push af
- ld bc,IndexStr
- or a ; clear carry flag
- sbc hl,bc ; compare hl to IndexStr
- call z,FetchIndAddr ; if necessary, get index byte
- pop af
- ret
-
- ;------------------------------------------------------
- ; Fetch (IX+nn) index, print it to important places
- ;------------------------------------------------------
- FetchIndAddr:
- call FetchByte ; fetch and print to screen
- ld hl,IndexStr+4
- call PrintByte ; print to IndexStr
- ret
-
- ;------------------------------------------------------
- ; Fetch (XXXXh) address for loads, stores, etc
- ; A is destroyed. HL->AddrStr, which holds "(XXXXh)"
- ;------------------------------------------------------
- FetchAbsAddr:
- call FetchWord ; fetch word into BC
- ld hl,AddrStr+1
- call PrintWord ; print BC into (HL)
- dec hl
- ret
-
- ;------------------------------------------------------
- ; Fetch XXXXh address for relative jumps
- ; A is destroyed. HL->imm16Str, which holds "XXXXh"
- ;------------------------------------------------------
- FetchRelAddr:
- call FetchByte ; get and display byte
- ld l,a
- rlca ; if sign bit of A is set
- sbc a,a ; set all bits in A
- ld h,a ; now HL = sign-extended A
- add hl,de ; add current memory location
- ld b,h
- ld c,l ; BC = address
- jr FI16_PrintI16 ; see FetchImm16
-
- ;------------------------------------------------------
- ; Fetch XXXXh address for absolute jumps, loads, etc.
- ; A is destroyed. HL->imm16Str, which holds "XXXXh"
- ;------------------------------------------------------
- FetchImm16:
- call FetchWord ; fetch word into BC
- FI16_PrintI16:
- ld hl,imm16Str
- call PrintWord ; print BC into (HL)
- ret
-
- ;------------------------------------------------------
- ; Swap pArg1 and pArg2 ; HL is destroyed
- ;------------------------------------------------------
- SwapArg1Arg2:
- ld hl,(pArg1)
- push hl
- ld hl,(pArg2)
- ld (pArg1),hl
- pop hl
- ld (pArg2),hl
- ret
-
- ;------------------------------------------------------
- ; Scroll Screen Down
- ;------------------------------------------------------
- ScrollDown:
- ld hl, 8*16*6+$FBFF ; move from second-to-bottom line
- ld de, 9*16*6+$FBFF ; move to bottom line
- ld bc, 8*16*6 ; move 8 lines
- lddr ; move!
- ld hl, 0*16*6+$FC00 ; clear top line
- jr ScrollCommon
-
- ;------------------------------------------------------
- ; Scroll Screen Up
- ;------------------------------------------------------
- ScrollUp:
- ld hl, 1*16*6+$FC00 ; move from one line down
- ld de, 0*16*6+$FC00 ; move to top line
- ld bc, 8*16*6 ; move 8 lines
- ldir ; move!
- ld hl, 8*16*6+$FC00 ; clear bottom line
- ScrollCommon:
- ld d,h
- ld e,l
- inc de
- ld bc, 16*6
- ld (hl), 0
- ldir
- ret
-
- ;-------------------------------------------------------
- ; Print the word in BC into four consecutive bytes at HL
- ;-------------------------------------------------------
- PrintWord:
- ld a,b
- call PrintByte
- inc hl
- inc hl
- ld a,c
- call PrintByte
- dec hl
- dec hl
- ret
-
- ;------------------------------------------------------
- ; Print the byte in A into two consecutive bytes at HL
- ;------------------------------------------------------
- PrintByte:
- push hl
- call PrintNybble
- call PrintNybble
- pop hl
- ret
-
- ; Print the high nybble of A into (HL++), swap nybbles
-
- PrintNybble:
- rrca
- rrca
- rrca
- rrca
- push af
- and $0F
- add a, '0'
- cp $3A
- jr c, Less_0A
- add a, 7
- Less_0A:
- ld (hl),a
- inc hl
- pop af
- ret
-
- ;------------------------------------------------------
- ; Load HL from Word Table.
- ; Input: A = some bits hold an index into the table
- ; H = AND bitmask to apply to A
- ; BC= table start address
- ; Output: HL= [BC+2*A(index bits)]
- ; A and BC are preserved
- ;------------------------------------------------------
- LD_HL_From_Table:
- push bc
- ld L,0 ; make sure L has no bits set
- ld b,8 ; do this 8 times, once for each bit
- LHBA_Loop:
- rlca ; rotate A
- rl L ; put that bit from A into L
- sla h
- jr c,LHBA_Bit1 ; if bit shifted out of H is 0
- srl L ; discard that bit from L
- LHBA_Bit1:
- djnz LHBA_Loop
- pop bc
- add hl,hl ; table is word-sized
- add hl,bc ; add table start address
- call LD_HL_pHL
- ret
-
- ;------------------------------------------------------
- ; Load HL from (HL)
- ;------------------------------------------------------
- LD_HL_pHL:
- push de
- ld e,(hl)
- inc hl
- ld d,(hl)
- ex de,hl
- pop de
- ret
-
- ;------------------------------------------------------
- ; Set up call table
- ;------------------------------------------------------
- ;__getkey .db $CD,0,0,$C9
-
- SetUpCalls:
- ld b,(EndOfCallTable-CallTable)/2
- ld hl, CallTable
- ld de, __clrLCD
- SUC_Loop:
- push bc
-
- push hl
- call LD_HL_pHL
- ldi ; copy call
- ldi
- ldi
- ldi
- pop hl
- inc hl
- inc hl
- pop bc
- djnz SUC_Loop
- ret
-
- CallTable: ; these need to be in the same order as the list at
- ; the top of this file
- .dw _clrLCD
- .dw _clrScrn
- .dw _putmap
- .dw _putc
- .dw _puts
- .dw _vputmap
- .dw _vputs
- .dw _busyOn
- .dw _busyOff
- .dw _getkey
- EndOfCallTable
-
- ;------------------------------------------------------
- ; Variables
- ;------------------------------------------------------
- DisAddrTop .dw $00
- DisFlags .db $00
-
- ByteStr .db "00",0
- WordStr .db "0000",0
- imm8Str .db "00h",0
- imm16Str .db "0000h",0
- PortStrSm .db "(0)",0
- PortStrLg .db "(00h)",0
- AddrStr .db "(0000h)",0
- IndexStr .db "(IX+00h)",0
- HLIXStr .db "HL",0
- _HLIX_Str .db "(HL)",0
-
- ;------------------------------------------------------
- ; Tables
- ;------------------------------------------------------
-
- s8ptrs .dw Normal_s8ptrs
- Normal_s8ptrs .dw BStr,CStr,DStr,EStr,HStr,LStr,_HL_Str,AStr
- Index_s8ptrs .dw BStr,CStr,DStr,EStr,XHStr,XLStr,IndexStr,AStr
-
- s16ptrs .dw BCStr,DEStr,HLIXStr,SPStr
- stack_s16ptrs .dw BCStr,DEStr,HLIXStr,AFStr
-
- inCptrs .dw BStr,CStr,DStr,EStr,HStr,LStr,DashStr,AStr
- outCptrs .dw BStr,CStr,DStr,EStr,HStr,LStr,ZeroStr,AStr
-
- condptrs .dw nzStr,zStr,ncStr,cStr,poStr,peStr,pStr,mStr
-
- rotptrs .dw rlcaStr,rrcaStr,rlaStr,rraStr
-
- imptrs .dw ZeroStr,QuestionStr,OneStr,TwoStr
-
- op001xx111ptrs .dw daaStr,cplStr,scfStr,ccfStr
-
- op80_BFptrs .dw addStr,adcStr,subStr,sbcStr
- .dw andStr,xorStr,orStr,cpStr
-
- opC0_evenptrs .dw retStr,jpStr,callStr
-
- opCB00_3Fptrs .dw rlcStr,rrcStr,rlStr,rrStr
- .dw slaStr,sraStr,sllStr,srlStr
-
- opCB40_FFptrs .dw QuestionStr,bitStr,resStr,setStr
-
- opEDA0_BFptrs .dw ldiStr,cpiStr,iniStr,outiStr
- .dw lddStr,cpdStr,indStr,outdStr
- .dw ldirStr,cpirStr,inirStr,otirStr
- .dw lddrStr,cpdrStr,indrStr,otdrStr
-
- ;------------------------------------------------------
- ; Strings
- ;------------------------------------------------------
- NullStr .db 0
- QuestionStr .db "?",0
- DashStr .db "-",0
- ZeroStr .db "0",0
- OneStr .db "1",0
- TwoStr .db "2",0
-
- AStr .db "A",0
- AFStr .db "AF",0
- AFpStr .db "AF",$27,0 ; AF'
- BStr .db "B",0
- BCStr .db "BC",0
- CStr .db "C",0
- DStr .db "D",0
- DEStr .db "DE",0
- EStr .db "E",0
- HStr .db "H",0
- HLStr .db "HL",0
- IStr .db "I",0
- IXStr .db "IX",0
- XHStr .db "XH",0
- XLStr .db "XL",0
- LStr .db "L",0
- RStr .db "R",0
- SPStr .db "SP",0
- _BC_Str .db "(BC)",0
- _DE_Str .db "(DE)",0
- _HL_Str .db "(HL)",0
- _SP_Str .db "(SP)",0
-
- PortCStr .db "(C)",0
-
- nzStr .db "nz",0
- zStr .db "z",0
- ncStr .db "nc",0
- cStr .db "c",0
- poStr .db "po",0
- peStr .db "pe",0
- pStr .db "p",0
- mStr .db "m",0
-
- StartOfStrings
-
- adcStr .db "ADC",0
- addStr .db "ADD",0
- andStr .db "AND",0
- bitStr .db "BIT",0
- callStr .db "CALL",0
- ccfStr .db "CCF",0
- cpStr .db "CP",0
- cpdStr .db "CPD",0
- cpdrStr .db "CPDR",0
- cpiStr .db "CPI",0
- cpirStr .db "CPIR",0
- cplStr .db "CPL",0
- daaStr .db "DAA",0
- decStr .db "DEC",0
- diStr .db "DI",0
- djnzStr .db "DJNZ",0
- eiStr .db "EI",0
- exStr .db "EX",0
- exxStr .db "EXX",0
- haltStr .db "HALT",0
- imStr .db "IM",0
- inStr .db "IN",0
- incStr .db "INC",0
- indStr .db "IND",0
- indrStr .db "INDR",0
- iniStr .db "INI",0
- inirStr .db "INIR",0
- jpStr .db "JP",0
- jrStr .db "JR",0
- ldStr .db "LD",0
- lddStr .db "LDD",0
- lddrStr .db "LDDR",0
- ldiStr .db "LDI",0
- ldirStr .db "LDIR",0
- negStr .db "NEG",0
- nopStr .db "NOP",0
- orStr .db "OR",0
- otdrStr .db "OTDR",0
- otirStr .db "OTIR",0
- outStr .db "OUT",0
- outdStr .db "OUTD",0
- outiStr .db "OUTI",0
- popStr .db "POP",0
- pushStr .db "PUSH",0
- resStr .db "RES",0
- retStr .db "RET",0
- retiStr .db "RETI",0
- retnStr .db "RETN",0
- rlStr .db "RL",0
- rlaStr .db "RLA",0
- rlcStr .db "RLC",0
- rlcaStr .db "RLCA",0
- rldStr .db "RLD",0
- rrStr .db "RR",0
- rraStr .db "RRA",0
- rrcStr .db "RRC",0
- rrcaStr .db "RRCA",0
- rrdStr .db "RRD",0
- rstStr .db "RST",0
- sbcStr .db "SBC",0
- scfStr .db "SCF",0
- setStr .db "SET",0
- slaStr .db "SLA",0
- sllStr .db "SLL",0
- sraStr .db "SRA",0
- srlStr .db "SRL",0
- subStr .db "SUB",0
- xorStr .db "XOR",0
-
- EndOfStrings
-
- SmallFont:
- .db $64 ; magic number
- .db $01 ; # of characters in font
-
- .db 'N'
- .db 5 ; width of character
- .db 00000b
- .db 10010b
- .db 11010b
- .db 10110b
- .db 10010b
- .db 10010b
-
- ProgramEnd:
- .end
-
-