You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1035 lines
28 KiB

;
; monitor.asm This is main monitor program for my system
;
;
BELL .EQU 07H
SPACE .EQU 20H
TAB .EQU 09H
CR .EQU 0DH
LF .EQU 0AH
FF .EQU 0CH
ESC .EQU 1BH
DELETE .EQU 7FH
STARTCPM .EQU 100H ;LOCATION WHERE CPM WILL BE PLACED FOR COLD BOOT
;---------PORT(S) TO SWITCH MASTER/SLAVE(S)
Z80PORT .EQU 0D0H ;4 PORTS ON Z80 BOARD FOR MEMORY MANAGEMENT.
BCTL .EQU 0A0H ;CHANNEL B CONTROL PORT FOR SCC
ACTL .EQU 0A1H ;CHANNEL A CONTROL
BDTA .EQU 0A2H ;CHANNEL B DATA
ADTA .EQU 0A3H ;CHANNEL A DATA
;-------------- S100Computers IDE HARD DISK CONTROLLER COMMANDS ETC.
IDEAport .EQU 030H ;lower 8 bits of IDE interface
IDEBport .EQU 031H ;upper 8 bits of IDE interface
IDECport .EQU 032H ;control lines for IDE interface
IDECtrl .EQU 033H ;8255 configuration port
IDEDrivePort .EQU 034H ;To select the 1st or 2nd CF card/drive (Not used with this monitor)
IDE_Reset_Delay .EQU 020H ;Time delay for reset/initilization (~60 uS, with 10MHz Z80, 2 I/O wait states)
CPM_ADDRESS .EQU 100H ;Will place the CPMLDR.COM Loader here with
;CPMLDR.COM will ALWAYS be on TRK 0,SEC2, (LBA Mode)
SEC_COUNT .EQU 12 ;CPMLDR.COM requires (currently) 10, 512 byte sectors
;Add extra just in case
RDcfg8255 .EQU 10010010B ;Set 8255 IDECport out, IDEAport/B input
WRcfg8255 .EQU 10000000B ;Set all three 8255 ports output
;
IDEa0line .EQU 01H ;direct from 8255 to IDE interface
IDEa1line .EQU 02H ;direct from 8255 to IDE interface
IDEa2line .EQU 04H ;direct from 8255 to IDE interface
IDEcs0line .EQU 08H ;inverter between 8255 and IDE interface
IDEcs1line .EQU 10H ;inverter between 8255 and IDE interface
IDEwrline .EQU 20H ;inverter between 8255 and IDE interface
IDErdline .EQU 40H ;inverter between 8255 and IDE interface
IDEreset .EQU 80H ;inverter between 8255 and IDE interface
;
;Symbolic constants for the IDE Drive registers, which makes the
;code more readable than always specifying the address pins
;
REGdata .EQU 08H ;IDEcs0line
REGerr .EQU 09H ;IDEcs0line + IDEa0line
REGcnt .EQU 0AH ;IDEcs0line + IDEa1line
REGsector .EQU 0BH ;IDEcs0line + IDEa1line + IDEa0line
REGcyLSB .EQU 0CH ;IDEcs0line + IDEa2line
REGcyMSB .EQU 0DH ;IDEcs0line + IDEa2line + IDEa0line
REGshd .EQU 0EH ;IDEcs0line + IDEa2line + IDEa1line ;(0EH)
REGCMD .EQU 0FH ;IDEcs0line + IDEa2line + IDEa1line + IDEa0line ;(0FH)
REGstatus .EQU 0FH ;IDEcs0line + IDEa2line + IDEa1line + IDEa0line
REGcontrol .EQU 16H ;IDEcs1line + IDEa2line + IDEa1line
REGastatus .EQU 17H ;IDEcs1line + IDEa2line + IDEa1line + IDEa0line
;IDE CMD Constants. These should never change.
CMDrecal .EQU 10H
CMDread .EQU 20H
CMDwrite .EQU 30H
CMDinit .EQU 91H
CMDid .EQU 0ECH
CMDdownspin .EQU 0E0H
CMDupspin .EQU 0E1H
;
; IDE Status Register:
; bit 7: Busy 1=busy, 0=not busy
; bit 6: Ready 1=ready for CMD, 0=not ready yet
; bit 5: DF 1=fault occured insIDE drive
; bit 4: DSC 1=seek complete
; bit 3: DRQ 1=data request ready, 0=not ready to xfer yet
; bit 2: CORR 1=correctable error occured
; bit 1: IDX vendor specific
; bit 0: ERR 1=error occured
;
.ORG 0F000H
JP BEGIN
TBL:
.DW NOTIMPL ; "@"
.DW MEMMAP ; "A" DISPLAY A MAP OF MEMORY
.DW NOTIMPL ; "B"
.DW NOTIMPL ; "C"
.DW DISP ; "D" DISPLAY MEMORY (IN HEX & ASCII)
.DW NOTIMPL ; "E" ECHO CHAR IN TO CHAR OUT
.DW FILL ; "F" FILL MEMORY WITH A CONSTANT
.DW GOTO ; "G" GO TO [ADDRESS]
.DW NOTIMPL ; "H"
.DW NOTIMPL ; "I"
.DW NOTIMPL ; "J" NON-DESTRUCTIVE MEMORY TEST
.DW NOTIMPL ; "K"
.DW NOTIMPL ; "L"
.DW NOTIMPL ; "M"
.DW XMEMMAP ; "N" DISPLAY EXTENDED MEMORY SEGEMENT:ADDRESS
.DW NOTIMPL ; "O"
.DW HBOOTCPM ; "P BOOT IN CPM FROM IDE HARD DISK"
.DW QUERY ; "Q" QUERY PORT (IN OR OUT)
.DW NOTIMPL ; "R"
.DW SUBS ; "S" SUBSTITUTE &/OR EXAMINE MEMORY
.DW NOTIMPL ; "T"
.DW NOTIMPL ; "U"
.DW NOTIMPL ; "V" COMPARE MEMORY
.DW NOTIMPL ; "X"
.DW NOTIMPL ; "Y"
.DW NOTIMPL ; "Z"
SCCINIT:
.DB 04H ;Point to WR4
.DB 44H ;X16 clock,1 Stop,NP
;
.DB 03H ;Point to WR3
.DB 0C1H ;Enable reciever, Auto Enable, Recieve 8 bits
; .DB 0E1H ;Enable reciever, No Auto Enable, Recieve 8 bits (for CTS bit)
;
.DB 05H ;Point to WR5
.DB 0EAH ;Enable, Transmit 8 bits
; ;Set RTS,DTR, Enable
;
.DB 0BH ;Point to WR11
.DB 56H ;Recieve/transmit clock = BRG
;
.DB 0CH ;Point to WR12
; .DB 40H ;Low Byte 2400 Baud
; .DB 1EH ;Low Byte 4800 Baud
; .DB 0EH ;Low Byte 9600 Baud
.DB 06H ;Low byte 19,200 Baud
; .DB 02H ;Low byte 38,400 Baud <<<<<<<<<<<
; .DB 00H ;Low byte 76,800 Baud
;
.DB 0DH ;Point to WR13
.DB 00H ;High byte for Baud
.DB 0EH ;Point to WR14
.DB 01H ;Use 4.9152 MHz Clock. Note SD Systems uses a 2.4576 MHz clock, enable BRG
;
.DB 0FH ;Point to WR15
.DB 00H ;Generate Int with CTS going high
.DB 00H
.DB 00H
.DB 00H
.DB 00H
.DB 00H
;
; BEGIN OF CODE -----------------------------------------------------------------------
BEGIN:
LD A,0FFH
XOR A
OUT (Z80PORT+1),A
LD A,0H
OUT (Z80PORT+2),A
LD A,04H
OUT (Z80PORT+3),A
LD A,ACTL
LD C,A
LD B,$0E
LD HL,SCCINIT
OTIR
LD A,BCTL
LD C,A
LD B,$0E
LD HL,SCCINIT
OTIR
ZAXXLE:
LD SP,AHEAD-4 ;SETUP FAKE STACK FRAME
JP MEMSZ1 ;RETURNS WITH TOP OF RAM IN [HL]
.DW AHEAD ;RETURN WILL PICK UP THIS ADDRESS
AHEAD:
LD SP,HL ;[HL] CONTAINS TOP OF RAM
PUSH HL
POP IX ;SAVE STACK POINTER IN IX FOR FUTURE USE
LD HL,MSG0
CALL ZPMSG
LD HL,SP_MSG ;PRINT CURRENT STACK LOCATION
CALL ZPMSG
PUSH IX ;SP IS STORED HERE FROM ABOVE
POP HL
CALL HLSP ;PRINT HL/SP
CALL CRLF ;THEN CRLF
START:
LD DE,START
PUSH DE ;EXTRA UNBALANCED POP & [DE] WOULD END UP IN [PC]
CALL CRLF
LD C,BELL ;A BELL HERE WILL SIGNAL WHEN JOBS ARE DONE
CALL CO
LD C,'-'
CALL CO
LD C,'>'
CALL CO
STAR0: ;MAIN LOOP. MONITOR WILL STAY HERE UNTIL CMD.
CALL TI
AND 7FH
JR Z,STAR0
SUB '@' ;COMMANDS @ TO Z ONLY
RET M
CP 1BH ;A-Z ONLY
RET NC
ADD A,A
LD HL,TBL
ADD A,L
LD L,A
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
LD C,02H
JP (HL) ;JUMP TO COMMAND TABLE
MSG0: .DB "Z80 ROM MONITOR V1.0 (David Mehaffy 12/24/2011) $"
SP_MSG .DB CR,LF,"SP=$"
ZPMSG: LD A,(HL) ;A ROUTINE TO PRINT OUT A STRING @ [HL]
INC HL ;UP TO THE FIRST '$'
CP '$'
RET Z
LD C,A
CALL CO
JR ZPMSG
;THIS IS A CALLED ROUTINE USED TO CALCULATE TOP OF RAM IS USED BY
;THE ERROR TO RESET THE STACK. Returns top of RAM in [HL]
MEMSIZ: PUSH BC ;SAVE [BC]
MEMSZ1: LD HL,0FFFFH ;START FROM THE TOP DOWN
MEMSZ2: LD A,(HL)
CPL
LD (HL),A
CP (HL)
CPL ;PUT BACK WHAT WAS THERE
LD (HL),A
JP Z,GOTTOP
DEC H ;TRY 100H BYTES LOWER
JR MEMSZ2 ;KEEP LOOKING FOR RAM
GOTTOP: POP BC ;RESTORE [BC]
RET
;ABORT IF ESC AT CONSOL, PAUSE IF ^S AT CONSOL
CCHK: CALL CSTS ;FIRST IS THERE ANYTHING THERE
RET Z
CALL CI
CP 'S'-40H
JR NZ,CCHK1
CCHK2: CALL CSTS ;WAIT HERE UNTIL ANOTHER INPUT IS GIVEN
JR Z,CCHK2
CCHK1: CP ESC
RET NZ ;RETURN EXECPT IF ESC
;RESTORE SYSTEM AFTER ERROR
ERROR: CALL MEMSIZ ;GET RAM AVAILABLE - WORKSPACE IN [HL]
LD SP,HL ;SET STACK UP IN WORKSPACE AREA
LD C,'*'
CALL CO
JP START
;PRINT HIGHEST MEMORY FROM BOTTOM
SIZE:
CALL MEMSIZ ;RETURNS WITH [HL]= RAM AVAILABLE-WORKSPACE
LFADR: CALL CRLF
;PRINT [HL] AND A SPACE
HLSP: PUSH HL
PUSH BC
CALL LADR
LD C,SPACE
CALL CO
POP BC
POP HL
RET
;PRINT A SPACE
SF488: LD C,SPACE
JP CO
;CONVERT HEX TO ASCII
CONV:
AND 0FH
ADD A,90H
DAA
ADC A,40H
DAA
LD C,A
RET
;GET TWO PARAMETERS AND PUT THEM IN [HL] & [DE] THEN CRLF
EXLF: CALL HEXSP
POP DE
POP HL
CRLF:
PUSH BC
LD C,LF
CALL CO
LD C,CR
CALL CO
POP BC
RET
;PUT THREE PARAMETERS IN [BC] [DE] [HL] THEN CR/LF
EXPR3: INC C ;ALREADY HAD [C]=2 FROM START
CALL HEXSP
CALL CRLF
POP BC
POP DE
POP HL
RET
;GET ONE PARAMETER
EXPR1: LD C,01H
HEXSP: LD HL,0000
EX0: CALL TI
EX1: LD B,A
CALL NIBBLE
JR C,EX2X
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
OR L
LD L,A
JR EX0
EX2X: EX (SP),HL
PUSH HL
LD A,B
CALL QCHK
JR NC,SF560
DEC C
RET Z
SF560: JP NZ,ERROR
DEC C
JR NZ,HEXSP
RET
EXF: LD C,01H
LD HL,0000H
JR EX1
;RANGE TEST ROUTINE CARRY SET = RANGE EXCEEDED
HILOX: CALL CCHK
CALL HILO
RET NC
POP DE ;DROP ONE LEVEL BACK TO START
RET
HILO: INC HL ;RANGE CHECK SET CARRY IF [DE]=[HL]
LD A,H
OR L
SCF
RET Z
LD A,E
SUB L
LD A,D
SBC A,H
RET
; PRINT [HL] ON CONSOLE
LADR: LD A,H
CALL LBYTE
LD A,L
LBYTE: PUSH AF
RRCA
RRCA
RRCA
RRCA
CALL SF598
POP AF
SF598: CALL CONV
JP CO
NIBBLE: SUB 30H
RET C
CP 17H
CCF
RET C
CP LF
CCF
RET NC
SUB 07H
CP LF
RET
COPCK: LD C,'-'
CALL CO
PCHK: CALL TI
;TEST FOR DELIMITERS
QCHK: CP SPACE
RET Z
CP ','
RET Z
CP CR
SCF
RET Z
CCF
RET
;KEYBOARD HANDLING ROUTINTE (WILL NOT ECHO CR/LF)
;IT CONVERTS LOWER CASE TO UPPERCASE FOR LOOKUP COMMANDS
;ALSO ^C WILL FOR A JUMP TO BOOT TO CP/M
;ALL OTHER CHARACTERS ARE ECHOED ON CONSOLE
TI:
CALL CI
CP CR
RET Z
CP 'C' - 40H ;^C TO BOOT TO CP/M
JP Z,FBOOT
PUSH BC
LD C,A
CALL CO
LD A,C
POP BC
CP 40H ;LC-.UC
RET C
CP 7BH
RET NC
SF574: AND 5FH
RET
BITS1: PUSH DE ;DISPLAY 8 BITS OF [A]
PUSH BC
LD E,A
CALL BITS
POP BC
POP DE
RET
BITS: LD B,08H ;DISPLAY 8 BITS OF [E]
CALL SF488
SF76E: SLA E
LD A,18H
ADC A,A
LD C,A
CALL CO
DJNZ SF76E
RET
;<<<<<<<<<<<<<<<< MAIN CONSOLE ROUTINES <<<<<<<<<<<<<
CO:
IN A,(ACTL)
AND 04H ;ARE WE READY FOR A CHARACTER
JR Z,CO
LD A,C
OUT (ADTA),A
RET
CI:
IN A,(ACTL)
AND 01H
JR Z,CI
IN A,(ADTA)
RET
CSTS: IN A,(ACTL)
AND 01H
RET Z ;RETURN Z IF NOTHING
LD A,0FFH
XOR A ;RETURN FF / NZ IF SOMETHING
RET
;-------------- BOOT UP CPM FROM HARD DISK ON S100COMPUTERS IDR BOARD ----------------
;BOOT UP THE 8255/IDE Board HARD DISK/Flash Memory Card
;NOTE CODE IS ALL HERE IN CASE A 2716 IS USED
HBOOTCPM:
POP HL ;CLEAN UP STACK
CALL INITILIZE_IDE_BOARD ;Initilze the 8255 and drive (again just in case)
LD D,11100000B ;Data for IDE SDH reg (512bytes, LBA mode,single drive)
LD E,REGshd ;00001110,(0EH) CS0,A2,A1,
CALL IDEwr8D ;Write byte to select the MASTER device
LD B,0FFH ;Delay time to allow a Hard Disk to get up to speed
WaitInit:
LD E,REGstatus ;Get status after initilization
CALL IDErd8D ;Check Status (info in [D])
BIT 7,D
JR Z,SECREAD ;Zero, so all is OK to write to drive
;Delay to allow drive to get up to speed
PUSH BC
LD BC,0FFFFH
DXLAY2: LD D,2 ;May need to adjust delay time to allow cold drive to
DXLAY1: DEC D ;to speed
JR NZ,DXLAY1
DEC BC
LD A,C
OR B
JR NZ,DXLAY2
POP BC
DJNZ WaitInit ;If after 0FFH, 0FEH, 0FDH... 0, then drive initilization problem
IDError:
LD HL,DRIVE_NR_ERR ;Drive not ready
JP ABORT_ERR_MSG
SECREAD: ;Note CPMLDR will ALWAYS be on TRK 0,SEC 1,Head 0
CALL IDEwaitnotbusy ;Make sure drive is ready
JR C,IDError ;NC if ready
LD D,1 ;Load track 0,sec 1, head 0
LD E,REGsector ;Send info to drive
CALL IDEwr8D
LD D,0 ;Send Low TRK#
LD E,REGcyLSB
CALL IDEwr8D
LD D,0 ;Send High TRK#
LD E,REGcyMSB
CALL IDEwr8D
LD D,SEC_COUNT ;Count of CPM sectors we wish to read
LD E,REGcnt
CALL IDEwr8D
LD D,CMDread ;Send read CMD
LD E,REGCMD
CALL IDEwr8D ;Send sec read CMD to drive.
CALL IDEwdrq ;Wait until it's got the data
LD HL,CPM_ADDRESS ;DMA address where the CPMLDR resides in RAM
LD B,0 ;256X2 bytes
LD C,SEC_COUNT ;Count of sectors X 512
MoreRD16:
LD A,REGdata ;REG regsiter address
OUT (IDECport),A
OR IDErdline ;08H+40H, Pulse RD line
OUT (IDECport),A
IN A,(IDEAport) ;read the LOWER byte
LD (HL),A
INC HL
IN A,(IDEBport) ;read the UPPER byte
LD (HL),A
INC HL
LD A,REGdata ;Deassert RD line
OUT (IDECport),A
DJNZ MoreRD16
DEC C
JR NZ,MoreRD16
LD E,REGstatus ;Check the R/W status when done
CALL IDErd8D
BIT 0,D
JR NZ,IDEerr1 ;Z if no errors
LD HL,STARTCPM
LD A,(HL)
CP 31H ;EXPECT TO HAVE 31H @80H IE. LD SP,80H
JP Z,STARTCPM ;AS THE FIRST INSTRUCTION. IF OK JP to 100H in RAM
JP ERR_LD1 ;Boot Sector Data incorrect
IDEerr1:
LD HL,IDE_RW_ERROR ;Drive R/W Error
JP ABORT_ERR_MSG
; ----- SUPPORT ROUTINES --------------
INITILIZE_IDE_BOARD: ;Drive Select in [A]. Note leaves selected drive as [A]
LD A,RDcfg8255 ;Config 8255 chip (10010010B), read mode on return
OUT (IDECtrl),A ;Config 8255 chip, READ mode
;Hard reset the disk drive
;For some reason some CF cards need to the RESET line
;pulsed very carefully. You may need to play around
LD A,IDEreset ;with the pulse length. Symptoms are: incorrect data comming
OUT (IDECport),A ;back from a sector read (often due to the wrong sector being read)
;I have a (negative)pulse of 60 uSec. (10Mz Z80, two IO wait states).
LD C,IDE_Reset_Delay ;~60 uS seems to work for the 5 different CF cards I have
ResetDelay:
DEC C
JP NZ,ResetDelay ;Delay (reset pulse width)
XOR A
OUT (IDECport),A ;No IDE control lines asserted (just bit 7 of port C)
CALL DELAY_15 ;Need to delay a little before checking busy status
IDEwaitnotbusy: ;Drive READY if 01000000
LD B,0FFH
LD C,080H ;Delay, must be above 80H for 4MHz Z80. Leave longer for slower drives
MoreWait:
LD E,REGstatus ;Wait for RDY bit to be set
CALL IDErd8D
LD A,D
AND 11000000B
XOR 01000000B
JR Z,DoneNotBusy
DJNZ MoreWait
DEC C
JR NZ,MoreWait
SCF ;Set carry to indicate an error
RET
DoneNotBusy:
OR A ;Clear carry it indicate no error
RET
;Wait for the drive to be ready to transfer data.
IDEwdrq: ;Returns the drive's status in Acc
LD B,0FFH
LD C,0FFH ;Delay, must be above 80H for 4MHz Z80. Leave longer for slower drives
MoreDRQ:
LD E,REGstatus ;wait for DRQ bit to be set
CALL IDErd8D
LD A,D
AND 10001000B
CP 00001000B
JR Z,DoneDRQ
DJNZ MoreDRQ
DEC C
JR NZ,MoreDRQ
SCF ;Set carry to indicate error
RET
DoneDRQ:
OR A ;Clear carry
RET
;
;------------------------------------------------------------------
; Low Level 8 bit R/W to the drive controller. These are the routines that talk
; directly to the drive controller registers, via the 8255 chip.
; Note the 16 bit I/O to the drive (which is only for SEC Read here) is done directly
; in the routine MoreRD16 for speed reasons.
IDErd8D: ;READ 8 bits from IDE register in [E], return info in [D]
LD A,E
OUT (IDECport),A ;drive address onto control lines
OR IDErdline ;RD pulse pin (40H)
OUT (IDECport),A ;assert read pin
IN A,(IDEAport)
LD D,A ;return with data in [D]
LD A,E ;<---Ken Robbins suggestion
OUT (IDECport),A ;Deassert RD pin
XOR A
OUT (IDECport),A ;Zero all port C lines
RET
IDEwr8D: ;WRITE Data in [D] to IDE register in [E]
LD A,WRcfg8255 ;Set 8255 to write mode
OUT (IDECtrl),A
LD A,D ;Get data put it in 8255 A port
OUT (IDEAport),A
LD A,E ;select IDE register
OUT (IDECport),A
OR IDEwrline ;lower WR line
OUT (IDECport),A
LD A,E ;<-- Kens Robbins suggestion, raise WR line
OUT (IDECport),A
XOR A ;Deselect all lines including WR line
OUT (IDECport),A
LD A,RDcfg8255 ;Config 8255 chip, read mode on return
OUT (IDECtrl),A
RET
ERR_NR: LD HL,DRIVE_NR_ERR ;"DRIVE NOT READY
JP ABORT_ERR_MSG
ERR_LD: LD HL,BOOT_LD_ERR ;"ERROR READING BOOT/LOADER SECTORS"
JP ABORT_ERR_MSG
ERR_LD1:LD HL,BOOT_LD1_ERR ;"DATA ERROR IN BOOT SECTOR"
ABORT_ERR_MSG:
CALL ZPMSG
JP BEGIN ;BACK TO START OF MONITOR.
DELAY_15: ;DELAY ~15 MS
LD A,40
DELAY1: LD B,0
M0: DJNZ M0
DEC A
JR NZ,DELAY1
RET
;---------------------------------------------------------------
;MEMORY MAP PROGRAM CF.DR.DOBBS VOL 31 P40.
;IT WILL SHOW ON CONSOLE TOTAL MEMORY SUMMARY OF RAM, PROM, AND NO MEMORY
MEMMAP:
CALL CRLF
LD HL,0
LD B,1
MAP1: LD E,'R' ;PRINT R FOR RAM
LD A,(HL)
CPL
LD (HL),A
CP (HL)
CPL
LD (HL),A
JR NZ,MAP2
CP (HL)
JR Z,PRINT
MAP2: LD E,'p'
MAP3: LD A,0FFH
CP (HL)
JR NZ,PRINT
INC L
XOR A
CP L
JR NZ,MAP3
LD E,'.'
PRINT: LD L,0
DEC B
JR NZ,NLINE
LD B,16
CALL CRLF
CALL HXOT4
NLINE: LD A,SPACE
CALL OTA
LD A,E
CALL OTA
INC H
JR NZ,MAP1
CALL CRLF
CALL CRLF
JP START
;16 HEX OUTPUT ROUTINE
HXOT4:
LD C,H
CALL HXO2
LD C,L
HXO2: LD A,C
RRA
RRA
RRA
RRA
CALL HXO3
LD A,C
HXO3: AND 0FH
CP 10
JR C,HADJ
ADD A,7
HADJ: ADD A,30H
OTA: PUSH BC
LD C,A
CALL CO
POP BC
RET
;DISPLAY MEMORY IN HEX
DISP: CALL EXLF ;GET PARAMETERS IN [HL],[DE]
LD A,L ;ROUND OFF ADDRESSES TO XX00H
AND 0F0H
LD L,A
LD A,E ;FINAL ADDRESS LOWER HALF
AND 0F0H
ADD A,10H ;FINISH TO END 0F LINE
SF172: CALL LFADR
SF175: CALL BLANK
LD A,(HL)
CALL LBYTE
CALL HILOX
LD A,L
AND 0FH
JR NZ,SF175
LD C,TAB ;INSERT A TAB BETWEEN DATA
CALL CO
LD B,4H ;ALSO 4 SPACES
TA11: LD C,SPACE
CALL CO
DJNZ TA11
LD B,16 ;NOW PRINT ASCII (16 CHARACTERS)
PUSH DE ;TEMPORLY SAVE [DE]
LD DE,0010H
SBC HL,DE
POP DE
T11: LD A,(HL)
AND 7FH
CP ' ' ;FILTER OUT CONTROL CHARACTERS'
JR NC,T33
T22: LD A,'.'
T33: CP 07CH
JR NC,T22
LD C,A ;SET UP TO SEND
CALL CO
INC HL
DJNZ T11 ;REPEAT FOR WHOLE LINE
JR SF172
BLANK: LD C,' '
JP CO
;INSPECT AND / OR MODIFY MEMORY
SUBS: LD C,1
CALL HEXSP
POP HL
SF2E3: LD A,(HL)
CALL LBYTE
LD C,'-'
CALL CO
CALL PCHK
RET C
JR Z,SF2FC
CP 5FH
JR Z,SF305
PUSH HL
CALL EXF
POP DE
POP HL
LD (HL),E
LD A,B
CP CR
RET Z
SF2FC: INC HL
SF2FD: LD A,L
AND 07H
CALL Z,LFADR
JR SF2E3
SF305: DEC HL
JR SF2FD
;FILL A BLOCK OF MEMORY WITH A VALUE
FILL: CALL EXPR3
SF1A5: LD (HL),C
CALL HILOX
JR NC,SF1A5
POP DE
JP START
;GO TO A RAM LOCATION
GOTO: LD C,1 ;SIMPLE GOTO FIRST GET PARMS.
CALL HEXSP
CALL CRLF
POP HL ;GET PARAMETER PUSHED BY EXF
JP (HL)
; GET OR OUTPUT TO A PORT
QUERY: CALL PCHK
CP 'O' ;OUTPUT TO PORT
JR Z,SF77A
CP 'I' ;INPUT FROM PORT
JP Z,QQQ1
LD C,'*'
JP CO ;WILL ABORT IF NOT 'I' OR 'O'
QQQ1: LD C,1
CALL HEXSP
POP BC
IN A,(C)
JP BITS
;
SF77A: CALL HEXSP
POP DE
POP BC
OUT (C),E
RET
;Display Extended memory map for 1MG RAM using IA-2 Z80 Board window registers
XMEMMAP:
LD HL,MSG17 ;Get segment (0-F)
CALL ZPMSG
LD C,1
CALL HEXSP ;Get 2 or 4 hex digits (count in C).
POP HL
LD A,L ;Get single byte value
AND 0FH
EXX
LD D,A ;Store in D' for 000X:YYYY display below
SLA A
SLA A
SLA A
SLA A
OUT (Z80PORT+2),A ;Re-map to first 16K in segment:64K Space
LD E,A ;store shifted nibble in E'
LD HL,0 ;Will store 0-FFFF for total RAM display (not actual access)
EXX
LD D,0 ;Total display line count (256 characters, 16lines X 16 characters)
CALL CRLF
LD HL,0
LD B,1
XMAP1: LD A,H
AND 00111111B ;Wrap 16K window
LD H,A
LD E,'R' ;PRINT R FOR RAM
LD A,(HL)
CPL
LD (HL),A
CP (HL)
CPL
LD (HL),A ;Save it back
JR NZ,XMAP2
CP (HL)
JR Z,XPRINT
XMAP2: LD E,'p'
XMAP3: LD A,0FFH
CP (HL)
JR NZ,XPRINT
INC L
XOR A
CP L
JR NZ,XMAP3
LD E,'.'
XPRINT: LD L,0
DEC B
JR NZ,XNLINE
LD B,16
CALL CRLF
CALL SET_WINDOW
LD A,SPACE
JR XN11
XNLINE: LD A,SPACE
CALL OTA
LD A,E
XN11: CALL OTA
INC H
INC D ;Are we done yet
JR NZ,XMAP1
CALL CRLF
XOR A
OUT (Z80PORT+2),A ;Set RAM window back to the way it was
JP START
SET_WINDOW: ;Setup the unique IA-II Z80 board window to address > 64k
EXX
LD C,D ;Print seg value
CALL HXO2
LD C,':'
CALL CO
CALL HXOT4 ;Print HL' (not origional HL)
LD A,H ;get current H being displayed (Already pointed to first 16K window)
NOTW0: CP 40H
JR NZ,NOTW1
LD A,E
ADD A,04H ;Window for 4,5,6,7, set to H from above
JR DOWIN
NOTW1: CP 80H
JR NZ,NOTW2
LD A,E
ADD A,08H ;Window for 8,9,A,B set to H from above
JR DOWIN
NOTW2: CP 0C0H
JR NZ,NOTW3 ;Must be values in between
LD A,E
ADD A,0CH ;Window for 4,5,6,7, set to H from above
DOWIN: OUT (Z80PORT+2),A ;Re-map to first 16K in segment:64K Space
NOTW3: LD A,H
ADD A,10H
LD H,A
EXX ;Get back normal register set
RET
NOTIMPL:
RET
FBOOT:
RET
DRIVE_NR_ERR: .DB BELL,CR,LF
.DB "Drive not Ready.",CR,LF,LF,'$'
RESTORE_ERR: .DB BELL,CR,LF
.DB "Restore Failed.",CR,LF,LF,'$'
BOOT_LD_ERR: .DB BELL,CR,LF
.DB "Read Error.",CR,LF,LF,'$'
SEEK_ERROR_MSG: .DB BELL,CR,LF
.DB "Seek Error.",CR,LF,LF,'$'
BOOT_LD1_ERR: .DB BELL,CR,LF
.DB "BOOT error.",CR,LF,LF,'$'
IDE_RW_ERROR: .DB CR,LF
.DB "IDE Drive R/W Error"
.DB CR,LF,'$'
MSG17: .DB CR,LF
.DB "Segement (0-F):$"
.END