1632 lines
73 KiB
NASM
1632 lines
73 KiB
NASM
;****************************************************************
|
|
;
|
|
; MZ-2000 Initial Program Loader Firmware.
|
|
;
|
|
; Disassembled with dz80 v2.1 and comments copied from the
|
|
; MZ-80B IPL disassembly.
|
|
;
|
|
;****************************************************************
|
|
|
|
; I/O registers.
|
|
;
|
|
; 0xE0 = 8255 Port A - A7 : L APSS Search for next program
|
|
; A6 : L Automatic playback at end of rewind
|
|
; A5 : L Automatic rewind during playback(recording)
|
|
; A4 : L Invert Video
|
|
; A3 : L Stop Cassette
|
|
; A2 : L Play Cassette
|
|
; A1 : L Fast Forward
|
|
; A0 : L Rewind
|
|
; 0xE1 = 8255 Port B - B7 : H Detected BREAK key during cassette playback
|
|
; B6 : Tape Read Data
|
|
; B5 : L Cassette Loaded
|
|
; B4 : L Write/Record enabled
|
|
; B3 : L Tape End detected
|
|
; B2 :
|
|
; B1 :
|
|
; B0 : H Video Blanking detected
|
|
; 0xE2 = 8255 Port C - C7 : Tape write data
|
|
; C6 : L Record (H = Play)
|
|
; C5 : H Block FF, REW, STOP
|
|
; C4 : L Eject Tape
|
|
; C3 : L Start IPL (enter boot mode and boot memory configuration, ie. 0x0000:0x7FFF - ROM, 0x8000:0xFFFF Ram (lower bank remapped to upper bank)
|
|
; C2 : Sound output (bit toggle to generate a frequency).
|
|
; C1 : H Set memory to normal mode, no ROM, RAM = 0x0000:0xFFFF
|
|
; C0 : H Blank screen via video gate
|
|
; 0xE3 = 8255 Control
|
|
; 0xE4 = 8253 Counter 0 - 31.25KHz divider
|
|
; 0xE5 = 8253 Counter 1 - Output of counter 0, normally 1 second pulse
|
|
; 0xE6 = 8253 Counter 2 - Output of counter 1, counts 12 hours.
|
|
; 0xE7 = 8253 Control
|
|
; 0xE8 = PIO Port A
|
|
; A7 : H 0xD000:0xD7FF or 0xC000:0xFFFF VRAN paged in.
|
|
; A6 : H Select Character VRAM (H) or Graphics VRAM (L)
|
|
; A5 : H Select 80 char mode, 40 char mode = L
|
|
; A4 : L Select all key strobe lines active, for detection of any key press.
|
|
; A3-A0: Keyboard strobe lines
|
|
; 0xE9 = PIO Port A Control
|
|
; 0xEA = PIO Port B
|
|
; B7-B0: Keyboard data lines
|
|
; 0xEB = PIO Port B Control
|
|
; 0xF4 = Colour CRT Background Colour Selection
|
|
; 0xF5 = Priority, Bit 3 = 0, Character comes to foreground, = 1, Graphics comes to foreground. 2:0 = Colour
|
|
; 0xF6 = Bit 4 Graphics Display on CRT (H), 2:0 colour VRAM enable to Colour CRT / CRT (if enabled).
|
|
; 0xF7 = Selection of VRAM bank in memory map when enabled, 0 = None, 1 = Blue, 2 = Red, 3 = Green
|
|
;
|
|
FDC EQU 0D8h ; MB8866 IO Region 0D8h - 0DBh
|
|
FDC_CR EQU FDC + 000h ; Command Register
|
|
FDC_STR EQU FDC + 000h ; Status Register
|
|
FDC_TR EQU FDC + 001h ; Track Register
|
|
FDC_SCR EQU FDC + 002h ; Sector Register
|
|
FDC_DR EQU FDC + 003h ; Data Register
|
|
FDC_MOTOR EQU FDC + 004h ; DS[0-3] and Motor control. 4 drives DS= BIT 0 -> Bit 2 = Drive number, 2=1,1=0,0=0 DS0, 2=1,1=0,0=1 DS1 etc
|
|
; bit 7 = 1 MOTOR ON LOW (Active)
|
|
FDC_SIDE EQU FDC + 005h ; Side select, Bit 0 when set = SIDE SELECT LOW,
|
|
FDC_DDEN EQU FDC + 006h ; Double density enable, 0 = double density, 1 = single density disks.
|
|
PPIA EQU 0E0H ; 8255 Port A
|
|
PPIB EQU 0E1H ; 8255 Port B
|
|
PPIC EQU 0E2H ; 8255 Port C
|
|
PPICTL EQU 0E3H ; 8255 Control Port
|
|
PIOA EQU 0E8H ; Z80 PIO Port A
|
|
PIOCTLA EQU 0E9H ; Z80 PIO Port A Control Port
|
|
PIOB EQU 0EAH ; Z80 PIO Port B
|
|
PIOCTLB EQU 0EBH ; Z80 PIO Port B Control Port
|
|
CRTBKCOLR EQU 0F4H ; Configure external CRT background colour.
|
|
CRTGRPHPRIO EQU 0F5H ; Graphics priority register, character or a graphics colour has front display priority.
|
|
CRTGRPHSEL EQU 0F6H ; Graphics output select on CRT or external CRT
|
|
GRAMCOLRSEL EQU 0F7H ; Graphics RAM colour bank select.
|
|
GRAMADDRL EQU 0C000H ; Graphics RAM lower address.
|
|
IBUFE EQU 0CF00H ; Cassette header start.
|
|
FDNAME EQU 0CF07H ; Floppy disk name when floppy sector read.(ie after type+IPLPRO).
|
|
ATRB EQU 0CF00H ; Tape attribute byte.
|
|
NAME EQU 0CF01H ; Tape image name.
|
|
SIZE EQU 0CF12H ; Tape image size.
|
|
DTADR EQU 0CF14H ; Tape image load address.
|
|
SUMDT EQU 0FFE0H ; Check sum data.
|
|
TMCNT EQU 0FFE2H ;
|
|
IBADR1 EQU 0CF00H ;
|
|
IBADR2 EQU 08000H
|
|
NTRACK EQU 0FFE0H ; Track number.
|
|
NSECT EQU 0FFE1H ; Sector number.
|
|
BSIZE EQU 0FFE2H ; Size of file to read.
|
|
STTR EQU 0FFE4H ; Starting track.
|
|
STSE EQU 0FFE5H ; Starting sector.
|
|
MTFG EQU 0FFE6H ; Motor flag.
|
|
CLBF0 EQU 0FFE7H ;
|
|
CLBF1 EQU 0FFE8H
|
|
CLBF2 EQU 0FFE9H
|
|
CLBF3 EQU 0FFEAH
|
|
RETRY EQU 0FFEBH
|
|
DRINO EQU 0FFECH
|
|
PRGSTART EQU 00000H
|
|
|
|
|
|
|
|
|
|
ORG PRGSTART
|
|
|
|
; NST = Rising edge, set memory to normal state, ie. 0x0000:FFFF = RAM and reset Z80.
|
|
; BST = Falling edge, enter IPL mode and reset Z80.
|
|
|
|
; Build time configuration code - build the original version when BUILDVERSION = 0 or the TZPU enhanced version when BUILDVERSION = 1
|
|
;IF BUILDVERSION = 1
|
|
;ELSE
|
|
;ENDIF
|
|
|
|
RESET: JR START
|
|
;
|
|
; NST RESET - Toggling
|
|
;
|
|
NST: LD A,003H ; Set PC1 NST=1, this toggles the memory into the normal state and resets the CPU thus executing from 0000 in RAM BANK 1
|
|
OUT (PPICTL),A
|
|
;
|
|
START: LD A,082H ; 8255 A=OUT B=IN C=OUT
|
|
OUT (PPICTL),A
|
|
LD A,058H ; BST=1 NST=0 OPEN=1 WRITE=1
|
|
OUT (PPIC),A
|
|
LD SP,SUMDT ; Setup stack
|
|
LD A,0F7H
|
|
OUT (PPIA),A ; All signals inactive, stop cassette.
|
|
LD A,00FH
|
|
OUT (PIOCTLA),A ; Setup PIO A
|
|
LD A,0CFH
|
|
OUT (PIOCTLB),A ; Setup PIO B
|
|
LD A,0FFH
|
|
OUT (PIOCTLB),A
|
|
;
|
|
; tranZPUter build ensure the FPGA and CPLD are set to the correct initial operating mode.
|
|
IF BUILDVERSION = 1
|
|
LD A,VMMODE_MZ2000 ; Ensure correct video mode is selected in FPGA.
|
|
OUT (VMCTRL),A
|
|
LD A,MODE_MZ2000|MODE_VIDEO_FPGA|SYSMODE_MZ2000|MODE_RESET_PRESERVE
|
|
;LD A,MODE_MZ2000|SYSMODE_MZ2000|MODE_RESET_PRESERVE
|
|
OUT (CPLDCFG),A
|
|
ENDIF
|
|
;
|
|
XOR A ; Set Graphics VRAM to default, no access to GRAM.
|
|
OUT (CRTGRPHSEL),A
|
|
OUT (CRTBKCOLR),A ; Set background colour on external output to black.
|
|
INC A
|
|
OUT (GRAMCOLRSEL),A ; Activate Blue graphics RAM bank for graphics operations (this is the default installed bank, red and green are optional).
|
|
LD A,007H
|
|
OUT (CRTGRPHPRIO),A ; Enable all colour bank graphic output with character priority.
|
|
LD A,0D3H
|
|
OUT (PIOA),A ; 11010011 = VRAM paged in for characters, 40 char mode, keyboard strobe bank 3.
|
|
; A7 : H 0xD000:0xD7FF or 0xC000:0xFFFF VRAN paged in.
|
|
; A6 : H Select Character VRAM (H) or Graphics VRAM (L)
|
|
; A5 : H Select 80 char mode, 40 char mode = L
|
|
; A4 : L Select all key strobe lines active, for detection of any key press.
|
|
; A3-A0: Keyboard strobe lines
|
|
LD HL,0D000H
|
|
LD A,0D8H ; Set to character VRAM top address.
|
|
CLEAR: LD (HL),000H ; DISPLAY CLEAR
|
|
INC HL
|
|
CP H
|
|
JR NZ,CLEAR
|
|
LD A,0FFH ; Disable all PPI A signals.
|
|
; A7 : L APSS Search for next program
|
|
; A6 : L Automatic playback at end of rewind
|
|
; A5 : L Automatic rewind during playback(recording)
|
|
; A4 : L Invert Video
|
|
; A3 : L Stop Cassette
|
|
; A2 : L Play Cassette
|
|
; A1 : L Fast Forward
|
|
; A0 : L Rewind
|
|
OUT (PPIA),A
|
|
LD A,003H ; Select GREEN graphics RAM bank.
|
|
OUT (GRAMCOLRSEL),A
|
|
CALL FILLVRAM ; Clear it.
|
|
LD A,002H ; Select RED graphics RAM bank.
|
|
OUT (GRAMCOLRSEL),A
|
|
CALL FILLVRAM
|
|
LD A,001H ; Select BLUE graphics RAM bank.
|
|
OUT (GRAMCOLRSEL),A
|
|
CALL FILLVRAM
|
|
LD A,013H ; 00010011 = Disable VRAM (select RAM), keystrobe bank 3.
|
|
OUT (PIOA),A
|
|
XOR A ; Clear control variables.
|
|
LD (DRINO),A
|
|
LD (MTFG),A
|
|
|
|
; Boot time function selection key processing.
|
|
KEYIN: IF BUILDVERSION = 1
|
|
CALL KEYS1
|
|
BIT 6,A ; F - Floppy disk
|
|
JP Z,FD
|
|
BIT 3,A ; C - Cassette.
|
|
JR Z,CMT
|
|
BIT 0,A ; / - Boot external rom.
|
|
JP Z,EXROMT
|
|
LD B,016H
|
|
CALL KEYS
|
|
BIT 4,A ; T - TZFS Monitor
|
|
JP Z,TZFS
|
|
BIT 6,A ; V - Verification Test
|
|
JP Z,VTEST
|
|
LD B,010H
|
|
CALL KEYS
|
|
BIT 0,A ; F1
|
|
JP Z,FUNC_F1
|
|
BIT 1,A ; F2
|
|
JP Z,FUNC_F2
|
|
BIT 2,A ; F3
|
|
JP Z,FUNC_F3
|
|
BIT 3,A ; F4
|
|
JP Z,FUNC_F4
|
|
BIT 4,A ; F5
|
|
JP Z,FUNC_F5
|
|
BIT 5,A ; F6
|
|
JP Z,FUNC_F6
|
|
BIT 6,A ; F7
|
|
JP Z,FUNC_F7
|
|
BIT 7,A ; F8
|
|
JP Z,FUNC_F8
|
|
ELSE
|
|
CALL KEYS1 ; Get a key to decide on first action.
|
|
BIT 3,A ; C - Cassette.
|
|
JR Z,CMT
|
|
BIT 0,A ; / - Boot external rom.
|
|
JP Z,EXROMT
|
|
ENDIF
|
|
JR NKIN ; No selection, so standard startup, try FDC then CMT.
|
|
|
|
FILLVRAM: LD HL,GRAMADDRL ; Base of Video Graphics RAM in address space.
|
|
DI
|
|
IN A,(PIOA) ; Read the PIO register and enable Graphics RAM
|
|
SET 7,A
|
|
RES 6,A
|
|
OUT (PIOA),A
|
|
LD DE,GRAMADDRL + 1
|
|
LD (HL),000H
|
|
LD BC,03E7FH
|
|
L0082: LDIR
|
|
RES 7,A ; Read the PIO and disable Video/Graphics RAM (use normal RAM).
|
|
SET 6,A
|
|
OUT (PIOA),A
|
|
EI
|
|
RET
|
|
|
|
KEYS1: LD B,014H ;Preserve A4-A7, set A4 to prevent all strobes low, then select line 5 (0-4).
|
|
KEYS: IN A,(PIOA)
|
|
AND 0F0H
|
|
OR B
|
|
OUT (PIOA),A
|
|
IN A,(PIOB) ;Read the strobed key.
|
|
RET
|
|
|
|
NKIN: IF BUILDVERSION = 1
|
|
JP TRYAG ; Straight to the menu, dont auto start FD or cassette.
|
|
ELSE
|
|
CALL FDCC ; FD available?
|
|
JP Z,FD ; Yes, try and boot from floppy.
|
|
JR CMT ; No, boot from CMT.
|
|
ENDIF
|
|
|
|
;
|
|
; Check to see if the Floppy Disk interface is installed.
|
|
; NZ = not installed.
|
|
; Z = installed.
|
|
;
|
|
FDCC: LD A,0A5H
|
|
LD B,A
|
|
OUT (FDC_TR),A
|
|
CALL DLY80U
|
|
IN A,(FDC_TR)
|
|
CP B
|
|
RET
|
|
;
|
|
; ;
|
|
; CMT CONTROL ;
|
|
; ;
|
|
;
|
|
CMT: CALL MOTORSTOP
|
|
CALL KYEMES
|
|
CALL RDINF
|
|
JR C,ST1
|
|
CALL LDMSG
|
|
LD HL,NAME
|
|
LD E,010H
|
|
LD C,010H
|
|
CALL DISP2
|
|
LD A,(IBUFE)
|
|
CP 001H
|
|
JR NZ,MISMCH
|
|
CALL RDDAT
|
|
ST1: PUSH AF
|
|
CALL FR ; Rewind tape.
|
|
POP AF
|
|
JP C,TRYAG
|
|
JP NST ; Set to normal memory mode and restart at 0x0000
|
|
|
|
MISMCH: LD HL,MES16
|
|
LD E,00AH
|
|
LD C,00FH
|
|
CALL DISP
|
|
CALL MOTORSTOP
|
|
SCF
|
|
JR ST1
|
|
;
|
|
;READ INFORMATION
|
|
; CF=1:ERROR
|
|
QRDI:
|
|
RDINF: DI
|
|
IN A,(PPIC)
|
|
SET 5,A
|
|
OUT (PPIC),A
|
|
LD D,004H
|
|
LD BC,0080H
|
|
LD HL,IBUFE
|
|
RD1: CALL MOTOR
|
|
JR C,STPEIR
|
|
CALL TMARK
|
|
JR C,STPEIR
|
|
CALL RTAPE
|
|
JR C,STPEIR
|
|
BIT 3,D
|
|
JR Z,EIRTN
|
|
STPEIR: CALL MOTORSTOP
|
|
EIRTN: EI
|
|
RET
|
|
;
|
|
;
|
|
;READ DATA
|
|
;
|
|
QRDD:
|
|
RDDAT: DI
|
|
LD D,008H
|
|
LD BC,(0CF12H)
|
|
LD HL,IBADR2
|
|
JR RD1
|
|
;
|
|
;
|
|
;READ TAPE
|
|
; BC=SIZE
|
|
; DE=LOAD ADDRSS
|
|
RTAPE: PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
LD H,002H
|
|
RTP2: CALL SPDIN
|
|
JR C,TRTN1 ; BREAK
|
|
JR Z,RTP2
|
|
LD D,H
|
|
LD HL,00000H
|
|
LD (SUMDT),HL
|
|
POP HL
|
|
POP BC
|
|
PUSH BC
|
|
PUSH HL
|
|
RTP3: CALL RBYTE
|
|
JR C,TRTN1
|
|
LD (HL),A
|
|
INC HL
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,RTP3
|
|
LD HL,(SUMDT)
|
|
CALL RBYTE
|
|
JR C,TRTN1
|
|
LD E,A
|
|
CALL RBYTE
|
|
JR C,TRTN1
|
|
CP L
|
|
JR NZ,RTP5
|
|
LD A,E
|
|
CP H
|
|
JR Z,TRTN1
|
|
RTP5: DEC D
|
|
JR Z,RTP6
|
|
LD H,D
|
|
JR RTP2
|
|
|
|
RTP6: CALL BOOTER
|
|
SCF
|
|
TRTN1: POP HL
|
|
POP BC
|
|
POP DE
|
|
RET
|
|
|
|
EDGE: IN A,(PPIB)
|
|
CPL
|
|
RLCA
|
|
RET C ; BREAK
|
|
RLCA
|
|
JR NC,EDGE ; WAIT ON LOW
|
|
L016A: IN A,(PPIB)
|
|
CPL
|
|
RLCA
|
|
RET C ; BREAK
|
|
RLCA
|
|
JR C,L016A ; WAIT ON HIGH
|
|
RET
|
|
; 1 BYTE READ
|
|
; DATA=A
|
|
; SUMDT STORE
|
|
RBYTE: PUSH HL
|
|
LD HL,00800H ; 8 BITS
|
|
RBY1: CALL SPDIN
|
|
JR C,RBY3 ; BREAK
|
|
JR Z,RBY2 ; BIT=0
|
|
PUSH HL
|
|
LD HL,(SUMDT) ;CHECKSUM
|
|
INC HL
|
|
LD (SUMDT),HL
|
|
POP HL
|
|
SCF
|
|
RBY2: RL L
|
|
DEC H
|
|
JR NZ,RBY1
|
|
CALL EDGE
|
|
LD A,L
|
|
RBY3: POP HL
|
|
RET
|
|
;TAPE MARK DETECT
|
|
; E=L:INFORMATION
|
|
; E=S:DATA
|
|
TMARK: PUSH HL
|
|
LD HL,01414H
|
|
BIT 3,D
|
|
JR NZ,TM0
|
|
ADD HL,HL
|
|
TM0: LD (TMCNT),HL
|
|
TM1: LD HL,(TMCNT)
|
|
TM2: CALL SPDIN
|
|
JR C,RBY3
|
|
JR Z,TM1
|
|
DEC H
|
|
JR NZ,TM2
|
|
TM3: CALL SPDIN
|
|
JR C,RBY3
|
|
JR NZ,TM1
|
|
DEC L
|
|
JR NZ,TM3
|
|
CALL EDGE
|
|
JR RBY3
|
|
|
|
SPDIN: CALL EDGE ;WAIT ON HIGH
|
|
RET C ;BREAK
|
|
CALL DLY2
|
|
IN A,(PPIB) ;READ BIT
|
|
AND 040H
|
|
RET
|
|
;
|
|
;
|
|
;MOTOR ON
|
|
MOTOR: PUSH DE
|
|
PUSH BC
|
|
PUSH HL
|
|
IN A,(PPIB)
|
|
AND 020H
|
|
JR Z,MOTRD
|
|
LD HL,MES6
|
|
LD E,00AH
|
|
LD C,00EH
|
|
CALL DISP
|
|
CALL OPEN
|
|
MOT1: IN A,(PIOB)
|
|
CPL
|
|
RLCA
|
|
JR C,MOTR
|
|
IN A,(PPIB)
|
|
AND 020H
|
|
JR NZ,MOT1
|
|
CALL KYEMES
|
|
CALL DEL1M
|
|
MOTRD: CALL PLAY
|
|
MOTR: POP HL
|
|
POP BC
|
|
POP DE
|
|
RET
|
|
;
|
|
;
|
|
;MOTOR STOP
|
|
MOTORSTOP: LD A,0F7H
|
|
OUT (PPIA),A
|
|
CALL DEL6
|
|
LD A,0FFH
|
|
OUT (PPIA),A
|
|
RET
|
|
;EJECT
|
|
OPEN: LD A,008H ;Reset PC4 - EJECT activate
|
|
OUT (PPICTL),A
|
|
CALL DEL6
|
|
LD A,009H
|
|
OUT (PPICTL),A ;Set PC4 - Deactivate EJECT
|
|
RET
|
|
|
|
KYEMES: LD HL,MES3
|
|
LD E,004H
|
|
LD C,01CH
|
|
CALL DISP
|
|
RET
|
|
;
|
|
;PLAY
|
|
PLAY: LD A,0FBH
|
|
OUT (PPIA),A
|
|
CALL DEL6
|
|
LD A,0FFH
|
|
OUT (PPIA),A
|
|
RET
|
|
|
|
FR: LD A,0FEH
|
|
FR1: OUT (PPIA),A
|
|
CALL DEL6
|
|
LD A,0FFH
|
|
OUT (PPIA),A
|
|
IN A,(PPIC)
|
|
RES 5,A
|
|
OUT (PPIC),A
|
|
RET
|
|
;
|
|
;TIMING DEL
|
|
DM1: PUSH AF
|
|
DM1A: XOR A
|
|
DM1B: DEC A
|
|
JR NZ,DM1B
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,DM1A
|
|
POP AF
|
|
POP BC
|
|
RET
|
|
|
|
DEL6: PUSH BC
|
|
LD BC,RDINF
|
|
JR DM1
|
|
|
|
DEL1M: PUSH BC
|
|
LD BC,060FH
|
|
JR DM1
|
|
;
|
|
;TAPE DELAY TIMING
|
|
;
|
|
;
|
|
DLY2: LD A,031H
|
|
DLY2A: DEC A
|
|
JP NZ,DLY2A
|
|
RET
|
|
|
|
LDMSG: LD HL,MES1 ; Address of string to display.
|
|
LD E,000H ; Offset into first 256 characters of screen for message display.
|
|
LD C,00EH ; Number of characters to display.
|
|
JR DISP
|
|
|
|
DISP2: LD A,0D3H
|
|
OUT (PIOA),A
|
|
JR DISP1
|
|
|
|
BOOTER: LD HL,MES8
|
|
LD E,00AH
|
|
LD C,00DH
|
|
DISP: LD A,0D3H ; Page in character video ram.
|
|
OUT (PIOA),A
|
|
EXX
|
|
LD HL,0D000H ; Clear screen, entire 0xD000:0xDFFF area
|
|
LD A,0D8H ; Top of character VRAM.
|
|
DISP3: LD (HL),000H
|
|
INC HL
|
|
CP H
|
|
JR NZ,DISP3 ; When H moves to 0x0E then complete.
|
|
EXX
|
|
DISP1: XOR A
|
|
LD B,A
|
|
LD D,0D0H ; E points to offset in 0xD000 area for message display, given by caller.
|
|
LDIR ; HL set by caller to message string. C set to string length, B always 0.
|
|
LD A,013H ; Restore memory, page out video ram.
|
|
OUT (PIOA),A
|
|
RET
|
|
|
|
;
|
|
; Print method with full screen addressable.
|
|
;
|
|
PRTSTR: IF BUILDVERSION = 1
|
|
LD A,0D3H ; Enable VRAM.
|
|
OUT (PIOA),A
|
|
LD A,(HL) ; HL points to destination address and null terminated string.
|
|
LD E,A
|
|
INC HL
|
|
LD A,(HL)
|
|
LD D,A
|
|
PRTSTR1: INC HL
|
|
LD A,(HL) ; Copy from source (HL) to destination (DE) until a null byte is encountered.
|
|
OR A
|
|
JR Z,PRTSTR2
|
|
LD (DE),A
|
|
INC DE
|
|
JR PRTSTR1
|
|
PRTSTR2: LD A,013H ; Restore memory, page out video ram.
|
|
OUT (PIOA),A
|
|
RET
|
|
ENDIF
|
|
|
|
;
|
|
MES1: DB "IPL is loading"
|
|
MES3: DB "IPL is looking for a program"
|
|
MES6: IF BUILDVERSION = 1
|
|
DB "Make ready CMT"
|
|
ELSE
|
|
DB "Make ready CMT"
|
|
ENDIF
|
|
MES8: DB "Loading error"
|
|
MES9: DB "Make ready FD"
|
|
MES10: IF BUILDVERSION = 1
|
|
DW 0D05AH
|
|
DB "Select boot option:",000H
|
|
ELSE
|
|
DB "Press F or C"
|
|
ENDIF
|
|
MES11: IF BUILDVERSION = 1
|
|
DW 0D0ABH
|
|
DB "F: Floppy diskette",000H
|
|
ELSE
|
|
DB "F:Floppy diskette"
|
|
ENDIF
|
|
MES12: IF BUILDVERSION = 1
|
|
DW 0D0D3H
|
|
DB "C: Cassette tape",000H
|
|
ELSE
|
|
DB "C:Cassette tape"
|
|
ENDIF
|
|
MES13: DB "Drive No? (1-4)"
|
|
MES14: DB "This diskette is not master"
|
|
MES15: DB "Pressing S key starts the CMT"
|
|
MES16: DB "File mode error"
|
|
;
|
|
IPLMC: DB 01H
|
|
DB "IPLPRO"
|
|
|
|
IF BUILDVERSION = 1
|
|
MESBOOT: DW 0D0FBH
|
|
DB "B: NST Boot", 000H
|
|
MESTZFS: DW 0D123H
|
|
DB "T: TZFS Monitor", 000H
|
|
MESF1: DW 0D14BH
|
|
DB "F1: BASIC 1Z-001",000H
|
|
MESF2: DW 0D173H
|
|
DB "F2: BASIC 1Z-002",000H
|
|
MESF3: DW 0D19BH
|
|
DB "F3: MZ-80A",000H
|
|
MESF4: DW 0D1C3H
|
|
DB "F4: MZ-700",000H
|
|
MESF5: DW 0D1EBH
|
|
DB "F5: MZ-80B",000H
|
|
MESF6: DW 0D213H
|
|
DB 000H, "F6: ",000H
|
|
MESF7: DW 0D23BH
|
|
DB 000H, "F7: ",000H
|
|
MESF8: DW 0D263H
|
|
DB 000H, "F8: ",000H
|
|
ENDIF
|
|
|
|
; IY Offset locations points to FD control record.
|
|
; NTRACK 0FFE0H
|
|
; NSECT 0FFE1H
|
|
; BSIZE 0FFE2H
|
|
; STTR 0FFE4H
|
|
; STSE 0FFE5H
|
|
; MTFG 0FFE6H
|
|
; CLBF0 0FFE7H
|
|
; CLBF1 0FFE8H
|
|
; CLBF2 0FFE9H
|
|
; CLBF3 0FFEAH
|
|
; RETRY 0FFEBH
|
|
; DRINO 0FFECH
|
|
;
|
|
; DRIVE NO=DRINO (0-3)
|
|
;
|
|
; CASE OF SEQUENTIAL READ
|
|
; DRIVE NO=DRINO (0-3)
|
|
; BYTE SIZE =IY+2,3
|
|
; ADDRESS =IX+0,1
|
|
; NEXT TRACK =IY+0
|
|
; NEXT SECTOR =IY+1
|
|
; START TRACK =IY+4
|
|
; START SECTOR =IY+5
|
|
;
|
|
; Floppy record track 1, sector 1:
|
|
; 0x00 Attribute (1 = machine code).
|
|
; 0x01 : 0x06 Disk indicator, IPLPRO for bootable disks.
|
|
; 0x07 : 0x0F Floppy image name
|
|
; 0x10 : 0x11
|
|
; 0x12 : 0x13 Load address of file.
|
|
; 0x14 : 0x15 Size of file/boot file.
|
|
; Boot file commences at track 1, sector 2.
|
|
; Data is inverted (due to MB8877 controller).
|
|
;
|
|
;FD
|
|
FD: LD IX,IBUFE
|
|
XOR A
|
|
LD (0CF1EH),A ; Image load location.
|
|
LD (0CF1FH),A
|
|
LD IY,SUMDT
|
|
LD HL,0100H ; Load one 256 byte sector - the disk record.
|
|
LD (IY+002H),L
|
|
LD (IY+003H),H
|
|
CALL BREAD ; Read the first sector to verify if it is a valid disk.
|
|
LD HL,IBUFE ; Perform a MASTER CHECK, ie. code 01 + IPLPRO
|
|
LD DE,IPLMC
|
|
LD B,006H
|
|
MCHECK: LD C,(HL) ; Should be 0x1 and IPLPRO at beginning of first track to indicate bootable disk.
|
|
LD A,(DE)
|
|
CP C
|
|
JP NZ,NMASTE
|
|
INC HL
|
|
INC DE
|
|
DJNZ MCHECK
|
|
CALL LDMSG ; Ok, so bootable, indicate loading.
|
|
LD HL,FDNAME ; Offset into first sector for name of file.
|
|
LD E,010H
|
|
LD C,00AH
|
|
CALL DISP2 ; Display Floppy image name.
|
|
LD IX,IBADR2
|
|
LD HL,(0CF14H) ; Setup size of image load.
|
|
LD (IY+002H),L
|
|
LD (IY+003H),H
|
|
CALL BREAD
|
|
CALL MOFF
|
|
JP NST
|
|
|
|
NODISK: LD HL,MES9
|
|
LD E,00AH
|
|
LD C,00DH
|
|
CALL DISP
|
|
JP ERR1
|
|
;
|
|
; READY CHECK
|
|
;
|
|
READY: LD A,(MTFG) ; Motor flag
|
|
RRCA
|
|
CALL NC,MTON ; Check if motor is already running (cant read hardware so maintain in memory mirror flag).
|
|
LD A,(DRINO) ; Get drive number.
|
|
OR 084H ; Ensure the motor on and high select bit are set (Drives 0-3 are represented in hardware as 4-7).
|
|
OUT (FDC_MOTOR),A ; Send to motor/drive select register.
|
|
XOR A
|
|
CALL DLY60M ; Small delay to allow the motor to spin up etc.
|
|
LD HL,00000H
|
|
REDY0: DEC HL ; Delay loop, 65536 loops checking for the BUSY flag to be reset.
|
|
LD A,H
|
|
OR L
|
|
JR Z,NODISK
|
|
IN A,(FDC_CR) ; Get controller statue.
|
|
CPL ; Data bus is inverted on original Sharp controller.
|
|
RLCA
|
|
JR C,REDY0 ; Bit set, controller busy, loop. No new command can be issued whilst the controller is busy.
|
|
LD A,(DRINO)
|
|
LD C,A
|
|
LD HL,CLBF0 ; Get correct control block flag for selected drive.
|
|
LD B,000H
|
|
ADD HL,BC
|
|
BIT 0,(HL) ; Check to see if drive calibrated. Exit if it has been calibrated.
|
|
RET NZ
|
|
CALL RCLB ; Else call calibration, set flag and exit.
|
|
SET 0,(HL)
|
|
RET
|
|
;
|
|
; MOTOR ON
|
|
;
|
|
MTON: LD A,080H ; Spin up motor by enabling motor control.
|
|
OUT (FDC_MOTOR),A
|
|
LD B,00AH ; Wait 1 second for spinup.
|
|
MTD1: LD HL,03C19H
|
|
MTD2: DEC HL
|
|
LD A,L
|
|
OR H
|
|
JR NZ,MTD2
|
|
DJNZ MTD1
|
|
LD A,001H ; Set flag to indicate motor running.
|
|
LD (MTFG),A
|
|
RET
|
|
;
|
|
; Track SEEK
|
|
;
|
|
SEEK: LD A,01BH ; Send seek command to controller, the previous stored track will be searched.
|
|
CPL
|
|
OUT (FDC_CR),A
|
|
CALL BUSY ; Wait until the BUSY flag is cleared.
|
|
CALL DLY60M
|
|
IN A,(FDC_STR) ; Get status for caller to inspect.
|
|
CPL
|
|
AND 099H ; Mask Nit Ready, Seek Error, CRC Error, Busy flags, any set the error occurred.
|
|
RET
|
|
;
|
|
;MOTOR OFF
|
|
;
|
|
MOFF: CALL DLY1M ; Delay 1ms to allow previous commands to complete.
|
|
XOR A ; Clear the motor (and drive select) flags.
|
|
OUT (FDC_MOTOR),A
|
|
LD (CLBF0),A ; Clear all disk control block flags.
|
|
LD (CLBF1),A
|
|
LD (CLBF2),A
|
|
LD (CLBF3),A
|
|
LD (MTFG),A
|
|
RET
|
|
;
|
|
; RECALIBRATION
|
|
;
|
|
RCLB: PUSH HL ; Recalibration is made by sending the RESTORE command to the controller.
|
|
LD A,00BH
|
|
CPL
|
|
OUT (FDC_CR),A
|
|
CALL BUSY ; Wait until the BUSY flag is reset.
|
|
CALL DLY60M
|
|
IN A,(FDC_STR) ; Inspect status, TRACK 0 flag should be set.
|
|
CPL
|
|
AND 085H
|
|
XOR 004H
|
|
POP HL
|
|
RET Z ; If track 0 flag set, exit.
|
|
JP ERR ; Otherwise display error message as track 0 cannot be located, ie. no disk or corruption.
|
|
;
|
|
; BUSY AND WAIT
|
|
;
|
|
BUSY: PUSH DE ; Loop 65536 x 7 times for the BUSY flag in the controller to be reset.
|
|
PUSH HL ; Normally a command would have been sent and this method called.
|
|
CALL DLY80U
|
|
LD E,007H
|
|
BUSY2: LD HL,00000H
|
|
BUSY0: DEC HL
|
|
LD A,H
|
|
OR L
|
|
JR Z,BUSY1
|
|
IN A,(FDC_STR) ; Get status, invert due to original controller bus being inverted, the test bit 0, ie. BUSY flag.
|
|
CPL
|
|
RRCA
|
|
JR C,BUSY0
|
|
POP HL
|
|
POP DE
|
|
RET
|
|
|
|
BUSY1: DEC E
|
|
JR NZ,BUSY2
|
|
JP ERR
|
|
;
|
|
; DATA CHECK
|
|
;
|
|
CONVRT: LD B,000H
|
|
LD DE,0010H
|
|
LD HL,(0CF1EH)
|
|
XOR A
|
|
TRANS: SBC HL,DE
|
|
JR C,TRANS1
|
|
INC B
|
|
JR TRANS
|
|
|
|
TRANS1: ADD HL,DE
|
|
LD H,B ; B contains the track.
|
|
INC L ; L contains the sector.
|
|
LD (IY+004H),H
|
|
LD (IY+005H),L
|
|
DCHK: LD A,(DRINO) ; Check drive number is valid.
|
|
CP 004H
|
|
JR NC,DTCK1
|
|
LD A,(IY+004H) ; Check track boundary
|
|
CP 046H
|
|
JR NC,DTCK1
|
|
LD A,(IY+005H) ; Check sector boundary, cant be less than 1 or greater than 16
|
|
OR A
|
|
JR Z,DTCK1
|
|
CP 011H
|
|
JR NC,DTCK1
|
|
LD A,(IY+002H) ; Check the load size is not zero.
|
|
OR (IY+003H)
|
|
RET NZ
|
|
DTCK1: JP ERR
|
|
;
|
|
; SEQUENTIAL READ
|
|
;
|
|
; DRIVE NO=DRINO (0-3)
|
|
; BYTE SIZE =IY+2,3
|
|
; ADDRESS =IX+0,1
|
|
; NEXT TRACK =IY+0
|
|
; NEXT SECTOR =IY+1
|
|
; START TRACK =IY+4
|
|
; START SECTOR =IY+5
|
|
BREAD: DI
|
|
CALL CONVRT
|
|
LD A,00AH ; 10 tries before giving up.
|
|
LD (RETRY),A
|
|
READ1: CALL READY ; Perform a recalibration and check for drive readiness.
|
|
LD D,(IY+003H) ; Test to see if the size is a multiple of the sector size, if it isnt then increment sector count.
|
|
LD A,(IY+002H) ; D:A contain the number of bytes to read. D is in 256 blocks.
|
|
OR A
|
|
JR Z,RE0
|
|
INC D
|
|
RE0: LD A,(IY+005H) ; Get start sector.
|
|
LD (IY+001H),A ; Set as next sector.
|
|
LD A,(IY+004H) ; Get start track.
|
|
LD (IY+000H),A ; Set as next track.
|
|
PUSH IX
|
|
POP HL
|
|
RE8: SRL A ; Adjust track to account for heads, so shift right 1 place.
|
|
CPL
|
|
OUT (FDC_DR),A
|
|
JR NC,RE1 ; Set side according to track LSB. 1 sets the /SIDE1 signal to select lower head.
|
|
LD A,001H
|
|
JR RE2
|
|
|
|
RE1: LD A,000H
|
|
RE2: CPL
|
|
OUT (FDC_SIDE),A
|
|
CALL SEEK ; Seek to track loaded, 0 at start.
|
|
JR NZ,REE ; SEEK sets the NZ flag if any error occurred.
|
|
LD C,FDC_DR ; FDC Data register for INI command below.
|
|
LD A,(IY+000H) ; Get track and set.
|
|
SRL A ; Adjust for two heads.
|
|
CPL
|
|
OUT (FDC_TR),A
|
|
LD A,(IY+001H) ; Get sector and set.
|
|
CPL
|
|
OUT (FDC_SCR),A
|
|
EXX
|
|
LD HL,RE3 ; Place address onto stack for RET C in data input loop.
|
|
PUSH HL
|
|
EXX
|
|
LD A,094H ; Command: multiple sector read.
|
|
CPL
|
|
OUT (FDC_CR),A
|
|
CALL WAIT ; Wait until controller finished processing and deactivates busy flag.
|
|
RE6: LD B,000H
|
|
RE4: IN A,(FDC_STR) ; Read Command Type II Status Register values.
|
|
RRCA
|
|
RET C ; Exit if the controller is busy.
|
|
RRCA
|
|
JR C,RE4 ; Wait for DRQ to go active.
|
|
INI ; Read byte from controller, decrement B and increment HL.
|
|
JR NZ,RE4 ; B = 0? Loop for the expected number of bytes in sector.
|
|
INC (IY+001H)
|
|
LD A,(IY+001H) ; Next sector past limit?
|
|
CP 011H ; 16 Sectors per track is the limit.
|
|
JR Z,RETS ; Complete track read, exit.
|
|
DEC D ; Next 256 byte block.
|
|
JR NZ,RE6 ; Loop until all bytes we expect are read.
|
|
JR RE5 ; Exit when all are read.
|
|
|
|
RETS: DEC D ; We hit track end so decrement block as per above when we continue to loop.
|
|
RE5: LD A,0D8H ; Command: FORCED INTERRUPT to abort the multiple sector transfer command.
|
|
CPL
|
|
OUT (FDC_CR),A
|
|
CALL BUSY ; Wait until the BUSY signal goes inactive.
|
|
RE3: IN A,(FDC_STR) ; Get type 4 command status values.
|
|
CPL
|
|
AND 0FFH ; All flags should be reset if successful, retry otherwise.
|
|
JR NZ,REE
|
|
EXX
|
|
POP HL
|
|
EXX
|
|
LD A,(IY+001H) ; Get last sector read.
|
|
CP 011H ; Greater than 16?
|
|
JR NZ,REX ; If less, skip track increment.
|
|
LD A,001H ; Set to sector 1 and increment track.
|
|
LD (IY+001H),A
|
|
INC (IY+000H)
|
|
REX: LD A,D ; Check D (bytes in 256 byte chunks expected).
|
|
OR A
|
|
JR NZ,RE7 ; If it is not zero then we need to retry,
|
|
LD A,080H ; Turn motor off to complete.
|
|
OUT (FDC_MOTOR),A
|
|
RET
|
|
|
|
RE7: LD A,(IY+000H) ; Retrieve next track and redo the read with remaining bytes.
|
|
JR RE8
|
|
|
|
REE: LD A,(RETRY) ; The abort (FORCED INTERRUPT) command wasnt successful so retry the complete read.
|
|
DEC A
|
|
LD (RETRY),A
|
|
JR Z,ERR ; Retries expired then raise error.
|
|
CALL RCLB ; Perform a recalibration before the retry.
|
|
JP READ1
|
|
;
|
|
; Wait until BUSY flag resets - controller has accepted the command, processed it and now ready for data in/out.
|
|
;
|
|
WAIT: PUSH DE
|
|
PUSH HL
|
|
CALL DLY80U ; Short delay to allow the controller to act on the commmand.
|
|
; LD E,008H ; 8 x 65536 x 1/CPU FREQ max delay. 131ms with a 4MHz clock.
|
|
LD E,0FFH ; 8 x 65536 x 1/CPU FREQ max delay. 131ms with a 4MHz clock.
|
|
WAIT2: LD HL,00000H
|
|
WAIT0: DEC HL
|
|
LD A,H
|
|
OR L
|
|
JR Z,WAIT1
|
|
IN A,(FDC_STR) ; Get BUSY flag, loop if it is set.
|
|
CPL
|
|
RRCA
|
|
JR NC,WAIT0
|
|
POP HL
|
|
POP DE
|
|
RET
|
|
|
|
WAIT1: DEC E
|
|
JR NZ,WAIT2
|
|
JR ERR
|
|
|
|
NMASTE: LD HL,MES14
|
|
LD E,007H
|
|
LD C,01BH
|
|
CALL DISP
|
|
JR ERR1
|
|
;
|
|
; ;
|
|
; ERRROR OR BREAK ;
|
|
; ;
|
|
;
|
|
ERR: CALL BOOTER
|
|
ERR1: CALL MOFF
|
|
LD SP,SUMDT
|
|
|
|
TRYAG: IF BUILDVERSION = 1
|
|
LD HL,MES10
|
|
CALL PRTSTR
|
|
CALL FDCC ; Check for the FD Interface.
|
|
JR NZ,MENU1 ; NZ = FD not available.
|
|
LD HL,MES11 ; Floppy menu choice.
|
|
CALL PRTSTR
|
|
MENU1: LD HL,MES12 ; Cassette menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESBOOT ; Boot current RAM program.
|
|
CALL PRTSTR
|
|
LD HL,MESTZFS ; TZFS menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF1 ; Function 1 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF2 ; Function 2 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF3 ; Function 3 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF4 ; Function 4 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF5 ; Function 5 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF6 ; Function 6 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF7 ; Function 7 menu choice.
|
|
CALL PRTSTR
|
|
LD HL,MESF8 ; Function 8 menu choice.
|
|
CALL PRTSTR
|
|
GETCHOICE: CALL KEYS1
|
|
BIT 6,A ; F - Floppy disk
|
|
JP Z,DNO
|
|
BIT 3,A ; C - Cassette.
|
|
JP Z,CMT
|
|
BIT 2,A ; B - Boot current RAM 0x0000 program.
|
|
JP Z,NST
|
|
BIT 0,A ; / - Boot external rom.
|
|
JP Z,EXROMT
|
|
LD B,016H
|
|
CALL KEYS
|
|
BIT 4,A ; T - TZFS Monitor
|
|
JP Z,TZFS
|
|
BIT 6,A ; V - Verification Test
|
|
JP Z,VTEST
|
|
LD B,010H
|
|
CALL KEYS
|
|
BIT 0,A ; F1
|
|
JP Z,FUNC_F1
|
|
BIT 1,A ; F2
|
|
JP Z,FUNC_F2
|
|
BIT 2,A ; F3
|
|
JP Z,FUNC_F3
|
|
BIT 3,A ; F4
|
|
JP Z,FUNC_F4
|
|
BIT 4,A ; F5
|
|
JP Z,FUNC_F5
|
|
BIT 5,A ; F6
|
|
JP Z,FUNC_F6
|
|
BIT 6,A ; F7
|
|
JP Z,FUNC_F7
|
|
BIT 7,A ; F8
|
|
JP Z,FUNC_F8
|
|
JR GETCHOICE
|
|
ELSE
|
|
CALL FDCC ; Check for the FD Interface.
|
|
JR NZ,TRYAG3 ; NZ = FD not available.
|
|
LD HL,MES10
|
|
LD E,05AH
|
|
LD C,00CH
|
|
CALL DISP2
|
|
LD E,0ABH
|
|
LD C,011H
|
|
CALL DISP2
|
|
LD E,0D3H
|
|
LD C,00FH
|
|
CALL DISP2
|
|
TRYAG1: CALL KEYS1
|
|
BIT 3,A
|
|
JP Z,CMT
|
|
BIT 6,A
|
|
JR Z,DNO
|
|
JR TRYAG1
|
|
ENDIF
|
|
|
|
DNO: LD HL,MES13
|
|
LD E,00AH
|
|
LD C,00FH
|
|
CALL DISP
|
|
DNO10: LD D,012H
|
|
CALL DNO0
|
|
JR NC,DNO3
|
|
LD D,018H
|
|
CALL DNO0
|
|
JR NC,DNO3
|
|
JR DNO10
|
|
|
|
DNO3: LD A,B
|
|
LD (DRINO),A
|
|
JP FD
|
|
|
|
TRYAG3: LD HL,MES15
|
|
LD E,054H
|
|
LD C,01DH
|
|
CALL DISP2
|
|
TRYAG4: LD B,006H
|
|
TRYAG5: CALL KEYS
|
|
BIT 3,A
|
|
JP Z,CMT
|
|
JR TRYAG5
|
|
|
|
DNO0: IN A,(PIOA)
|
|
AND 0F0H
|
|
OR D
|
|
OUT (PIOA),A
|
|
IN A,(PIOB)
|
|
LD B,000H
|
|
LD C,004H
|
|
RRCA
|
|
DNO1: RRCA
|
|
RET NC
|
|
INC B
|
|
DEC C
|
|
JR NZ,DNO1
|
|
RET
|
|
;
|
|
; TIME DELAY (1M &60M &80U )
|
|
;
|
|
DLY80U: PUSH DE
|
|
LD DE,000DH
|
|
JP DLYT
|
|
|
|
DLY1M: PUSH DE
|
|
LD DE,L0082
|
|
JP DLYT
|
|
|
|
DLY60M: PUSH DE
|
|
LD DE,01A2CH
|
|
DLYT: DEC DE
|
|
LD A,E
|
|
OR D
|
|
JR NZ,DLYT
|
|
POP DE
|
|
RET
|
|
;
|
|
;
|
|
; ;
|
|
; INTRAM EXROM ;
|
|
; ;
|
|
;
|
|
EXROMT: LD HL,IBADR2
|
|
LD IX,EROM1
|
|
JR SEROMA
|
|
|
|
EROM1: IN A,(0F9H) ; Check to see if the external ROM has been installed.
|
|
CP 000H
|
|
JP NZ,NKIN ; Byte is not 0, no rom so exit.
|
|
LD IX,EROM2
|
|
ERMT1: JR SEROMA
|
|
|
|
EROM2: IN A,(0F9H)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,L
|
|
OR H
|
|
JR NZ,ERMT1
|
|
OUT (0F8H),A
|
|
JP NST
|
|
|
|
; Output a 16bit address to the external ROM control registers.
|
|
SEROMA: LD A,H
|
|
OUT (0F8H),A
|
|
LD A,L
|
|
OUT (0F9H),A
|
|
LD D,004H
|
|
SEROMD: DEC D ; Short pause for the address to latch.
|
|
JR NZ,SEROMD
|
|
JP (IX) ; Pass control to the function provided in IX for address evaluation.
|
|
|
|
;
|
|
; Load option extensions under the tranZPUter.
|
|
;
|
|
TZFS: IF BUILDVERSION = 1
|
|
JP TRYAG
|
|
ENDIF
|
|
|
|
FUNC_F1: IF BUILDVERSION = 1
|
|
LD HL,FN_1
|
|
CALL SDLOADFILE
|
|
JP TRYAG
|
|
FN_1: DB "BASIC MZ-1Z001",NULL,NULL,NULL
|
|
ENDIF
|
|
|
|
FUNC_F2: IF BUILDVERSION = 1
|
|
LD HL,FN_2
|
|
CALL SDLOADFILE
|
|
JP TRYAG
|
|
FN_2: DB "BASIC MZ-1Z002",NULL,NULL,NULL
|
|
ENDIF
|
|
|
|
FUNC_F3: IF BUILDVERSION = 1
|
|
CALL SETMZ80A
|
|
JP TRYAG
|
|
ENDIF
|
|
|
|
FUNC_F4: IF BUILDVERSION = 1
|
|
CALL SETMZ700
|
|
JP TRYAG
|
|
ENDIF
|
|
|
|
FUNC_F5: IF BUILDVERSION = 1
|
|
CALL SETMZ80B
|
|
JP TRYAG
|
|
ENDIF
|
|
|
|
FUNC_F6: IF BUILDVERSION = 1
|
|
LD HL,FN_6
|
|
CALL SDLOADFILE
|
|
JP TRYAG
|
|
FN_6: DB NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
|
|
ENDIF
|
|
|
|
FUNC_F7: IF BUILDVERSION = 1
|
|
LD HL,FN_7
|
|
CALL SDLOADFILE
|
|
JP TRYAG
|
|
FN_7: DB NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
|
|
ENDIF
|
|
|
|
; A simple graphics test routine, not optimised, just to indicate if the graphics are working on the tranZPUter.
|
|
FUNC_F8: IF BUILDVERSION = 1
|
|
LD A,0AFH ; Setup to enable FPGA video.
|
|
OUT (06EH),A
|
|
LD A,000H
|
|
OUT (0B9H),A
|
|
LD A,07FH
|
|
OUT (0B8H),A
|
|
LD A,0D3H
|
|
OUT (PIOA),A
|
|
F8CLR: LD HL,0D800H
|
|
LD A,0E0H
|
|
F8CLR1: LD (HL),070H ; Load zero's
|
|
INC HL
|
|
CP H
|
|
JR NZ,F8CLR1
|
|
;
|
|
F8LOOP: LD A,001H ; Select BLUE graphics RAM bank.
|
|
OUT (GRAMCOLRSEL),A
|
|
CALL FUNCFILLW
|
|
LD A,002H ; Select RED graphics RAM bank.
|
|
OUT (GRAMCOLRSEL),A
|
|
CALL FUNCFILLW
|
|
LD A,003H ; Select GREEN graphics RAM bank.
|
|
OUT (GRAMCOLRSEL),A
|
|
CALL FUNCFILLW
|
|
JR F8LOOP
|
|
|
|
FUNCFILLW: EX AF,AF' ; 2nd bank
|
|
XOR A
|
|
FUNCFILLW1: EX AF,AF' ; 1st bank
|
|
CALL FUNCFILL
|
|
EX AF,AF' ; 2nd bank
|
|
INC A
|
|
JR NZ,FUNCFILLW1
|
|
EX AF,AF' ; 1st bank
|
|
CALL FUNCFILL
|
|
RET
|
|
|
|
FUNCFILL: DI
|
|
LD HL,GRAMADDRL ; Base of Video Graphics RAM in address space.
|
|
IN A,(PIOA) ; Read the PIO register and enable Graphics RAM
|
|
SET 7,A
|
|
RES 6,A
|
|
OUT (PIOA),A
|
|
LD DE,GRAMADDRL + 1
|
|
EX AF,AF'
|
|
LD (HL),A
|
|
LD BC,03E7FH
|
|
LDIR
|
|
EX AF,AF'
|
|
;
|
|
FUNCFILL2: IN A,(PIOA)
|
|
RES 7,A ; Read the PIO and disable Video/Graphics RAM (use normal RAM).
|
|
SET 6,A
|
|
OUT (PIOA),A
|
|
EI
|
|
RET
|
|
ENDIF
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; SERVICE COMMAND METHODS
|
|
;-------------------------------------------------------------------------------
|
|
|
|
SDLOADFILE: IF BUILDVERSION = 1
|
|
; HL Contains the source filename to use, copy into structure.
|
|
LD DE,TZSVC_FILENAME
|
|
LD BC,TZSVCFILESZ
|
|
LDIR ; Copy in the MZF filename.
|
|
LD HL,00000H ; Setup the load address to 0x0000 = default load address in IPL mode.
|
|
LD (TZSVC_LOADADDR),HL
|
|
;
|
|
LD A,TZSVC_FTYPE_MZF ; Default to full file load.
|
|
LD (TZSVC_FILE_TYPE),A
|
|
|
|
LD A,0FFH ; We have to use filenames not index numbers so mark as unused.
|
|
LD (TZSVC_FILE_NO), A
|
|
|
|
LD A,000H ; tranZPUter memory is target for file load.
|
|
LD (TZSVC_MEM_TARGET), A
|
|
|
|
LD A,TZSVC_CMD_LOADFILE
|
|
LD (TZSVCCMD), A ; Load up the command into the service record.
|
|
CALL SVC_CMD ; And make communications with the I/O processor, returning with the required record.
|
|
OR A
|
|
JR Z, SDLOADFIL2
|
|
LD HL,SVCIOERR
|
|
SDLOADFIL1: CALL PRTSTR
|
|
RET
|
|
SDLOADFIL2: LD A,(TZSVCRESULT) ; Check result, non zero will be a file error.
|
|
OR A
|
|
LD HL,SVCFILERR
|
|
JR NZ,SDLOADFIL1
|
|
;
|
|
JP NST ; Initiate a normal state restart to run the loaded program.
|
|
ENDIF
|
|
|
|
;----------------------------------------------
|
|
; Hardware Emulation Mode Activation Routines.
|
|
;----------------------------------------------
|
|
|
|
SETMZ80K: IF BUILDVERSION = 1
|
|
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
|
|
ENDIF
|
|
SETMZ80C: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ80C
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ1200: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ1200
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ80A: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ80A
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ700: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ700
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ1500: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ1500
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ800: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ800
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ80B: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ80B
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ2000: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ2000
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ2200: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ2200
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
SETMZ2500: IF BUILDVERSION = 1
|
|
LD D, TZSVC_CMD_EMU_SETMZ2500
|
|
JR SETEMUMZ
|
|
ENDIF
|
|
|
|
SETEMUMZ: IF BUILDVERSION = 1
|
|
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
|
|
SOFTCPUERR: LD HL,SVCNOCPUERR
|
|
JR EMUMZERR
|
|
SETT80ERR: LD HL,SVCT80ERR
|
|
JR EMUMZERR
|
|
NOEMUERR: LD HL,SVCNOEMUERR
|
|
EMUMZERR: CALL PRTSTR
|
|
RET
|
|
ENDIF
|
|
|
|
; Method to send a command to the I/O processor and verify it is being acted upon.
|
|
; THe method, after sending the command, polls the service structure result to see if the I/O processor has updated it. If it doesnt update the result
|
|
; then after a period of time the command is resent. After a number of retries the command aborts with error. This is needed in case of the I/O processor crashing
|
|
; we dont want the host to lock up.
|
|
;
|
|
; Inputs:
|
|
; A = Command.
|
|
; Outputs:
|
|
; A = 0 - Success, command being processed.
|
|
; A = 1 - Failure, no contact with I/O processor.
|
|
; A = 2 - Failure, no result from I/O processor, it could have crashed or SD card removed!
|
|
SVC_CMD: IF BUILDVERSION = 1
|
|
PUSH BC
|
|
LD (TZSVCCMD), A ; Load up the command into the service record.
|
|
LD A,TZSVC_STATUS_REQUEST
|
|
LD (TZSVCRESULT),A ; Set the service structure result to REQUEST, if this changes then the K64 is processing.
|
|
|
|
LD BC, TZSVCWAITIORETRIES ; Safety in case the IO request wasnt seen by the I/O processor, if we havent seen a response in the service
|
|
|
|
SVC_CMD1: PUSH BC
|
|
LD A,(TZSVCCMD)
|
|
OUT (SVCREQ),A ; Make the service request via the service request port.
|
|
|
|
LD BC,0
|
|
SVC_CMD2: LD A,(TZSVCRESULT)
|
|
CP TZSVC_STATUS_REQUEST ; I/O processor when it recognises the request sets the status to PROCESSING or gives a result, if this hasnt occurred the the K64F hasnt begun processing.
|
|
JR NZ, SVC_CMD3
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ, SVC_CMD2
|
|
POP BC
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,SVC_CMD1 ; Retry sending the I/O command.
|
|
;
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,SVCIOERR
|
|
CALL PRTSTR
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
LD A,1 ; No response, error.
|
|
RET
|
|
SVC_CMD3: POP BC
|
|
;
|
|
LD BC,TZSVCWAITCOUNT ; Number of loops to wait for a response before setting error.
|
|
SVC_CMD4: PUSH BC
|
|
LD BC,0
|
|
SVC_CMD5: LD A,(TZSVCRESULT)
|
|
CP TZSVC_STATUS_PROCESSING ; Wait until the I/O processor sets the result, again timeout in case it locks up.
|
|
JR NZ, SVC_CMD6
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,SVC_CMD5
|
|
POP BC
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JR NZ,SVC_CMD4 ; Retry polling for result.
|
|
;
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,SVCRESPERR
|
|
CALL PRTSTR
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
LD A,2
|
|
RET
|
|
SVC_CMD6: XOR A ; Success.
|
|
POP BC
|
|
POP BC
|
|
RET
|
|
ENDIF
|
|
|
|
SVCIOERR: IF BUILDVERSION = 1
|
|
DW 0D00AH
|
|
DB "I/O Error, time out!", NULL
|
|
ENDIF
|
|
SVCRESPERR: IF BUILDVERSION = 1
|
|
DW 0D00AH
|
|
DB "I/O Response Error, time out!", NULL
|
|
ENDIF
|
|
SVCFILERR: IF BUILDVERSION = 1
|
|
DW 0D00AH
|
|
DB "File not found error!", NULL
|
|
ENDIF
|
|
SVCNOCPUERR:IF BUILDVERSION = 1
|
|
DW 0D00AH
|
|
DB "No SoftCPU available in FPGA!", NULL
|
|
ENDIF
|
|
SVCT80ERR: IF BUILDVERSION = 1
|
|
DW 0D00AH
|
|
DB "Error, failed to switch to T80 CPU!", NULL
|
|
ENDIF
|
|
SVCNOEMUERR:IF BUILDVERSION = 1
|
|
DW 0D00AH
|
|
DB "No emuMZ available in FPGA!", NULL
|
|
ENDIF
|
|
|
|
; Method to perform a series of dev tests to visually or physically check CPLD/FPGA/firmware changes.
|
|
VTEST: IF BUILDVERSION = 1
|
|
LD A,0AFH ; Setup to enable FPGA video.
|
|
OUT (06EH),A
|
|
LD A,0D3H ; Page in character video ram.
|
|
OUT (PIOA),A
|
|
VTF0: LD HL,0D000H
|
|
LD A,0D8H ; Set to character VRAM top address.
|
|
VTF1: LD (HL),030H ; Load zero's
|
|
INC HL
|
|
CP H
|
|
JR NZ,VTF1
|
|
LD A,0E0H
|
|
VTF2: LD (HL),071H ; Set blue background white foreground.
|
|
INC HL
|
|
CP H
|
|
JR NZ,VTF2
|
|
LD A,031H
|
|
PUSH AF
|
|
VTF3: LD HL,0D028H
|
|
LD DE,0D000H
|
|
VTF4: LD A,(HL)
|
|
LD (DE),A
|
|
INC HL
|
|
INC DE
|
|
LD A,0D4H
|
|
CP H
|
|
JR NZ,VTF4
|
|
LD HL,0D3C0H
|
|
LD A,0D8H
|
|
EX AF,AF'
|
|
POP AF
|
|
VTF5: LD (HL),A
|
|
EX AF,AF'
|
|
INC HL
|
|
CP H
|
|
JR Z,VTF6
|
|
EX AF,AF'
|
|
JR VTF5
|
|
VTF6: EX AF,AF'
|
|
INC A
|
|
PUSH AF
|
|
LD HL,0D000H
|
|
LD A,(HL)
|
|
LD C,A
|
|
VTF7: LD A,(HL)
|
|
CP C
|
|
JR NZ,VTFER
|
|
INC HL
|
|
;LD A,H
|
|
;CP 0D3H
|
|
;JR NZ,VTF7
|
|
LD A,L
|
|
CP 027H
|
|
JR NZ,VTF7
|
|
POP AF
|
|
OR A
|
|
JR Z,VTF8
|
|
PUSH AF
|
|
JR VTF3
|
|
VTF8: LD C,0
|
|
VTF9: LD HL,0D000H
|
|
LD A,0D4H
|
|
VTF10: LD (HL),C
|
|
INC HL
|
|
CP H
|
|
JR NZ,VTF10
|
|
VTF11: LD HL,0D000H
|
|
VTF12: LD A,(HL)
|
|
CP C
|
|
JR NZ,VTFER
|
|
INC HL
|
|
LD A,H
|
|
CP 0D4H
|
|
JR NZ,VTF12
|
|
INC C
|
|
JR VTF9
|
|
|
|
VTFER: JP GETCHOICE
|
|
ENDIF
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; END OF SERVICE COMMAND METHODS
|
|
;-------------------------------------------------------------------------------
|
|
|
|
; Align to rom size.
|
|
IF BUILDVERSION = 1
|
|
; TranZPUter virtual rom can be any size upto 64K, currently = 4K.
|
|
DS 01000H - 1 - ($ + 01000H - 1) % 01000H, 0FFh
|
|
ELSE
|
|
; Original ROM is 2K in size.
|
|
DS 0800H - 1 - ($ + 0800H - 1) % 0800H, 0FFh
|
|
ENDIF
|
|
|
|
; Configuration for TZFS service structure memory allocation.
|
|
TZSVCMEM: EQU 07D80H ; Start of a memory structure used to communicate with the K64F I/O processor for services such as disk access.
|
|
|
|
; Bring in the TZFS definitions and service structure definition,
|
|
INCLUDE "tzfs_definitions.asm"
|
|
INCLUDE "tzfs_svcstruct.asm"
|
|
|