Files
RFS/asm/mz-1e05.asm
2026-01-07 09:17:16 +00:00

535 lines
16 KiB
NASM

; V1.10
;
; To compile use:
;
; AS80 [1.31] - Assembler for 8080/8085/Z80 microprocessor.
;
; Available from:
; - http://www.falstaff.demon.co.uk/cross.html
; - ftp://ftp.simtel.net/pub/simtelnet/msdos/crossasm/as80_131.zip
; - and many Simtel mirrors.
;
; as80 -i -l -n -x2 -v -z mz-1e05.asm
; Bring in additional resources.
INCLUDE "rfs_definitions.asm"
INCLUDE "macros.asm"
;
;----< MFM Minifloppy control >----
;
;
; Call condition
;
; Case of disk initialize
; Drive N = IX+0 (0 - 3)
;
;
; Case of sequential read & write
; Drive N = IX+0 (0 - 3)
;
; Sector addrs = IX+1,2 (0 - $045F) H C S
; (0 - 1119) -> 70 x 16 sectors -> 2 x 35 x 16
; Byte size = IX+3,4
; Address = IX+5,6
; Next track = IX+7
; Next sector = IX+8
; Start track = IX+9
; Start sector = IX+10
;
;
; I/O Port address
;
;
; Subroutine work
;
BPRO EQU 0CF00H
BUF EQU 011A3H
BPARA EQU BPRO - 23 ; BootPARAmeter
CMD EQU BPARA + 11 ; CoMmanD
MTFG EQU CMD + 1 ; MoTorFlaG
CLBF0 EQU MTFG + 1
CLBF1 EQU CLBF0 + 1
CLBF2 EQU CLBF1 + 1
CLBF3 EQU CLBF2 + 1
VRFCNT EQU CLBF3 + 1 ; VeRiFyCouNT
STAFG EQU VRFCNT + 1 ; STAtusFlaG
;
;
;--------< Ercode map >--------
;
; 50 : Not ready
; 41 : Data error
; Track 80 err
; Write protect err
; Seek err
; CRC err
; Lost data
; 54 : Unformat
; Recode not found
; 56 : Invalid data
;
;
ORG 0F000H
MZ_1E05: NOP
LD HL,000ADH
JR L_F007
FDX: EX (SP),HL
L_F007: LD (BPARA + 21),HL
XOR A
LD DE,0
CALL ?TMST
CALL FDCC ; FD i/o check
JP NZ,NOTIO
LD DE,BPARA ; destination address
LD HL,BOOT ; source address
LD BC,11 ; 11 bytes
LDIR ; copy
SJP: LD IX,BPARA
CALL BREAD ; read from drive 0, sector 0,
;
LD HL,BPRO ; compare this address
LD DE,IPLMC ; with the IPL MasterCode
LD B,7 ; this are 7 bytes : 3,'IPLPRO'
MCHECK: LD C,(HL)
LD A,(DE)
CP C
JP NZ,MASTE ; not equal than MasterError
INC HL
INC DE
DJNZ MCHECK
; else Master was found
LD DE,IPLM0 ; 'IPL IS LOADING'
RST 018H
LD DE,BPRO + 7 ; NAME
RST 018H
LD HL,(BPRO + 016H) ; TARGETADDRESS from BootBlock
LD A,H
OR L
JR NZ,L_F051 ; if it is != 0 than normal file
LD HL,(BPRO + 018H) ; TARGETADDRESS from BootBlock
LD A,H
OR L
JR Z,L_F057 ; if it is also 0 than ROM replace file
L_F051: XOR A ; else normal file,
LD HL,(BPRO + 018H) ; TARGETADDRESS from BootBlock
JR L_F05C
L_F057: LD A,0FFH ; target is at $0000, bankswitching is needed
LD HL,01200H ; for now use temporary buffer at $1200
L_F05C: LD (0CEFDH),A
LD (IX + 5),L ; set the TargetAddress
LD (IX + 6),H
LD HL,(BPRO + 014H) ; BYTE SIZE from BootBlock
LD (IX + 3),L
LD (IX + 4),H
LD HL,(BPRO + 01EH) ; START SECTOR from BootBlock
LD (IX + 1),L
LD (IX + 2),H
;
CALL BREAD
CALL MOFF
LD A,(0CEFDH)
CP 0FFH
JR NZ,L_F093
OUT (0E0H),A
LD HL,01200H ; SourceAddress
LD DE,(BPRO + 016H) ; TargetAddress
LD BC,(BPRO + 014H) ; ByteCounter
LDIR ; copy
L_F093: LD BC,00200H ; Default code
LD HL,(BPRO + 018H) ; TARGET/EXECUTION ADDRESS from BootBlock
JP (HL)
MASTE: CALL MOFF
LD DE,ERRM1 ; 'NOT MASTER'
JR ERRTR1
ERRTRT: CP 50
NOTIO: LD DE,IPLM3 ; 'MAKE READY FD'
JR Z,ERRTR1
LD DE,ERRM0 ; 'FD:LOADING ERROR'
ERRTR1: CALL 00009H
RST 018H
LD SP,010EEH
LD HL,(BPARA + 21)
EX (SP),HL
RET
;
;
; PARAMETER SETTING
;
IPLMC: DB 003H ; IPL MASTER FLAG
DB "IPLPRO"
BOOT: DB 000H ; DRIVE NO.
DW 00000H ; SECTOR ADDR.
DW 00100H ; IFM BYTE SIZE
DW BPRO ; IFM LOADING ADDR.
DW 00000H ; IX+7,8 (track 0, sector 0)
ERRM1: DB "FD:NOT MASTER",00DH
IPLM0: DB "IPL IS LOADING ",00DH
IPLM3: DB "MAKE READY FD",00DH
ERRM0: DB "FD:LOADING ERROR",00DH
FDCC: LD A,0A5H
LD B,A
OUT (FDC_TRACK),A
CALL DLY80U
IN A,(FDC_TRACK)
CP B
RET
L_F111: DB 000H, 000H
;
;
; READY CHECK
;
READY: LD A,(MTFG)
RRCA
CALL NC,MTON
LD A,(IX + 0) ; DRIVE NO SET
OR 084H
OUT (FDC_DRIVE),A ; DRIVE SELECT MOTON
XOR A
LD (CMD),A
CALL DLY60M
LD HL,0
REDY0: DEC HL
LD A,H
OR L
JR Z,REDY1
IN A,(FDC_CMD) ; STATUS GET
CPL
RLCA
JR C,REDY0
LD C,(IX + 0)
LD HL,CLBF0
LD B,000H
ADD HL,BC
BIT 0,(HL)
JR NZ,REDY2
CALL RCLB
SET 0,(HL)
REDY2: RET
REDY1: LD A,032H
JP ERJMP
;
;
; MOTOR ON
;
MTON: LD A,080H
OUT (FDC_DRIVE),A
LD B,16
MTD1: CALL DLY60M
DJNZ MTD1
LD A,1
LD (MTFG),A
RET
;
;
; SEEK TREATMENT
;
SEEK: LD A,01BH ; 1x = SEEK,
CALL CMDOT1 ; load head, no verify, max stepping rate
AND 099H
RET
;
;
; MOTOR OFF
;
MOFF: PUSH AF
CALL DLY1M ; 1000 US DELAY
XOR A
OUT (FDC_DRIVE),A
LD (CLBF0),A
LD (CLBF1),A
LD (CLBF2),A
LD (CLBF3),A
LD (MTFG),A
POP AF
RET
;
;
; RECALIBRATION
;
RCLB: LD A,00BH ; 0x = RESTORE (seek track 0)
CALL CMDOT1 ; load head, no verify, max stepping rate
AND 085H
XOR 004H
RET Z
L_F189: JP ERRORX
;
;
; COMMAND OUT ROUTINE
;
CMDOT1: LD (CMD),A
CPL
OUT (FDC_CMD),A
CALL BSYON
CALL DLY60M
IN A,(FDC_CMD)
CPL
LD (STAFG),A
RET
;
;
; BUSY AND WAIT
;
BSYON: PUSH DE
PUSH HL
CALL BSY0
BSYON2: LD HL,00000H
BSYON0: DEC HL
LD A,H
OR L
JR Z,BSYON1
IN A,(FDC_CMD)
RRCA
JR NC,BSYON0
POP HL
POP DE
RET
;
BSYON1: DEC E
JR NZ,BSYON2
BSYONE: LD A,029H
POP HL
POP DE
JP ERJMP
;
BSYOFF: PUSH DE
PUSH HL
CALL BSY0
BSYOF2: LD HL,00000H
BSYOF0: DEC HL
LD A,H
OR L
JR Z,BSYOF1
IN A,(FDC_CMD) ; Status Register
RRCA
JR C,BSYOF0
POP HL
POP DE
RET
;
BSYOF1: DEC E
JR NZ,BSYOF2
JR BSYONE
;
BSY0: CALL DLY80U
LD E,007H
RET
;
;
; SEQUENTIAL READ
;
BREAD: CALL CNVRT
CALL PARST1 ; HL = IX + 5,6 (TargetAddress)
RE8: CALL SIDST
CALL SEEK
JP NZ,ERJMP
CALL PARST2 ; C = DataRegister
DI ; disable interrupts
LD A,094H ; 9x = READ SECTOR, multiple records
CALL CMDOT2 ; compare for side 0, 15ms delay,
RE6: ; disable side select compare
LD B,0 ; ByteCounter = 0, to load 256 bytes of the sector
RE4: IN A,(FDC_CMD)
RRCA
JR C,RE3
RRCA
JR C,RE4
INI ; (HL) = in(C), B = B - 1 , HL = HL + 1
JR NZ,RE4
INC (IX + 8) ; NextSector = NextSector + 1
LD A,(IX + 8)
CP 011H ; if NextSector = 17
JR Z,L_F213 ; than end
DEC D ; else SectorCounter = SectorCounter - 1
JR NZ,RE6 ; if SectorCounter = 0
JR L_F214 ; than end
L_F213: DEC D
L_F214: CALL INTER
RE3: EI ; enable interrupts
IN A,(FDC_CMD)
CPL
LD (STAFG),A
AND 0FFH
JR NZ,ERRORX
CALL ADJ ; adjust sector and track
JP Z,REND
LD A,(IX + 7) ; track
JR RE8
REND: LD A,080H
OUT (FDC_DRIVE),A ; motor on
RET
;
;
; PARAMETER SET
;
;
PARST1: CALL READY
LD D,(IX + 4) ; D = bytes to read (highbyte) (256 bytes)
LD A,(IX + 3) ; A = bytes to read (lowbyte)
OR A ; if A = 0
JR Z,L_F23F ; than it's ok
INC D ; else read 256 bytes more (1 sector)
L_F23F: LD A,(IX + 10) ; NextSector = StartSector
LD (IX + 8),A
LD A,(IX + 9) ; NextTrack = StartTrack
LD (IX + 7),A
LD L,(IX + 5) ; HL = TargetAddress
LD H,(IX + 6)
RET
;
;
; SIZE SEEK SET
;
SIDST: SRL A
CPL
OUT (FDC_DATA),A
JR NC,L_F25D ; NC than Head 0
LD A,1 ; else Head 1
JR L_F25E
L_F25D: XOR A
L_F25E: CPL
OUT (FDC_SIDE),A ; set HeadSelect
RET
;
;
; TRACK & SECTOR SET
;
PARST2: LD C,FDC_DATA
LD A,(IX + 7) ; A = NextTrack
SRL A
CPL
OUT (FDC_TRACK),A
LD A,(IX + 8) ; A = NextSector
CPL
OUT (FDC_SECTOR),A
RET
;
;
; ADJUST SECT & TRACK
;
ADJ: LD A,(IX + 8) ; A = NextSector
CP 17 ; if NextSector = 17
JR NZ,L_F282 ; than the border is not reached
LD A,001H ; else
LD (IX + 8),A ; NextSector = 1
INC (IX + 7) ; NextTrack = NextTrack + 1
L_F282: LD A,D
OR A
RET
;
;
; COMMAND OUT & WAIT
;
CMDOT2: LD (CMD),A
CPL
OUT (FDC_CMD),A
CALL BSYOFF
RET
;
;
; FORCE INTERRUPT
;
INTER: LD A,0D8H
CPL
OUT (FDC_CMD),A
CALL BSYON
RET
;
;
; STATUS CHECK
;
ERRORX: LD A,(CMD)
CP 00BH ; Restore (seek track 0)
JR Z,ERCK1
CP 01BH ; Seek
JR Z,ERCK1
CP 0F4H ; Write track
JR Z,ERCK1
LD A,(STAFG)
BIT 7,A
JR NZ,ERRET
BIT 6,A
JR NZ,ERRET1
BIT 4,A
LD A,54
JR NZ,ERJMP
JR ERRET1
ERCK1: LD A,(STAFG)
BIT 7,A
JR NZ,ERRET
ERRET1: LD A,41
JR ERJMP
ERRET: LD A,50
ERJMP: CALL MOFF
JP ERRTRT
;
;
; SECTOR TO TRACK & SECTOR CONVERT
;
CNVRT: LD B,0 ; TrackCounter = 0
LD DE,16 ; 16 sectors per track
LD L,(IX + 1) ; HL = SectorAddress
LD H,(IX + 2)
XOR A
TRANS0: SBC HL,DE ; SectorAddress - SectorPerTrack
JR C,TRANS1 ; if < 0 than ready
INC B ; else TrackCounter = TrackCounter + 1
JR TRANS0 ; next try
TRANS1: ADD HL,DE ; undo the last substraction
LD H,B
INC L ; adjust sector (sector is 1..16 and not 0..15)
LD (IX + 9),H ; set StartTrack
LD (IX + 10),L ; set StartSector
RET
;
;
; TIME DELAY ( 1m & 60m & 80u )
;
DLY80U: PUSH DE
LD DE,15
JP DLYT
DLY1M: PUSH DE
LD DE,160
JP DLYT
DLY60M: PUSH DE
LD DE,8230
DLYT: DEC DE
LD A,E
OR D
JR NZ,DLYT
POP DE
RET
ALIGN 0FFF0H
ORG 0FFF0H
DB " 84.03.14 V1.0A"