Files
TZFS/asm/tzfs_bank4.asm

2003 lines
108 KiB
NASM

;--------------------------------------------------------------------------------------------------------
;-
;- Name: tzfs_bank4.asm
;- Created: July 2019
;- Author(s): Philip Smart
;- Description: Sharp MZ series tzfs (tranZPUter Filing System).
;- Bank 4 - 1200:CFFF, F000:FFFF
;-
;- This assembly language program is a branch from the original RFS written for the
;- MZ80A_RFS upgrade board. It is adapted to work within the similar yet different
;- environment of the tranZPUter SW which has a large RAM capacity (512K) and an
;- I/O processor in the K64F/ZPU.
;-
;- Credits: Assembler/Disassembler base code (C) Eric M. Klaus Feb 2023. Based on TASM and adapted
;- to the Sharp system under TZFS.
;- Copyright: (c) 2018-2023 Philip Smart <philip.smart@net2net.org>
;-
;- History: May 2020 - Branch taken from RFS v2.0 and adapted for the tranZPUter SW.
;- Dec 2020 - Updates to accommodate v1.3 of the tranZPUter SW-700 board where soft
;- CPU's now become possible.
;- Feb 2023 - TZFS now running on FusionX. Changes to ensure compatibility and
;- addition of new commands, assemble, disassemble, fill, write I/O,
;- read I/O.
;- TZFS4 now extended to the full RAM range, 1200:CFFF and F000:FFFF. In
;- this memory mode, writing to the core memory page must be done by the
;- API which is sited in E800:EFFF.
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;============================================================
;
; TZFS BANK 4 - TZFS commands
; - Full range, 1200:CFFF, F000:FFFF available.
;
;============================================================
ORG MEMSTART
COUNT_C: DS 1 ; Counter C
ADDR:
ADDR_LO: DS 1
ADDR_HI: DS 1
ASM_ADDR: DS 8 ; Assembler Destination address
ASM_BUF: DS 16 ; 16 byte ASM Input Buffer
OUT_BUF: DS 4 ; 4 byte test buffer(last part of ASM_BUF)
INS_BUF: DS 4 ; 4 Byte Instruction Buffer
PARM_BUF: DS 7 ; 7 Byte Parm Buffer
VAL_BUF: ; 5 Byte Value Buffer
VAL_BUF_HI: DS 2 ; 2 Hi Bytes in Value Buffer
VAL_BUF_LO: DS 2 ; 2 Lo Bytes in Value Buffer
DS 1
SRC_ADDR: DS 2 ; 2 byte source pointer storage
DES_ADDR: DS 2 ; 2 byte destination pointer storage
BLK_ADDR: DS 2 ; 2 byte table block pointer storage
ROW_ADDR: DS 2 ; 2 byte table row pointer storage
BLK_NUM: DS 1 ; 1 byte Block Number
BLK_SIZE: DS 1 ; 1 byte Block Size
ROW_NUM: DS 1 ; 1 byte Row Number
ML_BUF: DS 2 ; 3 byte ML buffer
ML_BTCOUNT: DS 1 ; Last byte of ML buffer(byte count)
VAL_LO: DS 1 ; Converted value LO
VAL_HI: DS 1 ; Converted value Hi
; Fill remaining variable area 0's.
ALIGN_NOPS MEMSTART+0800H
ORG MEMSTART+0800H
;-------------------------------------------------------------------------------
; START OF ADDITIONAL TZFS COMMANDS
;-------------------------------------------------------------------------------
;******************************************************************
; DASM_MAIN Z80 Dis-Assembler
; Based on tables used by the TASM for the Z80 target
;******************************************************************
DASM_MAIN: CALL HLHEX ; get starting address
LD (ADDR_LO),HL
LD (SRC_ADDR),HL ; Save in SRC_ADDR & SRC_ADDR+1
LD BC,0h ; Add 1 To Start Address BC=0000
SCF ; C=1
ADC HL,BC ; Add HL+BC+C to HL(FFFF will overflow to 0000)
RET Z ; Exit if xFFFF was entered
INC DE
INC DE
INC DE
INC DE
CALL HLHEX ; get end address
JP NC,DASM_UENDAD ; User entered a non-zero address(use it)
XOR A
LD (ASM_ADDR),A ; NOT Using End Address - Just do 16 rows
LD (ASM_ADDR+1),A ; Set ASM_ADDR=x0000
LD A,10h
LD (COUNT_C),A ; Set Row Counter = 16
JP DASM_UROWCT
DASM_UENDAD:LD A,0FFh ; End Address Was entered - Use It
LD (COUNT_C),A ; Set Row Counter = xFF
;LD HL,(ADDR_LO)
LD (ASM_ADDR),HL
DASM_UROWCT:LD HL,(SRC_ADDR)
LD (ADDR_LO),HL
XOR A
LD (TMPCNT),A ; Set paging rowcount to 0. Used with PRTSTR.
; ** Print CR, LF, ADDR_HI, ADDR_LO (in HEX), space
DASM_LOOP1: CALL NL ; Print CR & LF
LD A,(ADDR_HI) ; Print Address Buffer
CALL PRTHX
LD A,(ADDR_LO)
CALL PRTHX
CALL PRNTS ; Print Space
LD HL,ASM_BUF ; Clear ASM_BUF, INS_BUF, PARM_BUF & VAL_BUF
LD B,30h ; (Set to all spaces)
CALL MEMSET
; ** Get 2 bytes from memory pointed to by ADDR_LO & ADDR_HI
LD HL,(ADDR_LO) ; Address ->HL
LD A,(HL) ; First Byte ->A
CALL ?GETMEM ; First Byte ->A
LD (ML_BUF),A ; Store in ML_BUF Byte 0
INC HL
CALL ?GETMEM ; Second Byte ->A
LD (ML_BUF+1),A ; Store in ML_BUF Byte 1
CALL DASMBITINST ; Is This a BIT,SET or RES Inst.?
JP NZ,DASM_FIND ; NO=Do regular search
CALL DSMFINDOPCD ; Search For Matching BIT,SET,RES OP Code
JP Z,DASM_ERR ; NOT FOUND - Error Message
CALL DASMGETINST ; Copy 4 byte Assembler Inst. to ASM_BUF
JP DASM_JUSTV ; VAL_BUF has already been populated
DASM_FIND: CALL DSMFINDOPCD ; Search For Matching OP Code
JP Z,DASM_ERR ; NOT FOUND - Error Message
CALL DASMGETINST ; Copy 4 byte Assembler Inst. to ASM_BUF
; ** Are Data Bytes expected? YES=COPY TO VAL_BUF
LD A,'0'
LD (VAL_BUF_HI),A ; Set VAL_BUF_HI="00"
LD (VAL_BUF_HI+1),A
LD A,0
LD (VAL_BUF_LO),A ; Set VAL_BUF_LO=NULL(NO DATA indicator)
CALL DASMGETVAL ; Get 1 or 2 value bytes from memory
DASM_JUSTV: CALL DSMLFJVAL ; Left justify VAL_BUF(Trim leading zeros)
CALL DASMGETPARM ; Build parameter string with value data
CALL DSMRTRIMASM ; Trim trailing spaces from ASM_BUF
LD A,0Fh ; Output Memory Bytes and Advance Address Pointer
LD C,A
LD HL,(ADDR_LO) ; Address ->HL
LD A,(ML_BTCOUNT) ; Get Total Byte count from lookup table
LD B,A ; Save in B
DASM_MEMOUT:CALL ?GETMEM ; LD A,(HL)
CALL PRTHX
CALL PRNTS ; Print Space
INC HL ; Adjust memory pointer and byte count
DEC C
DEC C
DEC C
DEC B
JP NZ,DASM_MEMOUT ; DONE? NO=Continue
LD (ADDR_LO),HL ; Save New Memory Address
DASM_SPCOUT:CALL PRNTS ; Pad with spaces to 15 bytes
DEC C
JP NZ,DASM_SPCOUT ; DONE? NO=Continue
LD BC,010H
LD DE,NAME
PUSH DE
LD HL,ASM_BUF
LDIR
POP DE
LD A,1
CALL ?PRTSTR ; Print assembly string.
LD A,(COUNT_C) ; Get Row Count
CP 0FFh ; Using End Address?
JP Z,DASM_CKEADR
DEC A ; Decrement
RET Z ; DONE? - YES = Exit
LD (COUNT_C),A ; NO= Save Row Count
JP DASM_LOOP1 ; Continue...
DASM_CKEADR:LD HL,(ASM_ADDR) ; Get End Address
LD BC,(ADDR_LO) ; Get Memory Address pointer
SBC HL,BC ; Subtract End from Current
RET M ; If resulte negative - Exit
JP DASM_LOOP1 ; Otherwise Continue...
DASM_ERR: LD DE,MSGNOTFND
CALL ?PRINTMSG
SCF
RET
;******************************************************************
; Dis-Assembler Routines
;******************************************************************
;******************************************************************
; ISVALBUF0
; Return Z=1 if VAL_BUF contains a single '0' followed by a NULL
;******************************************************************
ISVALBUF0: LD A,(VAL_BUF)
CP '0'
JP NZ,IZVBFZ_RET
LD A,(VAL_BUF+1)
CP 0
IZVBFZ_RET: RET
;******************************************************************
; IS_DIGIT
;
; RETURN Z=1 if A is 'A'-'F' otherwise Z=0 (A is unchanged )
; NOTE: A MUST be a non-zero ASCII Digit
;******************************************************************
IS_DIGIT: CALL ISDECDIGIT ; Is it '0'-'9'
JP Z,IS_DIG_EXIT ; YES=EXIT with Z=1
CALL ISHEXDIGIT ; test for 'A'-'F' and return
IS_DIG_EXIT:RET
;******************************************************************
; ISHEXDIGIT
;
; RETURN Z=1 if A is 'A'-'F' otherwise Z=0 (A is unchanged)
; NOTE: A MUST be a non-zero ASCII Digit
;******************************************************************
ISHEXDIGIT: CP 'A' ; is A <'A'?
JP M,ISHEXD_EXIT ; YES=just exit Z=0
CP 'G' ; is A <='F'?
JP M,ISHEXD_ZRET ; YES=return Z=1
JP ISHEXD_EXIT ; otherwise return Z=0
ISHEXD_ZRET:CP A ; Set Z=1 and Return
RET
ISHEXD_EXIT:CP 0 ; Set Z=0 and Return
RET
;******************************************************************
; ISDECDIGIT
;
; RETURN A=1 if A is '0'-'9' otherwise Z=0 (A is unchanged)
; NOTE: A MUST be a non-zero ASCII Digit
;******************************************************************
ISDECDIGIT: CP '0' ; is A <'0'?
JP M,ISDECD_EXIT ; YES= exit with Z=0
CP 03Ah ; is A <='9'?
JP M,ISDECD_ZRET ; YES=return Z=1
JP ISDECD_EXIT ; otherwise just exit with Z=0
ISDECD_ZRET:CP A ; Set Z=1 and Return
RET
ISDECD_EXIT:CP 0 ; Set Z=0 and Return
RET
;******************************************************************
; MEMSET
; HL=src B=COUNT A=FILL BYTE
; COPY A to (HL) for B bytes
;******************************************************************
MEMSET: LD (HL),A
INC HL
DEC B
JP NZ, MEMSET
RET
;******************************************************************
; RTJUSTVAL
; Shift bytes in VAL_BUF right until left padded with '0's
;******************************************************************
RTJUSTVAL: PUSH IX
PUSH BC
LD IX,VAL_BUF
LD B,05h ; B=MAX search count 5
RTJVAL_LOOP:LD A,(IX+3) ; Get last byte from VAL_BUF
CP ' ' ; Is It SPACE?
JP NZ,RTJVAL_EXIT ; Exit
LD A,(IX+2) ; Shift 3 bytes left 1 positiom
LD (IX+3),A
LD A,(IX+1)
LD (IX+2),A
LD A,(IX+0)
LD (IX+1),A
LD A,'0' ; Pad first position with '0'
LD (IX+0),A
DEC B
JP NZ,RTJVAL_LOOP
RTJVAL_EXIT:POP BC
POP IX
RET
;******************************************************************
; ISIXIYPRM
; Is parameter (IX*) or (IY*)
;******************************************************************
ISIXIYPRM: PUSH BC
PUSH HL
LD C,0 ; C = match counter
LD B,7 ; B = byte counter
LD HL,(ROW_ADDR) ; HL = Row data pointer
ISIX_LOOP: LD A,(HL) ; Get a byte from row
CP '(' ; If '(', 'I' or '*' Increment C
JP Z,ISIX_CKI
CP '*'
JP Z,ISIX_COUNT
JP ISIX_NEXT ; None of the above then continue
ISIX_CKI: INC HL ; Check for '(' followed by 'I'
LD A,(HL) ; Get byte after the '(' just found
CP 'I' ; Is it = 'I'?
JP Z,ISIX_COUNT ; Yes=Count the match
JP ISIX_NEXT2 ; No = Continue
ISIX_COUNT: INC C
ISIX_NEXT: INC HL ; Advance row data pointer
ISIX_NEXT2: DEC B ; Decrement byte count
JP NZ,ISIX_LOOP ; DONE? NO = Continue
LD A,C ; Get match count
CP 2 ; If = 2 Return Z=1 otherwise Z=0
POP HL
POP BC
RET
;******************************************************************
; DSMRTRIMASM
; Trim trailing spaces from ASM_BUF
;******************************************************************
DSMRTRIMASM:PUSH BC
PUSH HL
LD B,0Fh ; B=MAX loop count 15
LD HL,ASM_BUF+15 ; HL=tail of ASM_BUF
DSMRTA_LOOP:LD A,(HL) ; Get a byte from VAL_BUF
CP ' ' ; Is It ' '?
JP NZ,DSMRTA_EXIT ; No = Exit
XOR A ; A=00h
LD (HL),A ; Store in ASM_BUF
DEC HL ; Decrement ASM_BUF pointer
DEC B ; Decrement byte count
JP NZ,DSMRTA_LOOP ; Done? No=Continue
DSMRTA_EXIT:POP HL ; Restore BC, HL & Exit
POP BC
RET
;******************************************************************
; DSMLFJVAL
; Shift bytes in VAL_BUF left until non-zero char is encountered
;******************************************************************
DSMLFJVAL: PUSH BC
LD B,03h ; B=MAX loop count 3
DSMLFJ_LOOP:LD A,(VAL_BUF) ; Get 1st byte from VAL_BUF
CP '0' ; Is It '0'?
JP NZ,DSMLFJ_EXIT ; No = Exit
LD A,(VAL_BUF+1) ; Shift 3 bytes left 1 positiom
LD (VAL_BUF),A
LD A,(VAL_BUF+2)
LD (VAL_BUF+1),A
LD A,(VAL_BUF+3)
LD (VAL_BUF+2),A
LD A,0 ; Set last position to NULL
LD (VAL_BUF+3),A
DEC B
JP NZ,DSMLFJ_LOOP
DSMLFJ_EXIT:POP BC
RET
;******************************************************************
; BYTE2ASCII
; Convert Hex Value of A to 2 Hex ASCII bytes in HL
; NOTE: L=MSB, H=LSB since strings are usually Hi,Lo eg:"35"
; if we use LD (address),HL then address = L and address+1 = H
;******************************************************************
BYTE2ASCII: LD H,A ; Save A in H
RRA ; Shift Hi 4 Bits to Low 4 Bits
RRA
RRA
RRA
CALL NIB_TOHEX
LD L,A ; MSB->L
LD A,H ; Restore A from H
CALL NIB_TOHEX
LD H,A ; LSB->H
RET
;******************************************************************
; NIB_TOHEX
; Convert Lo 4 bits of A to ASCII of it's HEX value (0-9 or A-F)
;******************************************************************
NIB_TOHEX: AND 0Fh ; Mask Hi 4 Bits
CP 0Ah ; is it 9 or less?
JP M,ADD_30X
ADD A,07h
ADD_30X: ADD A,030h
RET
;******************************************************************
; DASMBITINST
; ML_BUF contains 2 bytes from current memory location.
; If Byte1=0xCB and (Byte2 & 0xC0) > 0 This is a BIR, SET or RES inst.
; Pull the "Bit" value from Byte2 and populate VAL_LO
; Mask the "Bit" indicator bits from byte 2 and do the lookup
;******************************************************************
DASMBITINST:LD B,0CBh ; B=0xCB
LD A,(ML_BUF) ; A=ML_BUF Byte1
CP B ; Compare A with B
JP NZ,DASMBIT_RET ; NoMatch Exit with Z=0
LD A,(ML_BUF+1) ; Get Byte2
AND 0C0h ; AND with 0xCO
JP NZ,DASMBIT_VAL ; Not Zero then this is a BIT,SET or RES
LD A,0FFh ; Otherwise...
JP DASMBITRETN ; Return with Z=0
DASMBIT_VAL:LD A,(ML_BUF+1) ; Get Byte2
AND 038h ; Mask All but 'BIT#' bits
RRA ; Shift Right 3x
RRA
RRA
AND 07h
PUSH HL ; Save Address Pointer
CALL BYTE2ASCII ; Convert A to 2 ASCII Bytes in HL
LD (VAL_BUF_LO),HL ; Store 2 bytes in VAL_BUF_LO
LD A,'0'
LD (VAL_BUF_HI),A
LD (VAL_BUF_HI+1),A ; Store '00' in VAL_BUF_HI
POP HL ; Restore Address pointer
LD A,(ML_BUF+1) ; Get Byte2
AND 0C7h ; AND with 0xC7
LD (ML_BUF+1),A ; Replace MLByte2
DASMBITRETZ:LD A,0 ; Return with Z=1
DASMBITRETN:CP 0 ; Return with Z=0
DASMBIT_RET:RET
;******************************************************************
; DASMGETPARM
; Build the Assembly instruction parameter string from bytes in
; the found row in the lookup table.
; Assumes justified value bytes are already in VAL_BUF if required.
; NOTE: ROW_ADDR is set by successful find by DSMFINDOPCD
;******************************************************************
DASMGETPARM:LD B,7 ; Byte Counter = 7
LD IY,ASM_BUF+5 ; ;IY=Target Address (ASM_BUF+5)
LD IX,(ROW_ADDR) ; IX=Source Address (Table Row Address)
DASM_GETPRM:LD A,(IX) ; Get Parm Byte
CP '*' ; Is it a '*'?
JP NZ,DASM_SAVPAR ; NO=Save Parm byte
CALL ISIXIYPRM ; Is this an (IX*) ot (IY*) Parm?
JP NZ,DASM_MOVVAL ; NO=Just move the value bytes
CALL ISVALBUF0 ; Is VAL_BUF="0"
JP Z,DASM_NXTPR2 ; YES=Skip move of value bytes
LD A,'+'
LD (IY),A ; Store a '+'
INC IY ; Advance Target Address & move value bytes
DASM_MOVVAL:LD C,4 ; Byte count=4
LD HL,VAL_BUF ; HL = VAL_BUF
DASM_MVLOOP:LD A,(HL) ; Get a value byte
CP 0 ; NULL?
JP Z,DASM_SAVH ; YES=DONE goto Save 'h' & continue
LD (IY),A ; Store the value char
INC IY ; Advance destination (ASM_BUF) pointer
INC HL
DEC C
JP NZ,DASM_MVLOOP
DASM_SAVH: LD A,'h' ; Load the 'h'
DASM_SAVPAR:LD (IY),A ; Store parm char
DASM_NXTPAR:INC IY ; Advance Target Address
DASM_NXTPR2:INC IX ; Advance Source Address
DEC B ; Count Source bytes
JP NZ,DASM_GETPRM ; DONE? NO=Continue
RET ; YES= Exit
;******************************************************************
; DASMGETVAL
; Copy 1 or 2 bytes of value data from memory to VAL_BUF
; Data value are converted to ASCII HEX chars in VAL_BUF
; NOTE: ML_BTCOUNT is set by successful find by DSMFINDOPCD
;******************************************************************
DASMGETVAL: LD HL,(ADDR_LO) ; Get memory Address->HL
LD A,(ML_BTCOUNT) ; Get Total Byte count from lookup table
LD B,A ; Save in B
DEC B ; Skip 1 Byte count
INC HL ; Skip 1 byte in memory
LD A,(ML_BUF+1) ; Is this a 2 byte instruction?
CP 0
JP Z,DASMCKBTCNT ; NO= check final byte count
DEC B ; Decrement byte count
INC HL ; Adjust memory pointer
DASMCKBTCNT:LD A,0
CP B ; Is byte count=0?
JP Z,DASM_GVEXIT ; YES=NO Data Bytes expected - Exit
CALL ?GETMEM ; LD A,(HL) ;Get 1st Data Byte from memory
PUSH HL ; Save Address Pointer
CALL BYTE2ASCII ; Convert A to 2 ASCII Bytes in HL
LD (VAL_BUF_LO),HL ; Store 2 bytes in VAL_BUF_LO
POP HL ; Restore Address pointer
DEC B
LD A,0
CP B ; Is byte count=0?
JP Z,DASM_GVEXIT ; YES=NO More Data Bytes expected - Exit
INC HL
CALL ?GETMEM ; LD A,(HL) ;Get 2nd Data Byte from memory
CALL BYTE2ASCII ; Convert A to 2 ASCII Bytes in HL
LD (VAL_BUF_HI),HL ; Store 2 bytes in VAL_BUF_LO
DASM_GVEXIT:RET
;******************************************************************
; DASMGETINST
; Copy 4 byte Assembler Instruction to ASM_BUFF
; NOTE: BLK_ADDR is set by successful find by DSMFINDOPCD
;******************************************************************
DASMGETINST:LD HL,(BLK_ADDR) ; Block Header Row Address ->HL
LD DE,ASM_BUF ; ASM_BUF address->DE
LD B,04h ; Byte Count=4
DASM_MOVINS:INC HL ; Inc Block Header data pointer
LD A,(HL) ; Get 1 byte from Block Header
LD (DE),A ; Save to ASM_BUF
INC DE ; Inc destination (ASM_BUF) pointer
DEC B ; Dec byte count
JP NZ,DASM_MOVINS ; DONE? No=Continue
RET ; YES=Exit
;******************************************************************
; DSMFINDOPCD
; ML_BUF contains 2 bytes from current memory location.
; Search opcode table for a matching opcode
; Return with BLK_ADDR=block header address, ROW_ADDR=found row address
; ML_BYCOUNT=a non-zero count if match was found
;******************************************************************
DSMFINDOPCD:PUSH BC
LD IX,OPCD_TABLE ; Set IX=Table Start Address
DSMFN_LOOP1:LD A,(IX+0)
CP '#' ; Is Row Byte0='#'?
JP NZ,DSMFNCKBT1 ; YES=SAVE IX->BLK_ADDR
LD (BLK_ADDR),IX
JP DSMFNNXTROW
DSMFNCKBT1: LD A,(ML_BUF) ; IS ML_BUF0=(CB,DD,ED or FD)?
CP 0CBh
JP Z,DSMFN_CKBT2
CP 0DDh
JP Z,DSMFN_CKBT2
CP 0EDh
JP Z,DSMFN_CKBT2
CP 0FDh
JP Z,DSMFN_CKBT2
LD C,(IX+7) ; If ML_BUF0 is NOT one of the above
CP C ; Compare with row byte7
JP NZ,DSMFNNXTROW ; NO=Next Row
LD A,0
LD C,(IX+8) ; Get Row Byte8
CP C ; Is it Zero
JP Z,DSMFN_MATCH ; YES=MATCH!
JP DSMFNNXTROW ; NO=Next Row
DSMFN_CKBT2:LD C,(IX+8) ; If ML_BUF0=(CB,DD,ED or FD)?
CP C ; Compare with row byte8
JP NZ,DSMFNNXTROW ; NO=Next Row
LD A,(ML_BUF+1) ; YES=Check Next Byte
LD C,(IX+7) ; Combare with row byte7
CP C
JP Z,DSMFN_MATCH ; YES=MATCH!
DSMFNNXTROW:LD BC,000Ah ; Add 10 to IX and KEEP LOOKING
ADD IX,BC
LD A,(IX+5) ; End Of Lookup Table?
CP 0
JP NZ,DSMFN_LOOP1 ; NO=Keep Looking otherwise EXIT
DSMFN_MATCH:LD (ROW_ADDR),IX ; Save IX->ROW_ADDR
LD A,(IX+8)
LD (ML_BUF+1),A ; Save row byte8 ->ML_BUF1
LD A,(IX+9)
LD (ML_BTCOUNT),A ; Save byte count->ML_BYCOUNT
CP 0 ; Set Z flag if NOT FOUND
POP BC
RET
;******************************************************************
; *** END DIS_MAIN
;******************************************************************
;******************************************************************
; ASM_MAIN Z80 Assembler
; Based on tables used by the TASM for the Z80 target
;******************************************************************
ASM_MAIN: CALL HLHEX ; Print "Enter Address:" and get 4 hex bytes
JP C,DASM_ERR
LD (ADDR),HL
; ** Print CR, LF, ADDR_HI, ADDR_LO (in HEX), space
ASM_LOOP1: CALL NL ; Print CR & LF
LD A,(ADDR_HI) ; Print Address Buffer
CALL PRTHX
LD A,(ADDR_LO)
CALL PRTHX
CALL PRNTS ; Print Space
LD HL,ASM_BUF ; Clear ASM_BUF, INS_BUF, PARM_BUF & VAL_BUF
LD B,30h
CALL MEMSET
LD DE,BUFER ; Use the SA1510 input buffer, it is larger and free format.
CALL GETL
CALL HLHEX ; Check if the address is present, if it is, update address as user may have changed it.
JR C,ASM_LOOP3
LD (ADDR),HL
ASM_LOOP3: LD BC,01005H
LD DE,BUFER+5 ; Skip memory address.
LD HL,ASM_BUF
CALL GETSTR
LD A,0C2H ; Put cursor back to end of input line. Need to use display control for scrolling.
CALL ?DPCT ; Cursor up.
; Clear the line, could have old data on it.
LD A,(SCRNMODE)
LD B,39
OR A
JR Z,ASM_LOOP4
LD B,79
ASM_LOOP4: CALL PRNTS
DJNZ ASM_LOOP4
; Reprint the line, removing leading white space.
LD HL,(DSPXY)
LD L, 0
LD (DSPXY),HL
LD A,(ADDR_HI) ; Print Address Buffer
CALL PRTHX
LD A,(ADDR_LO)
CALL PRTHX
CALL PRNTS ; Print Space
LD DE,ASM_BUF
ASM_LOOP5: LD A,(DE)
CP 000H
JR Z,ASM_LOOP6
CALL PRNT
INC DE
JR ASM_LOOP5
ASM_LOOP6: LD HL,(DSPXY)
LD L, 22
LD (DSPXY),HL ; To end of instruction.
LD A,(ASM_BUF) ; Check 1st byte of ASM_BUF
CP 0 ; Nothing was entered (QUIT)
JP Z,ASM_EXIT ; Just exit
;ASM_LOOP2: CALL PRNTS ; print spaces (16-input length from B)
; INC C
; LD A,C
; CP 0Fh
; JP M,ASM_LOOP2
ASM_CPYINS: LD DE,INS_BUF
LD HL,ASM_BUF
CALL CPY2SPC ; Copy the instruction from ASM_BUF to INST_BUF
CALL SKIPSPC ; find the start of the parm. bytes
LD BC,PARM_BUF
CALL PADWSPC ; Pad the instruction buffer to 4 bytes
;**** Process the input parameter *****
LD A,10h
LD B,A ; Load byte counter =16
GET_NEXTASM:LD A,(HL) ; Get 1 byte from ASM_BUF
CP 0 ; if we reached the end of input?
JP Z,ASMLOOPEXIT ; just exit
CALL ISFLAGORNUM ; Is it $,+,# or 0-9?
JP NZ,SAVE_ASMCHR
CALL ASMGETVAL ; Extract the numbers to VAL_BUF
LD A,'*' ; Load PARM_BUF with a '*'
LD (DE),A
INC DE ; Advance dest. pointer
LD A,(HL) ; Get next non-number byte from ASM_BUF
SAVE_ASMCHR:CP 0 ; if we reached the end while in getval()?
JP Z,ASMLOOPEXIT ; just exit
LD (DE),A ; Otherwise store the byte
INC DE ; Advance dest. pointer
INC HL ; Advance src. pointer
DEC B
JP NZ,GET_NEXTASM
ASMLOOPEXIT:LD BC,VAL_BUF
CALL PADWSPC ; Pad the parm buffer to 7 bytes
LD (SRC_ADDR),HL ; Save HL & DE
LD (DES_ADDR),DE
CALL ASMFINDINST ; Find Instruction in table
LD A,(BLK_SIZE) ; Got a match? YES=search for a parameter match
CP 0
JP NZ,ASM_FINDPRM
ASM_ERR_INS:LD DE,MSGNOINSTR
CALL ?PRINTMSG
JP ASM_LOOP1 ; Get another line of ASM input...
ASM_FINDPRM:CALL ASMFINDPARM ; Look for matching parameter pattern
LD A,(ML_BUF+2) ; Found one? NO=ERROR
CP 0
JP NZ,ASMOUTML
LD DE,MSGNOPARAM
CALL ?PRINTMSG
JP ASM_LOOP1 ; Get another line of ASM input...
ASMOUTML: CALL RTJUSTVAL ; Right Justify VAL_BUF
LD DE,VAL_BUF_HI ; Convert 4 ASCII Chars in VAL_BUF to 2 values
CALL HLHEX
JR C, ASM_ERR_INS ; Couldnt convert the number.
LD A,H
LD (VAL_HI),A
LD A,L
LD (VAL_LO),A
;; Populate OUT_BUF with ML output
LD IX,OUT_BUF
LD A,(ML_BUF+1)
CP 0
JP Z,ASMNOBYTE2
LD (IX),A
INC IX
CP 0CBh ; Is this a BIT,SET or RES Inst?
JP NZ,ASMNOBYTE2 ; NO=Continue
LD A,(ML_BUF) ; YES=Check 1st ML byte
AND 0C0h ; Are Bits 7 or 6 are set?
JP Z,ASMNOBYTE2 ; NO=Continue
LD A,(ML_BUF) ; YES=Combine Val with ML_BUF byte1
LD B,A
LD A,(VAL_LO)
SLA A
SLA A
SLA A
AND 38h
OR B
LD (ML_BUF),A
ASMNOBYTE2: LD A,(ML_BUF)
LD (IX),A
INC IX
LD A,(VAL_LO)
LD (IX),A
INC IX
LD A,(VAL_HI)
LD (IX),A
;; *** Move ML code(s) to target address, ***
;; *** print them and adjust pointer ***
;CALL PRNTS
;CALL PRNTS
;CALL PRNTS
;CALL PRNTS
ASM_TOMEM: LD A,(ML_BTCOUNT) ; Load Byte Count ->B
LD B,A
LD IX,OUT_BUF ; Load IX with OUT_BUF address
ASM_TOMEM1: LD HL,(ADDR_LO) ; Load HL with Target Address
LD A,(IX) ; Get Byte to Move
CALL ?SETMEM ; Store at target address
CALL PRTHX ; Print it
CALL PRNTS ; Print 1 space
INC HL ; Advance Target Pointer
LD (ADDR_LO),HL ; Save in ADDR_LO & HI
INC IX ; Advance ML_BUF pointer
DEC B ; Decrement byte counter
JP NZ,ASM_TOMEM1 ; Done? NO=Continue
JP ASM_LOOP1 ; Get another line of ASM input...
ASM_EXIT: RET
;******************************************************************
; END of ASM_MAIN
;******************************************************************
;******************************************************************
; Z80 Assembler Routines
;******************************************************************
; Method to get a string parameter and copy it into the provided buffer.
; (Duplicate method, also in Bank TZFS1).
; Inputs:
; DE = Pointer to BUFER where user entered data has been placed.
; HL = Pointer to Destination buffer.
; B = Max number of characters to read.
; Outputs:
; DE and HL point to end of bufer and buffer resepectively.
; B = Characters copied (ie. B - input B = no characters).
;
GETSTR: LD A,(DE) ; Skip white space and control characters before copy.
CP 33
JR NC, GSTR1
CP 00DH
JR Z, GSTR2 ; No directory means use the I/O set default.
OR A
JR Z, GSTR2
INC DE
INC C ; Count the characters on the line.
JR GETSTR
GSTR1: LD (HL),A ; Copy the name entered by user. Validation is done on the I/O processor, bad directory name will result in error next read/write.
INC DE
INC HL
INC C ; Count the characters on the line.
LD A,(DE) ; Get next char and check it isnt CR, end of input line character.
CP 00DH
JR Z,GSTR2 ; Finished if we encounter CR.
DJNZ GSTR1 ; Loop until buffer is full, ignore characters beyond buffer limit.
GSTR2: XOR A ; Place end of buffer terminator as I/O processor uses C strings.
LD (HL),A
RET
;******************************************************************
; ASMFINDPARM
; HL=src dest = PARM_BUF
; Search block until match of PARM_BUF or end of block is found
; Return with HL pointing to match block B=block count
;******************************************************************
ASMFINDPARM:PUSH DE
PUSH BC
PUSH HL
LD IX,(BLK_ADDR) ; Load Saved Block Address->IX
LD A,(BLK_SIZE) ; Get Block Size
LD L,A ; L=ROW COUNTER
AFP_NEXTROW:LD DE,000Ah ; 10 bytes per row
ADD IX,DE ; Add 10 to Address (next block)
LD (ROW_ADDR),IX ; Save ROW Address
LD IY,PARM_BUF ; IY=PARM_BUF
LD C,07h ; Loop count =7
AFP_CMPLOOP:LD A,(IX+0) ; Get Table byte->A
LD B,(IY+0) ; Get PARM_BUF byte->B
CP B ; Compare A-B
JP NZ,AFP_NOMATCH ; Mismatch = Exit loop
INC IX ; Advance pointers
INC IY
DEC C ; Decrement loop count
JP NZ,AFP_CMPLOOP ; Not done yet - continue
JP AFP_MATCH ; Match Found Get ML Bytes & Counts
; Match not found, advance to next block
AFP_NOMATCH:DEC L ; Decrement row counter
JP Z,AFP_NOFIND ; Done = NOT FOUND EXIT
LD IX,(ROW_ADDR) ; Get Saved ROW Address->IX
JP AFP_NEXTROW ; Continue
AFP_NOFIND: LD A,0 ; Not Found set ML_BUF[2]=0
LD (ML_BUF+2),A
JP AFP_EXIT
AFP_MATCH: LD A,(IX+0) ; Get Table ML Byte 1
LD (ML_BUF),A ; Save it in M_BUF[0]
LD A,(IX+1) ; Get Table ML Byte 2
LD (ML_BUF+1),A ; Save it in M_BUF[1]
LD A,(IX+2) ; Get Table ML Byte count
LD (ML_BUF+2),A ; Save it in M_BUF[2]
AFP_EXIT: POP HL
POP BC
POP DE
RET
;******************************************************************
; ASMFINDINST
; HL=src dest = VAL_BUF
; Search table until match of INS_BUF or end of table is found
; Return with IX pointing to match block B=block count
;******************************************************************
ASMFINDINST:PUSH DE
PUSH BC
LD A,0
LD (ROW_NUM),A
LD IX,OPCD_TABLE
AFI_NEXTBLK:LD (BLK_ADDR),IX ; Save Block Address
LD A,(IX+5) ; Get Block Size & Save
LD (BLK_SIZE),A
CP 0 ; If Block Size = 0 EXIT
JP Z,AFI_EXIT
LD IY,INS_BUF ; IX=INS_BUF
LD C,04h ; Loop count =4
AFI_CMPLOOP:LD A,(IX+1) ; Get Table byte->A
LD B,(IY+0) ; Get INS_BUF byte->B
CP B ; Compare A-B
JP NZ,AFI_NOMATCH ; Mismatch = Exit loop
INC IX ; Advance pointers
INC IY
DEC C ; Decremebnt loop count
JP NZ,AFI_CMPLOOP ; Not done yet - continue
JP AFI_EXIT ; Match Found EXIT
; Match not found, advance to next block
AFI_NOMATCH:LD A,(BLK_SIZE) ; Get Block Size
INC A ; Add 1 to Block count
LD IX,(BLK_ADDR) ; Get Saved Block Start Address
LD DE,000Ah ; 10 bytes per row
AFI_BLKLOOP:ADD IX,DE ; Add 10 to Address
DEC A ; Decrement block counter
JP NZ,AFI_BLKLOOP ; Not Done = loop
LD A,(ROW_NUM) ; Advance Row Number
INC A
LD (ROW_NUM),A
JP AFI_NEXTBLK
AFI_EXIT: POP BC
POP DE
RET
;******************************************************************
; ASMRTJVAL
; Shift bytes in VAL_BUF right until left padded with '0's
;******************************************************************
ASMRJTVAL: PUSH DE
PUSH BC
LD IX,VAL_BUF
LD B,05h ; B=MAX search count 5
ASMRJT_LOOP:LD A,(IX+3) ; Get last byte from VAL_BUF
CP ' ' ; Is It SPACE?
JP NZ,ASMRJT_EXIT ; Exit
LD A,(IX+2) ; Shift 3 bytes left 1 positiom
LD (IX+3),A
LD A,(IX+1)
LD (IX+2),A
LD A,(IX+0)
LD (IX+1),A
LD A,'0' ; Pad first position with '0'
LD (IX+0),A
DEC B
JP NZ,ASMRJT_LOOP
ASMRJT_EXIT:POP BC
POP DE
RET
;******************************************************************
; ASMGETVAL
; HL=src dest = VAL_BUF
; Copy bytes from src to dest until a non digit is encountered (4 bytes max.)
; skip over number flags ('$','+,'#')
;******************************************************************
ASMGETVAL: PUSH DE
PUSH BC
LD DE,VAL_BUF
LD B,05h ; B=MAX search count 5
ASMGVL_LOOP:LD A,(HL) ; Get a byte from ASM_BUF
CP 0 ; End of input?
JP Z,ASMGVL_EXIT ; Exit
CALL ISVALFLAG ; Test A for '#' '$' or '+'
JP Z,ASMGVL_SKIP ; If match then just skip it
CALL IS_DIGIT ; Is A= '0'-'9' or 'A'-'F'?
JP NZ,ASMGVL_EXIT
LD (DE),A ; Save the byte to VAL_BUF
INC DE ; Advance the destination pointer
ASMGVL_SKIP:INC HL ; Advance the sourc pointer
DEC B ; Decrement byte count
JP NZ,ASMGVL_LOOP ; Max reached? NO=Continue
ASMGVL_EXIT:POP BC
POP DE
RET
;******************************************************************
; ISFLAGORNUM
;
; RETURN Z=1 if A = '$', '+' ,'#' or '0'-'9'
;******************************************************************
ISFLAGORNUM:CALL ISVALFLAG ; is A ='$','#' or '+'?
JP Z,ISNUMF_ZRET ; YES=return Z=1
CALL ISDECDIGIT ; Test for '0-'9'
ISNUMF_ZRET:RET ;(Z is set accordingly)
;******************************************************************
; ISVALFLAG
;
; RETURN Z=1 if A = '$', '+' ,'#' or '0'-'9' (A is unchanged )
; NOTE: A MUST be a non-zero ASCII Digit
;******************************************************************
ISVALFLAG: CP '$' ; is A ='$'?
JP Z,ISVALF_ZRET ; YES=return Z=1
CP '+' ; is A ='+'?
JP Z,ISVALF_ZRET ; YES=return Z=1
CP '#' ; is A ='#'?
JP Z,ISVALF_ZRET ; YES=return Z=1
CP 0 ; Otherwise set Z=0
ISVALF_ZRET:RET
;******************************************************************
; PADWSPC
; DE=dest BC=END
; starting at current DE fill with spaces until DE=BC
; NOTE: BC MUST BE > DE no bounds checking is done
;******************************************************************
PADWSPC: LD A,B
CP D
JP NZ,DOPADWSPC
LD A,C
CP E
JP M,PADWSP_EXIT
JP NZ,DOPADWSPC
PADWSP_EXIT:RET
DOPADWSPC: LD A,' '
LD (DE),A
INC DE
JP PADWSPC
;******************************************************************
; SKIPSPC
; HL=src b=MAX
; advance HL until it is pointing at a non-space byte (16 bytes max.)
;******************************************************************
SKIPSPC: LD B,10h ; B= MAX byte count 16
SKIPSP_LOOP:LD A,(HL)
INC HL
CP ' '
JP Z,SKIPSP_EXIT
CP 0
JP Z,SKIPSP_EXIT
DEC B
JP NZ,SKIPSP_LOOP
SKIPSP_EXIT:RET
;******************************************************************
; CPY2SPC
; HL=src DE=dest b=count
; Copy bytes from src to dest until a space is encountered (12 bytes max.)
;******************************************************************
CPY2SPC: LD B,0Ch ; B= MAX byte count 12
CPY2SP_LOOP:LD A,(HL)
CP ' '
JP Z,CPY2SP_EXIT ; Found space so EXIT
CP 0
JP NZ,CPY2SP_COPY ; Found NULL before space
LD A,' '
LD (HL),A ; Replace with space & exit
INC HL
LD A,0 ; Terminate
LD (HL),A
DEC HL
JP CPY2SP_EXIT
CPY2SP_COPY:LD (DE),A ; Copy the byte
INC DE ; Advance destination pointer
INC HL ; Advance source pointer
DEC B ; Decremet byte count
JP NZ,CPY2SP_LOOP ; If MAX not reached continue...
CPY2SP_EXIT:RET
;-------------------------------------------------------------------------------
; Z80 Assembler lookup table
; FORMAT: 10 bytes per row
; Instruction Blocks: start with # followed by 4 char instruction
; byte 5 = #of rows for this instruction
; Parameter Blocks: A 7 byte parameter pattern
; Opcode byte 1, Opcode byte 2(if any otherwise zero)
; Number of byte used for opcodes & data parameters.
;-------------------------------------------------------------------------------
OPCD_TABLE: DB "#ADC ", 00FH, 000H, 000H, 000H, 000H
DB "A,(HL) ", 08EH, 000H, 001H
DB "A,(IX*)", 08EH, 0DDH, 003H
DB "A,(IY*)", 08EH, 0FDH, 003H
DB "A,A ", 08FH, 000H, 001H
DB "A,B ", 088H, 000H, 001H
DB "A,C ", 089H, 000H, 001H
DB "A,D ", 08AH, 000H, 001H
DB "A,E ", 08BH, 000H, 001H
DB "A,H ", 08CH, 000H, 001H
DB "A,L ", 08DH, 000H, 001H
DB "A,* ", 0CEH, 000H, 002H
DB "HL,BC ", 04AH, 0EDH, 002H
DB "HL,DE ", 05AH, 0EDH, 002H
DB "HL,HL ", 06AH, 0EDH, 002H
DB "HL,SP ", 07AH, 0EDH, 002H
DB "#ADD ", 017H, 000H, 000H, 000H, 000H
DB "A,(HL) ", 086H, 000H, 001H
DB "A,(IX*)", 086H, 0DDH, 003H
DB "A,(IY*)", 086H, 0FDH, 003H
DB "A,A ", 087H, 000H, 001H
DB "A,B ", 080H, 000H, 001H
DB "A,C ", 081H, 000H, 001H
DB "A,D ", 082H, 000H, 001H
DB "A,E ", 083H, 000H, 001H
DB "A,H ", 084H, 000H, 001H
DB "A,L ", 085H, 000H, 001H
DB "A,* ", 0C6H, 000H, 002H
DB "HL,BC ", 009H, 000H, 001H
DB "HL,DE ", 019H, 000H, 001H
DB "HL,HL ", 029H, 000H, 001H
DB "HL,SP ", 039H, 000H, 001H
DB "IX,BC ", 009H, 0DDH, 002H
DB "IX,DE ", 019H, 0DDH, 002H
DB "IX,IX ", 029H, 0DDH, 002H
DB "IX,SP ", 039H, 0DDH, 002H
DB "IY,BC ", 009H, 0FDH, 002H
DB "IY,DE ", 019H, 0FDH, 002H
DB "IY,IY ", 029H, 0FDH, 002H
DB "IY,SP ", 039H, 0FDH, 002H
DB "#AND ", 00BH, 000H, 000H, 000H, 000H
DB "(HL) ", 0A6H, 000H, 001H
DB "(IX*) ", 0A6H, 0DDH, 003H
DB "(IY*) ", 0A6H, 0FDH, 003H
DB "A ", 0A7H, 000H, 001H
DB "B ", 0A0H, 000H, 001H
DB "C ", 0A1H, 000H, 001H
DB "D ", 0A2H, 000H, 001H
DB "E ", 0A3H, 000H, 001H
DB "H ", 0A4H, 000H, 001H
DB "L ", 0A5H, 000H, 001H
DB "* ", 0E6H, 000H, 002H
DB "#BIT ", 008H, 000H, 000H, 000H, 000H
DB "*,(HL) ", 046H, 0CBH, 002H
DB "*,A ", 047H, 0CBH, 002H
DB "*,B ", 040H, 0CBH, 002H
DB "*,C ", 041H, 0CBH, 002H
DB "*,D ", 042H, 0CBH, 002H
DB "*,E ", 043H, 0CBH, 002H
DB "*,H ", 044H, 0CBH, 002H
DB "*,L ", 045H, 0CBH, 002H
DB "#CALL", 009H, 000H, 000H, 000H, 000H
DB "C,* ", 0DCH, 000H, 003H
DB "M,* ", 0FCH, 000H, 003H
DB "NC,* ", 0D4H, 000H, 003H
DB "NZ,* ", 0C4H, 000H, 003H
DB "P,* ", 0F4H, 000H, 003H
DB "PE,* ", 0ECH, 000H, 003H
DB "PO,* ", 0E4H, 000H, 003H
DB "Z,* ", 0CCH, 000H, 003H
DB "* ", 0CDH, 000H, 003H
DB "#CCF ", 001H, 000H, 000H, 000H, 000H
DB " ", 03FH, 000H, 001H
DB "#CP ", 00BH, 000H, 000H, 000H, 000H
DB "(HL) ", 0BEH, 000H, 001H
DB "(IX*) ", 0BEH, 0DDH, 003H
DB "(IY*) ", 0BEH, 0FDH, 003H
DB "A ", 0BFH, 000H, 001H
DB "B ", 0B8H, 000H, 001H
DB "C ", 0B9H, 000H, 001H
DB "D ", 0BAH, 000H, 001H
DB "E ", 0BBH, 000H, 001H
DB "H ", 0BCH, 000H, 001H
DB "L ", 0BDH, 000H, 001H
DB "* ", 0FEH, 000H, 002H
DB "#CPD ", 001H, 000H, 000H, 000H, 000H
DB " ", 0A9H, 0EDH, 002H
DB "#CPDR", 001H, 000H, 000H, 000H, 000H
DB " ", 0B9H, 0EDH, 002H
DB "#CPIR", 001H, 000H, 000H, 000H, 000H
DB " ", 0B1H, 0EDH, 002H
DB "#CPI ", 001H, 000H, 000H, 000H, 000H
DB " ", 0A1H, 0EDH, 002H
DB "#CPL ", 001H, 000H, 000H, 000H, 000H
DB " ", 02FH, 000H, 001H
DB "#DAA ", 001H, 000H, 000H, 000H, 000H
DB " ", 027H, 000H, 001H
DB "#DEC ", 010H, 000H, 000H, 000H, 000H
DB "(HL) ", 035H, 000H, 001H
DB "(IX*) ", 035H, 0DDH, 003H
DB "(IY*) ", 035H, 0FDH, 003H
DB "A ", 03DH, 000H, 001H
DB "B ", 005H, 000H, 001H
DB "BC ", 00BH, 000H, 001H
DB "C ", 00DH, 000H, 001H
DB "D ", 015H, 000H, 001H
DB "DE ", 01BH, 000H, 001H
DB "E ", 01DH, 000H, 001H
DB "H ", 025H, 000H, 001H
DB "HL ", 02BH, 000H, 001H
DB "IX ", 02BH, 0DDH, 002H
DB "IY ", 02BH, 0FDH, 002H
DB "L ", 02DH, 000H, 001H
DB "SP ", 03BH, 000H, 001H
DB "#DI ", 001H, 000H, 000H, 000H, 000H
DB " ", 0F3H, 000H, 001H
DB "#DJNZ", 001H, 000H, 000H, 000H, 000H
DB "* ", 010H, 000H, 002H
DB "#EI ", 001H, 000H, 000H, 000H, 000H
DB " ", 0FBH, 000H, 001H
DB "#EX ", 005H, 000H, 000H, 000H, 000H
DB "(SP),HL", 0E3H, 000H, 001H
DB "(SP),IX", 0E3H, 0DDH, 002H
DB "(SP),IY", 0E3H, 0FDH, 002H
DB "AF,AF", 02CH, 020H, 008H, 000H, 001H
DB "DE,HL ", 0EBH, 000H, 001H
DB "#EXX ", 001H, 000H, 000H, 000H, 000H
DB " ", 0D9H, 000H, 001H
DB "#HALT", 001H, 000H, 000H, 000H, 000H
DB " ", 076H, 000H, 001H
DB "#IM ", 003H, 000H, 000H, 000H, 000H
DB "0 ", 046H, 0EDH, 002H
DB "1 ", 056H, 0EDH, 002H
DB "2 ", 05EH, 0EDH, 002H
DB "#IN ", 008H, 000H, 000H, 000H, 000H
DB "A,(C) ", 078H, 0EDH, 002H
DB "B,(C) ", 040H, 0EDH, 002H
DB "C,(C) ", 048H, 0EDH, 002H
DB "D,(C) ", 050H, 0EDH, 002H
DB "E,(C) ", 058H, 0EDH, 002H
DB "H,(C) ", 060H, 0EDH, 002H
DB "L,(C) ", 068H, 0EDH, 002H
DB "A,(*) ", 0DBH, 000H, 002H
DB "#IN0 ", 007H, 000H, 000H, 000H, 000H
DB " A,(*) ", 038H, 0EDH, 003H
DB " B,(*) ", 000H, 0EDH, 003H
DB " C,(*) ", 008H, 0EDH, 003H
DB " D,(*) ", 010H, 0EDH, 003H
DB " E,(*) ", 018H, 0EDH, 003H
DB " H,(*) ", 020H, 0EDH, 003H
DB " L,(*) ", 028H, 0EDH, 003H
DB "#INC ", 010H, 000H, 000H, 000H, 000H
DB "(HL) ", 034H, 000H, 001H
DB "(IX*) ", 034H, 0DDH, 003H
DB "(IY*) ", 034H, 0FDH, 003H
DB "A ", 03CH, 000H, 001H
DB "B ", 004H, 000H, 001H
DB "BC ", 003H, 000H, 001H
DB "C ", 00CH, 000H, 001H
DB "D ", 014H, 000H, 001H
DB "DE ", 013H, 000H, 001H
DB "E ", 01CH, 000H, 001H
DB "H ", 024H, 000H, 001H
DB "HL ", 023H, 000H, 001H
DB "IX ", 023H, 0DDH, 002H
DB "IY ", 023H, 0FDH, 002H
DB "L ", 02CH, 000H, 001H
DB "SP ", 033H, 000H, 001H
DB "#IND ", 001H, 000H, 000H, 000H, 000H
DB " ", 0AAH, 0EDH, 002H
DB "#INDR", 001H, 000H, 000H, 000H, 000H
DB " ", 0BAH, 0EDH, 002H
DB "#INI ", 001H, 000H, 000H, 000H, 000H
DB " ", 0A2H, 0EDH, 002H
DB "#INIR", 001H, 000H, 000H, 000H, 000H
DB " ", 0B2H, 0EDH, 002H
DB "#JP ", 00CH, 000H, 000H, 000H, 000H
DB "(HL) ", 0E9H, 000H, 001H
DB "(IX) ", 0E9H, 0DDH, 002H
DB "(IY) ", 0E9H, 0FDH, 002H
DB "C,* ", 0DAH, 000H, 003H
DB "M,* ", 0FAH, 000H, 003H
DB "NC,* ", 0D2H, 000H, 003H
DB "NZ,* ", 0C2H, 000H, 003H
DB "P,* ", 0F2H, 000H, 003H
DB "PE,* ", 0EAH, 000H, 003H
DB "PO,* ", 0E2H, 000H, 003H
DB "Z,* ", 0CAH, 000H, 003H
DB "* ", 0C3H, 000H, 003H
DB "#JR ", 005H, 000H, 000H, 000H, 000H
DB "C,* ", 038H, 000H, 002H
DB "NC,* ", 030H, 000H, 002H
DB "NZ,* ", 020H, 000H, 002H
DB "Z,* ", 028H, 000H, 002H
DB "* ", 018H, 000H, 002H
DB "#LD ", 084H, 000H, 000H, 000H, 000H
DB "(BC),A ", 002H, 000H, 001H
DB "(DE),A ", 012H, 000H, 001H
DB "(HL),A ", 077H, 000H, 001H
DB "(HL),B ", 070H, 000H, 001H
DB "(HL),C ", 071H, 000H, 001H
DB "(HL),D ", 072H, 000H, 001H
DB "(HL),E ", 073H, 000H, 001H
DB "(HL),H ", 074H, 000H, 001H
DB "(HL),L ", 075H, 000H, 001H
DB "(HL),* ", 036H, 000H, 002H
DB "(IX*),A", 077H, 0DDH, 003H
DB "(IX*),B", 070H, 0DDH, 003H
DB "(IX*),C", 071H, 0DDH, 003H
DB "(IX*),D", 072H, 0DDH, 003H
DB "(IX*),E", 073H, 0DDH, 003H
DB "(IX*),H", 074H, 0DDH, 003H
DB "(IX*),L", 075H, 0DDH, 003H
DB "(IX*),*", 036H, 0DDH, 004H
DB "(IY*),A", 077H, 0FDH, 003H
DB "(IY*),B", 070H, 0FDH, 003H
DB "(IY*),C", 071H, 0FDH, 003H
DB "(IY*),D", 072H, 0FDH, 003H
DB "(IY*),E", 073H, 0FDH, 003H
DB "(IY*),H", 074H, 0FDH, 003H
DB "(IY*),L", 075H, 0FDH, 003H
DB "(IY*),*", 036H, 0FDH, 004H
DB "(*),A ", 032H, 000H, 003H
DB "(*),BC ", 043H, 0EDH, 004H
DB "(*),DE ", 053H, 0EDH, 004H
DB "(*),HL ", 022H, 000H, 003H
DB "(*),IX ", 022H, 0DDH, 004H
DB "(*),IY ", 022H, 0FDH, 004H
DB "(*),SP ", 073H, 0EDH, 004H
DB "A,(BC) ", 00AH, 000H, 001H
DB "A,(DE) ", 01AH, 000H, 001H
DB "A,(HL) ", 07EH, 000H, 001H
DB "A,(IX*)", 07EH, 0DDH, 003H
DB "A,(IY*)", 07EH, 0FDH, 003H
DB "A,A ", 07FH, 000H, 001H
DB "A,B ", 078H, 000H, 001H
DB "A,C ", 079H, 000H, 001H
DB "A,D ", 07AH, 000H, 001H
DB "A,E ", 07BH, 000H, 001H
DB "A,H ", 07CH, 000H, 001H
DB "A,I ", 057H, 0EDH, 002H
DB "A,L ", 07DH, 000H, 001H
DB "A,R ", 05FH, 0EDH, 002H
DB "A,(*) ", 03AH, 000H, 003H
DB "A,* ", 03EH, 000H, 002H
DB "B,(HL) ", 046H, 000H, 001H
DB "B,(IX*)", 046H, 0DDH, 003H
DB "B,(IY*)", 046H, 0FDH, 003H
DB "B,A ", 047H, 000H, 001H
DB "B,B ", 040H, 000H, 001H
DB "B,C ", 041H, 000H, 001H
DB "B,D ", 042H, 000H, 001H
DB "B,E ", 043H, 000H, 001H
DB "B,H ", 044H, 000H, 001H
DB "B,L ", 045H, 000H, 001H
DB "B,* ", 006H, 000H, 002H
DB "BC,(*) ", 04BH, 0EDH, 004H
DB "BC,* ", 001H, 000H, 003H
DB "C,(HL) ", 04EH, 000H, 001H
DB "C,(IX*)", 04EH, 0DDH, 003H
DB "C,(IY*)", 04EH, 0FDH, 003H
DB "C,A ", 04FH, 000H, 001H
DB "C,B ", 048H, 000H, 001H
DB "C,C ", 049H, 000H, 001H
DB "C,D ", 04AH, 000H, 001H
DB "C,E ", 04BH, 000H, 001H
DB "C,H ", 04CH, 000H, 001H
DB "C,L ", 04DH, 000H, 001H
DB "C,* ", 00EH, 000H, 002H
DB "D,(HL) ", 056H, 000H, 001H
DB "D,(IX*)", 056H, 0DDH, 003H
DB "D,(IY*)", 056H, 0FDH, 003H
DB "D,A ", 057H, 000H, 001H
DB "D,B ", 050H, 000H, 001H
DB "D,C ", 051H, 000H, 001H
DB "D,D ", 052H, 000H, 001H
DB "D,E ", 053H, 000H, 001H
DB "D,H ", 054H, 000H, 001H
DB "D,L ", 055H, 000H, 001H
DB "D,* ", 016H, 000H, 002H
DB "DE,(*) ", 05BH, 0EDH, 004H
DB "DE,* ", 011H, 000H, 003H
DB "E,(HL) ", 05EH, 000H, 001H
DB "E,(IX*)", 05EH, 0DDH, 003H
DB "E,(IY*)", 05EH, 0FDH, 003H
DB "E,A ", 05FH, 000H, 001H
DB "E,B ", 058H, 000H, 001H
DB "E,C ", 059H, 000H, 001H
DB "E,D ", 05AH, 000H, 001H
DB "E,E ", 05BH, 000H, 001H
DB "E,H ", 05CH, 000H, 001H
DB "E,L ", 05DH, 000H, 001H
DB "E,* ", 01EH, 000H, 002H
DB "H,(HL) ", 066H, 000H, 001H
DB "H,(IX*)", 066H, 0DDH, 003H
DB "H,(IY*)", 066H, 0FDH, 003H
DB "H,A ", 067H, 000H, 001H
DB "H,B ", 060H, 000H, 001H
DB "H,C ", 061H, 000H, 001H
DB "H,D ", 062H, 000H, 001H
DB "H,E ", 063H, 000H, 001H
DB "H,H ", 064H, 000H, 001H
DB "H,L ", 065H, 000H, 001H
DB "H,* ", 026H, 000H, 002H
DB "HL,(*) ", 02AH, 000H, 003H
DB "HL,* ", 021H, 000H, 003H
DB "I,A ", 047H, 0EDH, 002H
DB "IX,(*) ", 02AH, 0DDH, 004H
DB "IX,* ", 021H, 0DDH, 004H
DB "IY,(*) ", 02AH, 0FDH, 004H
DB "IY,* ", 021H, 0FDH, 004H
DB "L,(HL) ", 06EH, 000H, 001H
DB "L,(IX*)", 06EH, 0DDH, 003H
DB "L,(IY*)", 06EH, 0FDH, 003H
DB "L,A ", 06FH, 000H, 001H
DB "L,B ", 068H, 000H, 001H
DB "L,C ", 069H, 000H, 001H
DB "L,D ", 06AH, 000H, 001H
DB "L,E ", 06BH, 000H, 001H
DB "L,H ", 06CH, 000H, 001H
DB "L,L ", 06DH, 000H, 001H
DB "L,* ", 02EH, 000H, 002H
DB "R,A ", 04FH, 0EDH, 002H
DB "SP,(*) ", 07BH, 0EDH, 004H
DB "SP,HL ", 0F9H, 000H, 001H
DB "SP,IX ", 0F9H, 0DDH, 002H
DB "SP,IY ", 0F9H, 0FDH, 002H
DB "SP,* ", 031H, 000H, 003H
DB "#LDD ", 001H, 000H, 000H, 000H, 000H
DB " ", 0A8H, 0EDH, 002H
DB "#LDDR", 001H, 000H, 000H, 000H, 000H
DB " ", 0B8H, 0EDH, 002H
DB "#LDI ", 001H, 000H, 000H, 000H, 000H
DB " ", 0A0H, 0EDH, 002H
DB "#LDIR", 001H, 000H, 000H, 000H, 000H
DB " ", 0B0H, 0EDH, 002H
DB "#NEG ", 001H, 000H, 000H, 000H, 000H
DB " ", 044H, 0EDH, 002H
DB "#NOP ", 001H, 000H, 000H, 000H, 000H
DB " ", 000H, 000H, 001H
DB "#OR ", 00BH, 000H, 000H, 000H, 000H
DB "(HL) ", 0B6H, 000H, 001H
DB "(IX*) ", 0B6H, 0DDH, 003H
DB "(IY*) ", 0B6H, 0FDH, 003H
DB "A ", 0B7H, 000H, 001H
DB "B ", 0B0H, 000H, 001H
DB "C ", 0B1H, 000H, 001H
DB "D ", 0B2H, 000H, 001H
DB "E ", 0B3H, 000H, 001H
DB "H ", 0B4H, 000H, 001H
DB "L ", 0B5H, 000H, 001H
DB "* ", 0F6H, 000H, 002H
DB "#OTDR", 001H, 000H, 000H, 000H, 000H
DB " ", 0BBH, 0EDH, 002H
DB "#OTIR", 001H, 000H, 000H, 000H, 000H
DB " ", 0B3H, 0EDH, 002H
DB "#OUT ", 008H, 000H, 000H, 000H, 000H
DB "(C),A ", 079H, 0EDH, 002H
DB "(C),B ", 041H, 0EDH, 002H
DB "(C),C ", 049H, 0EDH, 002H
DB "(C),D ", 051H, 0EDH, 002H
DB "(C),E ", 059H, 0EDH, 002H
DB "(C),H ", 061H, 0EDH, 002H
DB "(C),L ", 069H, 0EDH, 002H
DB "(*),A ", 0D3H, 000H, 002H
DB "#OUT0", 007H, 000H, 000H, 000H, 000H
DB "(*),A ", 039H, 0EDH, 003H
DB "(*),B ", 001H, 0EDH, 003H
DB "(*),C ", 009H, 0EDH, 003H
DB "(*),D ", 011H, 0EDH, 003H
DB "(*),E ", 019H, 0EDH, 003H
DB "(*),H ", 021H, 0EDH, 003H
DB "(*),L ", 029H, 0EDH, 003H
DB "#OUTD", 001H, 000H, 000H, 000H, 000H
DB " ", 0ABH, 0EDH, 002H
DB "#OUTI", 001H, 000H, 000H, 000H, 000H
DB " ", 0A3H, 0EDH, 002H
DB "#POP ", 006H, 000H, 000H, 000H, 000H
DB "AF ", 0F1H, 000H, 001H
DB "BC ", 0C1H, 000H, 001H
DB "DE ", 0D1H, 000H, 001H
DB "HL ", 0E1H, 000H, 001H
DB "IX ", 0E1H, 0DDH, 002H
DB "IY ", 0E1H, 0FDH, 002H
DB "#PUSH", 006H, 000H, 000H, 000H, 000H
DB "AF ", 0F5H, 000H, 001H
DB "BC ", 0C5H, 000H, 001H
DB "DE ", 0D5H, 000H, 001H
DB "HL ", 0E5H, 000H, 001H
DB "IX ", 0E5H, 0DDH, 002H
DB "IY ", 0E5H, 0FDH, 002H
DB "#RES ", 008H, 000H, 000H, 000H, 000H
DB "*,(HL) ", 086H, 0CBH, 002H
DB "*,A ", 087H, 0CBH, 002H
DB "*,B ", 080H, 0CBH, 002H
DB "*,C ", 081H, 0CBH, 002H
DB "*,D ", 082H, 0CBH, 002H
DB "*,E ", 083H, 0CBH, 002H
DB "*,H ", 084H, 0CBH, 002H
DB "*,L ", 085H, 0CBH, 002H
DB "#RET ", 009H, 000H, 000H, 000H, 000H
DB " ", 0C9H, 000H, 001H
DB "C ", 0D8H, 000H, 001H
DB "M ", 0F8H, 000H, 001H
DB "NC ", 0D0H, 000H, 001H
DB "NZ ", 0C0H, 000H, 001H
DB "P ", 0F0H, 000H, 001H
DB "PE ", 0E8H, 000H, 001H
DB "PO ", 0E0H, 000H, 001H
DB "Z ", 0C8H, 000H, 001H
DB "#RETI", 001H, 000H, 000H, 000H, 000H
DB " ", 04DH, 0EDH, 002H
DB "#RETN", 001H, 000H, 000H, 000H, 000H
DB " ", 045H, 0EDH, 002H
DB "#RL ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 016H, 0CBH, 002H
DB "A ", 017H, 0CBH, 002H
DB "B ", 010H, 0CBH, 002H
DB "C ", 011H, 0CBH, 002H
DB "D ", 012H, 0CBH, 002H
DB "E ", 013H, 0CBH, 002H
DB "H ", 014H, 0CBH, 002H
DB "L ", 015H, 0CBH, 002H
DB "#RLA ", 001H, 000H, 000H, 000H, 000H
DB " ", 017H, 000H, 001H
DB "#RLC ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 006H, 0CBH, 002H
DB "A ", 007H, 0CBH, 002H
DB "B ", 000H, 0CBH, 002H
DB "C ", 001H, 0CBH, 002H
DB "D ", 002H, 0CBH, 002H
DB "E ", 003H, 0CBH, 002H
DB "H ", 004H, 0CBH, 002H
DB "L ", 005H, 0CBH, 002H
DB "#RLCA", 001H, 000H, 000H, 000H, 000H
DB " ", 007H, 000H, 001H
DB "#RLD ", 001H, 000H, 000H, 000H, 000H
DB " ", 06FH, 0EDH, 002H
DB "#RR ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 01EH, 0CBH, 002H
DB "A ", 01FH, 0CBH, 002H
DB "B ", 018H, 0CBH, 002H
DB "C ", 019H, 0CBH, 002H
DB "D ", 01AH, 0CBH, 002H
DB "E ", 01BH, 0CBH, 002H
DB "H ", 01CH, 0CBH, 002H
DB "L ", 01DH, 0CBH, 002H
DB "#RRA ", 001H, 000H, 000H, 000H, 000H
DB " ", 01FH, 000H, 001H
DB "#RRC ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 00EH, 0CBH, 002H
DB "A ", 00FH, 0CBH, 002H
DB "B ", 008H, 0CBH, 002H
DB "C ", 009H, 0CBH, 002H
DB "D ", 00AH, 0CBH, 002H
DB "E ", 00BH, 0CBH, 002H
DB "H ", 00CH, 0CBH, 002H
DB "L ", 00DH, 0CBH, 002H
DB "#RRCA", 001H, 000H, 000H, 000H, 000H
DB " ", 00FH, 000H, 001H
DB "#RRD ", 001H, 000H, 000H, 000H, 000H
DB " ", 067H, 0EDH, 002H
DB "#RST ", 008H, 000H, 000H, 000H, 000H
DB "00H ", 0C7H, 000H, 001H
DB "08H ", 0CFH, 000H, 001H
DB "10H ", 0D7H, 000H, 001H
DB "18H ", 0DFH, 000H, 001H
DB "20H ", 0E7H, 000H, 001H
DB "28H ", 0EFH, 000H, 001H
DB "30H ", 0F7H, 000H, 001H
DB "38H ", 0FFH, 000H, 001H
DB "#SBC ", 00FH, 000H, 000H, 000H, 000H
DB "A,(HL) ", 09EH, 000H, 001H
DB "A,(IX*)", 09EH, 0DDH, 003H
DB "A,(IY*)", 09EH, 0FDH, 003H
DB "A,A ", 09FH, 000H, 001H
DB "A,B ", 098H, 000H, 001H
DB "A,C ", 099H, 000H, 001H
DB "A,D ", 09AH, 000H, 001H
DB "A,E ", 09BH, 000H, 001H
DB "A,H ", 09CH, 000H, 001H
DB "A,L ", 09DH, 000H, 001H
DB "HL,BC ", 042H, 0EDH, 002H
DB "HL,DE ", 052H, 0EDH, 002H
DB "HL,HL ", 062H, 0EDH, 002H
DB "HL,SP ", 072H, 0EDH, 002H
DB "A,* ", 0DEH, 000H, 002H
DB "#SCF ", 001H, 000H, 000H, 000H, 000H
DB " ", 037H, 000H, 001H
DB "#SET ", 008H, 000H, 000H, 000H, 000H
DB "*,(HL) ", 0C6H, 0CBH, 002H
DB "*,A ", 0C7H, 0CBH, 002H
DB "*,B ", 0C0H, 0CBH, 002H
DB "*,C ", 0C1H, 0CBH, 002H
DB "*,D ", 0C2H, 0CBH, 002H
DB "*,E ", 0C3H, 0CBH, 002H
DB "*,H ", 0C4H, 0CBH, 002H
DB "*,L ", 0C5H, 0CBH, 002H
DB "#SLA ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 026H, 0CBH, 002H
DB "A ", 027H, 0CBH, 002H
DB "B ", 020H, 0CBH, 002H
DB "C ", 021H, 0CBH, 002H
DB "D ", 022H, 0CBH, 002H
DB "E ", 023H, 0CBH, 002H
DB "H ", 024H, 0CBH, 002H
DB "L ", 025H, 0CBH, 002H
DB "#SRA ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 02EH, 0CBH, 002H
DB "A ", 02FH, 0CBH, 002H
DB "B ", 028H, 0CBH, 002H
DB "C ", 029H, 0CBH, 002H
DB "D ", 02AH, 0CBH, 002H
DB "E ", 02BH, 0CBH, 002H
DB "H ", 02CH, 0CBH, 002H
DB "L ", 02DH, 0CBH, 002H
DB "#SRL ", 008H, 000H, 000H, 000H, 000H
DB "(HL) ", 03EH, 0CBH, 002H
DB "A ", 03FH, 0CBH, 002H
DB "B ", 038H, 0CBH, 002H
DB "C ", 039H, 0CBH, 002H
DB "D ", 03AH, 0CBH, 002H
DB "E ", 03BH, 0CBH, 002H
DB "H ", 03CH, 0CBH, 002H
DB "L ", 03DH, 0CBH, 002H
DB "#SUB ", 00BH, 000H, 000H, 000H, 000H
DB "(HL) ", 096H, 000H, 001H
DB "(IX*) ", 096H, 0DDH, 003H
DB "(IY*) ", 096H, 0FDH, 003H
DB "A ", 097H, 000H, 001H
DB "B ", 090H, 000H, 001H
DB "C ", 091H, 000H, 001H
DB "D ", 092H, 000H, 001H
DB "E ", 093H, 000H, 001H
DB "H ", 094H, 000H, 001H
DB "L ", 095H, 000H, 001H
DB "* ", 0D6H, 000H, 002H
DB "#XOR ", 00BH, 000H, 000H, 000H, 000H
DB "(HL) ", 0AEH, 000H, 001H
DB "(IX*) ", 0AEH, 0DDH, 003H
DB "(IY*) ", 0AEH, 0FDH, 003H
DB "A ", 0AFH, 000H, 001H
DB "B ", 0A8H, 000H, 001H
DB "C ", 0A9H, 000H, 001H
DB "D ", 0AAH, 000H, 001H
DB "E ", 0ABH, 000H, 001H
DB "H ", 0ACH, 000H, 001H
DB "L ", 0ADH, 000H, 001H
DB "* ", 0EEH, 000H, 002H
DB "#END ", 000H, 000H, 000H, 000H, 000H
;-------------------------------------------------------------------------------
; END of Z80 Assembler lookup table
;-------------------------------------------------------------------------------
; Fill remaining bytes with NOP's (000H).
ALIGN_NOPS 0D000H
; Next block of code goes up in the F000:FFFF ROM space.
;
ORG BANKRAMADDR
;-------------------------------------------------------------------------------
; START OF ADDITIONAL TZFS COMMANDS
;-------------------------------------------------------------------------------
; Copy - Source, Destination, Size.
COPYM: CALL READ4HEX ; Start address
JR C,COPYMERR
LD (TMPADR),HL
CALL READ4HEX
JR C,COPYMERR
LD (TMPCNT),HL
CALL READ4HEX
JR C,COPYMERR
PUSH HL
POP BC
LD HL,(TMPCNT)
LD DE,(TMPADR)
LDIR
COPYMERR: RET
; Write to I/O port. 16bit address to BC, 8bit value to A.
WRITEIO: CALL READ4HEX ; Get 16bit I/O port.
JR C,WRITEIOER
PUSH HL ; Swap to BC so B=15:8, C=7:0
POP BC
CALL _2HEX ; Get 8 bit data.
OUT (C),A ; Write 8 bit data to 16bit port.
WRITEIOER: RET
; Read 16bit I/O port value.
READIO: CALL READ4HEX ; Get 16bit I/O port.
JR C,READIOER
PUSH HL ; Swap to BC so B=15:8, C=7:0
POP BC
IN A,(C) ; Get 8bit value from 16bit I/O port.
CALL PRTHX ; Print.
CALL NL
READIOER: RET
; FusionX doesnt yet have the video capabilities, so no need to build in the logic.
IF BUILD_FUSIONX = 0
; Method to set the video mode.
; Param: 0 - Enable FPGA and set to MZ-80K mode.
; 1 - Enable FPGA and set to MZ-80C mode.
; 2 - Enable FPGA and set to MZ-1200 mode.
; 3 - Enable FPGA and set to MZ-80A mode (base mode on MZ-80A hardware).
; 4 - Enable FPGA and set to MZ-700 mode (base mode on MZ-700 hardware).
; 5 - Enable FPGA and set to MZ-1500 mode.
; 6 - Enable FPGA and set to MZ-800 mode.
; 7 - Enable FPGA and set to MZ-80B mode.
; 8 - Enable FPGA and set to MZ-2000 mode.
; 9 - Enable FPGA and set to MZ-2200 mode.
; 10 - Enable FPGA and set to MZ-2500 mode.
; O - Turn off FPGA Video, turn on mainboard video.
SETVMODE: IN A,(CPLDINFO) ; Get configuration of hardware.
BIT 3,A
JP Z,NOFPGAERR ; No hardware so cannot change mode.
PUSH DE ; Preserve DE in case no number given.
POP BC
CALL ConvertStringToNumber ; Convert the input into 0 (disable) or frequency in KHz.
JR NZ,SETVMODEOFF
LD A,H
CP 0
JP NZ,BADNUMERR ; Check that the given mode is in range 0 - 7.
LD A,L
CP 10
JP NC,BADNUMERR
;
SETVMODE0: IN A,(CPLDCFG)
OR MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to enable the FPGA video mode.
OUT (CPLDCFG),A
;
IN A,(VMCTRL) ; Get current setting.
AND 0F0H ; Clear old mode setting.
OR L ; Add in new setting.
OUT (VMCTRL),A
RLC L ; Shift mode to position for SCRNMODE storage.
RLC L
RLC L
RLC L
LD A,(SCRNMODE) ; Repeat for the screen mode variable, used when resetting or changing display settings.
AND 007H ; Clear video mode setting.
OR L ; Add in new setting.
SET 2, A ; Set flag to indicate video mode override - ie, dont use base machine mode.
SETVMODECLR:SET 1, A ; Ensure flag set so on restart the FPGA video mode is selected.
LD (SCRNMODE),A
LD A, 016H ; Clear the screen so we start from a known position.
CALL PRNT
LD A,071H ; Blue background and white characters.
LD HL,ARAM
CALL CLR8
RET
SETVMODEOFF:LD A,(DE)
CP 'O'
JR Z,SETVMODE1
CP 'o'
JP NZ,BADNUMERR
SETVMODE1: LD A,(SCRNMODE) ; Disable flag to enable FPGA on restart.
RES 1,A
LD (SCRNMODE),A
IN A,(CPLDCFG)
AND ~MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to disable the FPGA video mode.
OUT (CPLDCFG),A
RET
; Method to set the VGA output mode of the external display.
SETVGAMODE: IN A,(CPLDINFO) ; Get configuration of hardware.
BIT 3,A
JP Z,NOFPGAERR ; No hardware so cannot change mode.
CALL ConvertStringToNumber ; Convert the input into 0-3, 0 = off, 1 = 640x480, 2=1024x768, 3=800x600.
JP NZ,BADNUMERR
LD A,H
CP 0
JP NZ,BADNUMERR ; Check that the given mode is in range 0 - 15.
LD A,L
CP 15
JP NC,BADNUMERR
;
;RRC L
;RRC L ; Value to top 2 bits ready to be applied to VGA mode register.
;
SETVGAMODE1:IN A,(CPLDCFG)
OR MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to enable the FPGA video mode.
OUT (CPLDCFG),A
;
LD A, L ; Add in new setting.
OUT (VMVGAMODE),A
LD (SCRNMODE2), A
JP SETVMODECLR
; Method to set the VGA border colour on the external display.
SETVBORDER: IN A,(CPLDINFO) ; Get configuration of hardware.
BIT 3,A
JP Z,NOFPGAERR ; No hardware so cannot change mode.
CALL ConvertStringToNumber ; Convert the input into 0 - 7, bit 2 = Red, 1 = Green, 0 = Blue.
JP NZ,BADNUMERR
LD A,H
CP 0
JP NZ,BADNUMERR ; Check that the given mode is in range 0 - 7.
LD A,L
CP 7
JP NC,BADNUMERR
;
IN A,(CPLDCFG)
OR MODE_VIDEO_FPGA ; Set the tranZPUter CPLD hardware to enable the FPGA video mode.
OUT (CPLDCFG),A
;
LD A,L
OUT (VMVGATTR),A
RET
ENDIF ; BUILD_FUSIONX
; Method to enable/disable the alternate CPU frequency and change it's values.
;
SETFREQ: CALL ConvertStringToNumber ; Convert the input into 0 (disable) or frequency in KHz.
JP NZ,BADNUMERR
LD (TZSVC_CPU_FREQ),HL ; Set the required frequency in the service structure.
LD A,H
CP L
JR NZ,SETFREQ1
LD A, TZSVC_CMD_CPU_BASEFREQ ; Switch to the base frequency.
JR SETFREQ2
SETFREQ1: LD A, TZSVC_CMD_CPU_ALTFREQ ; Switch to the alternate frequency.
SETFREQ2: CALL SVC_CMD
OR A
JP NZ,SETFREQERR
LD A,H
CP L
RET Z ; If we are disabling the alternate cpu frequency (ie. = 0) exit.
LD A, TZSVC_CMD_CPU_CHGFREQ ; Switch to the base frequency.
CALL SVC_CMD
OR A
JP NZ,SETFREQERR
RET
; FusionX doesnt have the soft CPU capabilities, so no need to build in the logic.
IF BUILD_FUSIONX = 0
; Method to configure the hardware to use the T80 CPU instantiated in the FPGA.
;
SETT80: IN A,(CPUINFO)
LD C,A
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JP NZ,SOFTCPUERR
LD A,C
AND CPUMODE_IS_T80
JP Z,NOT80ERR
;LD L,VMMODE_VGA_640x480 ; Enable VGA mode for a better display.
;CALL SETVGAMODE1
LD A, TZSVC_CMD_CPU_SETT80 ; We need to ask the K64F to switch to the T80 as it may involve loading of ROMS.
CALL SVC_CMD
OR A
JP NZ,SETT80ERR
RET
; Method to configure the hardware to use the original Z80 CPU installed on the tranZPUter board.
;
SETZ80: IN A,(CPUINFO)
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JP NZ,SOFTCPUERR
CALL SETVMODE1 ; Turn off VGA mode, return to default MZ video.
LD A, TZSVC_CMD_CPU_SETZ80
CALL SVC_CMD
OR A
JP NZ,SETZ80ERR
RET
; Method to configure the hardware to use the ZPU Evolution CPU instantiated in the FPGA.
;
SETZPUEVO: IN A,(CPUINFO)
LD C,A
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JP NZ,SOFTCPUERR
LD A,C
AND CPUMODE_IS_ZPU_EVO
JP Z,NOZPUERR
LD L,VMMODE_VGA_640x480 ; Enable VGA mode for a better display.
CALL SETVGAMODE1
LD A, TZSVC_CMD_CPU_SETZPUEVO ; We need to ask the K64F to switch to the ZPU Evo as it may involve loading of ROMS.
CALL SVC_CMD
OR A
JP NZ,SETZPUERR
HALT ; ZPU will take over so stop the Z80 from further processing.
;----------------------------------------------
; Hardware Emulation Mode Activation Routines.
;----------------------------------------------
SETMZ80K: LD D, TZSVC_CMD_EMU_SETMZ80K ; We need to ask the K64F to switch to the Sharp MZ80K emulation as it involves loading ROMS.
JR SETEMUMZ
SETMZ80C: LD D, TZSVC_CMD_EMU_SETMZ80C
JR SETEMUMZ
SETMZ1200: LD D, TZSVC_CMD_EMU_SETMZ1200
JR SETEMUMZ
SETMZ80A: LD D, TZSVC_CMD_EMU_SETMZ80A
JR SETEMUMZ
SETMZ700: LD D, TZSVC_CMD_EMU_SETMZ700
JR SETEMUMZ
SETMZ1500: LD D, TZSVC_CMD_EMU_SETMZ1500
JR SETEMUMZ
SETMZ800: LD D, TZSVC_CMD_EMU_SETMZ800
JR SETEMUMZ
SETMZ80B: LD D, TZSVC_CMD_EMU_SETMZ80B
JR SETEMUMZ
SETMZ2000: LD D, TZSVC_CMD_EMU_SETMZ2000
JR SETEMUMZ
SETMZ2200: LD D, TZSVC_CMD_EMU_SETMZ2200
JR SETEMUMZ
SETMZ2500: LD D, TZSVC_CMD_EMU_SETMZ2500
JR SETEMUMZ
;
; General function to determine if the emulator MZ hardware is present and activate it. Activation requires making a request to the
; I/O processor as it needs to load up the correct BIOS etc prior to activating the emulation.
;
SETEMUMZ: IN A,(CPUINFO) ; Verify that the FPGA has emuMZ capabilities.
LD C,A
AND CPUMODE_IS_SOFT_MASK
CP CPUMODE_IS_SOFT_AVAIL
JR NZ,SOFTCPUERR
LD A,C
AND CPUMODE_IS_EMU_MZ
JR Z,NOEMUERR
LD L,VMMODE_VGA_640x480 ; Enable VGA mode for a better display.
CALL SETVGAMODE1
;
PUSH DE ; Setup the initial video mode based on the required emulation.
LD A,D
SUB TZSVC_CMD_EMU_SETMZ80K
LD L,A
LD H,0
CALL SETVMODE0
POP DE
;
LD A, D ; Load up the required emulation mode.
CALL SVC_CMD
OR A
JR NZ,SETT80ERR
HALT
ENDIF ; BUILD_FUSIONX
; Simple routine to clear screen or attributes.
CLR8: LD BC,00800H
PUSH DE
LD D,A
CLR8_1: LD (HL),D
INC HL
DEC BC
LD A,B
OR C
JR NZ,CLR8_1
POP DE
RET
;
; Message addresses are in Bank2.
;
IF BUILD_FUSIONX = 0
NOFPGAERR: LD DE,MSGNOFPGA
JR BADNUM2
SETT80ERR: LD DE,MSGT80ERR
JR BADNUM2
SETZ80ERR: LD DE,MSGZ80ERR
JR BADNUM2
SETZPUERR: LD DE,MSGZPUERR
JR BADNUM2
SOFTCPUERR: LD DE,MSGNOSOFTCPU
JR BADNUM2
NOT80ERR: LD DE,MSGNOT80CPU
JR BADNUM2
NOZPUERR: LD DE,MSGNOZPUCPU
JR BADNUM2
NOEMUERR: LD DE,MSGNOEMU
JR BADNUM2
ENDIF ; BUILD_FUSIONX
SETFREQERR: LD DE,MSGFREQERR
JR BADNUM2
BADNUMERR: LD DE,MSGBADNUM
BADNUM2: CALL ?PRINTMSG
RET
;-------------------------------------------------------------------------------
; END OF ADDITIONAL TZFS COMMANDS
;-------------------------------------------------------------------------------
; The FDC controller uses it's busy/wait signal as a ROM address line input, this
; causes a jump in the code dependent on the signal status. It gets around the 2MHz Z80 not being quick
; enough to process the signal by polling.
ALIGN_NOPS FDCJMP1
ORG FDCJMP1
FDCJMPL4: JP (IX)
; The FDC controller uses it's busy/wait signal as a ROM address line input, this
; causes a jump in the code dependent on the signal status. It gets around the 2MHz Z80 not being quick
; enough to process the signal by polling.
ALIGN_NOPS FDCJMP2
ORG FDCJMP2
FDCJMPH4: JP (IY)
; Ensure we fill the entire 4K by padding with FF's.
;
ALIGN_NOPS 10000H