;modified version for rtype deluxe dev
;
;
;
; FDC Code reading AMSDOS file
; Without system.
; V1.0
;
; By Targhan/Arkos
;
; AMSDOS limitations still present.
; 9 2-sized sectors per track (c1-c9), one side.
; However, can read sectors up to 41 tracks
; (used by files copied with Disc'o'Magic, for example).
;
; Can't read ASCII files (who cares ?)
;
;
; Filename entered follow the format =
; AAAAAAAABBB
; Use upper case only. Do not put the '.'.
;
;
;
; Proper use =
; call FDCON to turn the drive ON
;
; ld a,drive (0-3)
; ld b,head (0-1)
; call FDCVARS to tell which drive to use, head to read.
;
; ld hl,FILENAME
; ld de,destination
; ld bc,buffer read below about it.
; call LOADFILE to load the file.
; Return =
; A=state. 0=ok  1=disc missing  2=read fail
; 3=file not found
;
; When you've loaded all the files you wanted =
; call FDCOFF
;
; You shouldn't need it, but...
; call RECALIBR
; to recalibrate the current drive (use FDCON
; and FDCVARS first !). AMSDOS does it when you turn
; the CPC on. You can also do it when an error disc
; happened, before trying loading the file again.
;
; That's it !
;
;
; Notes
; - The 'buffer' of LOADFILE CAN be equal to DE. It is used
;   to load one sector of the Directory. In the case you want
;   to load a screen in #c000, you might want to set BC to
;   another address, so that you don't see garbage at the
;   beginning of the loading.
; - By changing the Head, you can read the file on the second
;    side of a 3"5 disc.
; - Automatically skips the AMSDOS header.
; - Even if the file is not found, 512 bytes will be use
; from the 'destination' address.
; - The User of a file is ignored (who cares ?), except for deleted files.
; - No buffer is needed.
; - The interruptions are CUT by the loading code.
; - Interruptions are turned on when turning on the FDC, so
;   put #c9fb in #38 before if you don't want your
;   interruptions code to be run at this moment.
; - Some little tables are defined at the end. You can relocate
;   them where you want if needed.
;
;
;
;Maximum number of direction entry of a file. *16 to get the maximum size
;loadable in KB. 4 should be more than enough (=64k).
NBMAXENT equ 4
;
;Track where the directory is. Some AMSDOS tweakings allow to use another one.
DIRTRACK equ 0
;
;First sector of the directory.
DIRFSECT equ #c1
;
;
;
;

current_head	db 0
current_drive	db 0

Quick_load:
	push HL
	push DE

	ld A,(current_head)
	ld B,A
	ld A,(current_drive)
	call FDCVARS

	pop DE
	pop HL

	push HL
	push DE

	ld C,E
	ld B,D

	call LOADFILE

	pop DE
	pop HL

	;nc = error
	;ret c
	;A = 0 no error
	or A
	ret z

	;error
	call RECALIBR
	jr Quick_load

;----------------------------
;
;
;
;
;Tell which drive to use, head to read.
;A=drive (0-3)
;B=head (0-1)
FDCVARS
 ld (FDCDRIVE),a
 ld c,a
 ld a,b
 ld (FDCHEAD),a
 rla
 rla
 and %100
 or c
 ld (FDCIDDR),a
 ret
;
;
;
;
;Turn FDC on and wait a bit.
FDCON    LD   A,(FDCMOTOR)
         OR   A
         RET  NZ
         INC  A
         LD   (FDCMOTOR),A
         LD   BC,#FA7E
         LD   A,1
         OUT  (C),A
;Wait for motor to get full speed
         LD   B,50 ;2 sec
;WAIT     HALT 
;         DJNZ WAIT
;         DI   
.wait
	push BC
	ld B,#F5

.wait_loop
	in A,(C)
	rra
	jr nc,wait_loop

.wait_counter_loop
	in A,(C)
	rra
	jr c,wait_counter_loop

	pop BC
	djnz wait
	
        RET  
;
;
;
;
;Turn FDC off.
FDCOFF   XOR  A
         LD   (FDCMOTOR),A
         LD   BC,#FA7E
         XOR  A
         OUT  (C),A
         RET  
;
;
;
;Recalibrate current drive.
RECALIBR
 call RECALIB2
 call RECALIB2
 ret
RECALIB2
         LD   A,%00000111
         CALL PUTFDC
  ld a,(FDCIDDR)
         CALL PUTFDC
         CALL WAITEND
         RET  
;
;
;
;
;
;Load a file
;HL=Filename
;DE=Where to load it
;BC=#200 buffer
;RET=A=state. 0=ok  1=disc missing  2=read fail
;3=file not found
LOADFILE
 ld (PTFILENM),hl
 LD (LOADWHER),DE
 ld (ADBUFFER),bc
;
;
        CALL BUILDTAB
 ret nc
;
 ld a,128
 ld (SKIPBYTE+1),a
;
;
;Reading the file
 LD IX,TABSECTS
LOADLP LD A,(IX+0)
 cp #ff
 jr z,LOADFOK
 cp #fe
 jr z,LOADNEXT
 LD B,(IX+1)
 push ix
 CALL READSECT
 pop ix
 ret nc
 ld (LOADWHER),hl
