;; 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. ;; #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