;
 ld hl,(TOREAD)
 ld a,l
 or h
 jr z,LOADFOK
;
 xor a
 ld (SKIPBYTE+1),a
;
LOADNEXT inc ix
  inc ix
 jr LOADLP
;
LOADFOK xor a
 scf
 ret
;
;
;
;
;
;
;
;
;
;Wait for the end of the current instruction (using ST0).
WAITEND
         LD   A,%00001000
         CALL PUTFDC
         CALL GETFDC                    ;Get ST0
         LD   (ST0),A
         CALL GETFDC
         XOR  A
         LD   (ST1),A                   ;Reset ST1 and ST2
         LD   (ST2),A
;
         LD   A,(ST0)
         BIT  5,A                       ;Instruction over ?
         JR   Z,WAITEND
         RET  
;
;Send data to FDC
;A=data
PUTFDC
        ex af,af'
 LD   BC,#FB7E
PUTFD2 IN   A,(C)
        JP   P,PUTFD2
        ex af,af'
 inc c
 OUT  (C),A
        RET  
;
;Get data from FDC
;Ret = A=FDC data
GETFDC
 LD   BC,#FB7E
GETFD2 IN   A,(C)
 JP   P,GETFD2
 inc c
        IN   A,(C)
        RET  
;
;
;Track change
;a=nb piste
GOTOPIST
         PUSH AF
         LD   A,%00001111
         CALL PUTFDC
         LD   A,(FDCIDDR)
         CALL PUTFDC
         POP  AF
         CALL PUTFDC
;
         CALL WAITEND
;
         RET  
;
;
;Read sector.
;A=track
;B=ID sector
;RET=A=state.Carry=1=ok A=0=ok  1=disc missing  2=read fail
;3=file not found
;HL=Where new data should be loaded (LOADWHER)
READSECT
         LD   (RSPIST+1),A
         PUSH BC
         CALL GOTOPIST
;
         LD   A,%01000110
         CALL PUTFDC
         LD   A,(FDCIDDR)               ;ID drive
         CALL PUTFDC
RSPIST   LD   A,0                       ;track
         CALL PUTFDC
         XOR  A               ;head
         CALL PUTFDC
         POP  BC                        ;ID sect
         LD   A,B
         PUSH AF
         CALL PUTFDC
         LD   A,2                       ;size
         CALL PUTFDC
         POP  AF                        ;last sect to read
         CALL PUTFDC
         LD   A,#52                     ;GAP
         CALL PUTFDC
         LD   A,#FF
         CALL PUTFDC
;
         LD   BC,#FB7E
;
SKIPBYTE ld a,0   ;If header, skip it
 or a
 jr z,RSAVLOOP
 ld e,a
;
 ld hl,BUFHEAD
;Read bytes to the header buffer.
RSSKIPLP
 IN   A,(C)                     ;FDC ready for transf ?
 JP   P,RSSKIPLP
 AND  %00100000   ;FDC performing ?
 JR   Z,RSFIN
;
 INC C
 IN A,(C)
 ld (hl),a
 inc hl
 DEC  C
 dec e
        jr nz,RSSKIPLP
;
 ld hl,(BUFHEAD+64)  ;get filesize
 ld (TOREAD),hl
;
;Normal reading code.
RSAVLOOP
 LD HL,(LOADWHER)
 ld de,(TOREAD)
RSLOOP
        IN   A,(C)                     ;FDC ready for transf ?
        JP   P,RSLOOP
        AND  %00100000    ;FDC performing ?
        JR   Z,RSFIN
;
        INC  C
        IN   A,(C)
        LD   (HL),A
        INC  HL
;
        DEC  C
 dec de
 ld a,e
 or d
        JR nz,RSLOOP
;
;Reading with saving. Done if end of file but sectors left.
RSWASTE
        IN   A,(C)                     ;FDC ready for transf ?
 JP   P,RSWASTE
        AND  %00100000    ;FDC performing ?
        JR   Z,RSFIN
;
        INC  C
        IN   A,(C)
        DEC  C
        JR RSWASTE
;
;Reading instr result
RSFIN
 ld (TOREAD),de
;
        CALL GETFDC
        LD   (ST0),A
        CALL GETFDC
        LD   (ST1),A
        CALL GETFDC
        LD   (ST2),A
        CALL GETFDC
        CALL GETFDC
        CALL GETFDC
        CALL GETFDC
;
;
;Test errors.
;ret= Carry=1=ok a=0=ok  a=1=disc missing  2=read fail
;ute ST0, ST1, ST2
         LD   A,(ST0)
         BIT  7,A
         JR   NZ,TESTEJEC               ;no disc
         BIT  3,A
         JR   NZ,TESTEJEC               ;no disc
         BIT  4,A
         JR   NZ,TESTFAIL               ;Read fail
;
         LD   A,(ST1)
         AND  %00110111
         JR   NZ,TESTFAIL
;
         LD   A,(ST2)
         AND  %00110000
         JR   NZ,TESTFAIL
;
TESTNOE
 XOR  A
 scf
 ret
TESTEJEC
 LD A,1
 or a
 ret
TESTFAIL
 LD A,2
 or a
 ret
ERRFNF
 LD A,3
 or a
 ret
;
;
;
;
;
;
;Search a file in the AMSDOS directory, and
;build the sector table.
;RET=A=state. 0=ok  1=disc missing  2=read fail
;3=file not found
.BUILDTAB
 ld a,DIRFSECT
 ld (BTSECT+1),a
 add a,4
 ld (BTESECT+1),a
 xor a
 ld (FILFOUND),a
 ld (SKIPBYTE+1),a
;
 ld hl,#ffff
 ld (TOREAD),hl
;
;
 ld hl,TABSECTS
 ld de,TABSECTS+1
 ld bc,TABSECTF-TABSECTS-1
 ld (hl),#fe
 ldir
;
;
BTLOOP ld a,DIRTRACK
BTSECT ld b,#c1
 call READSECT
 ret nc
;
 ld hl,(ADBUFFER)
 ld (BTBUFF+1),hl
;
;Search in the loaded sector the right entry(ies)
 ld b,16
BTENTLP push bc
 LD HL,(PTFILENM)
BTBUFF ld de,0
 ld a,(de)
 cp #e5   ;ignore deleted files
 jr z,BTNEXT
 inc de
        CALL CMP
        call C,BTFOUND
;
BTNEXT ld hl,(BTBUFF+1)
 ld de,32
 add hl,de
 ld (BTBUFF+1),hl
;
 pop bc
 djnz BTENTLP
;Next sector
 ld a,(BTSECT+1)
 inc a
 ld (BTSECT+1),a
BTESECT cp #c5
 jr nz,BTLOOP
;
 ld a,(FILFOUND)
 or a
 jr z,BTNOFND
 xor a
 scf
 ret
;
BTNOFND ld a,3  ;File not found
 ret
;
;
;
;Right entry found.
BTFOUND
 ld a,1
 ld (FILFOUND),a
;
 ld ix,(BTBUFF+1)
 ld a,(ix+12)   ;Get block number
 ld l,a    ;Calcule where to code the track+sect
 ld h,0    ;in the tabsects
 add hl,hl
 add hl,hl
 add hl,hl
 add hl,hl
 add hl,hl
 add hl,hl
 ld de,TABSECTS
 add hl,de
 ex de,hl
 defb #fd : ld l,e
 defb #fd : ld h,d
;
 ld de,16
 add ix,de
;
;ix=source
;iy=dest
 call CONV
;
 ret
;
;
;
;
;
;Compare two strings. 7th bit to 0.
;DE=     buffer   HL=filename
;RET=    Carry=OK
CMP
         LD   B,11
;
CM2      LD   A,(DE)
         RES  7,A
         CP   (HL)
         JR   NZ,CMPNOT
         INC  HL
         INC  DE
         DJNZ CM2
         SCF
         RET  
CMPNOT   OR A
         RET  
;
;
;Convert block table to table of tracks+sects
;IX=src  IY=dest
CONV
 ld b,16   ;Reading 16 blocks max
CVNEXT ld a,(ix+0)  ;read block number
 or a
 ret z
 inc ix
;
 push bc
;
         LD   L,A
         LD   H,0
         ADD  HL,HL
         CALL DIV9
         LD   (iy+0),c  ;get track
;
;  sect1
;
         LD   HL,(RESTE)
         LD   A,L
         add a,DIRFSECT
         LD   (iy+1),A
;
; sect2
;
         INC  A
         CP   #CA
         JR   NZ,CVP2
         LD   A,#C1
         INC  C
CVP2     LD   (iy+2),C
         LD   (iy+3),A
 ld de,4
 add iy,de
;
 pop bc
 djnz CVNEXT
 ret
;
;
;
DIV9     LD   DE,9  ;Not optimised. Who cares ?
         LD   C,0
DIV91    OR   A
         SBC  HL,DE
         JR   C,DIV92
         INC  C
         JR   DIV91
DIV92    ADD  HL,DE
         LD   (RESTE),HL
         RET  
;
;
FDCMOTOR defb 0   ;Drive motor (0-1)
FDCDRIVE defb 0   ;Drive used (0-3)
FDCHEAD defb 0   ;Head used (0-1)
FDCIDDR defb 0   ;Drive ID.
ST0 DEFB 0
ST1 DEFB 0
ST2 defb 0
FILFOUND defb 0
RESTE    DEFW 0
;
LOADWHER defw 0  ;Where to load the file
ADBUFFER defw 0  ;#200 buffer
PTFILENM defw 0  ;Point on the filename
TOREAD defw 0  ;Size (decrease)
;
;
;Table where is build the sector table.
;One directory entry can contain 16 blocks, hence '16'
;One block=2 sectors, each one defined by a track+sect ID. Hence the '*4'.
TABSECTS DEFS 16*4*NBMAXENT,#fe
TABSECTF DEFW #FFFF
;
BUFHEAD defs 128,0   ;Header put here
;
;*** End FDC code



             
