📄 fs.asm
字号:
; Hard disk filesystem
; Chris Ward, 21/1/2000
;partition table filesystem codes
FS_HDFS EQU 01
HDFSVER EQU 01 ;filesystem version
MAGPART fcs "CNWPART" ;magic word for partition table
MAGHDFS fcs "CNWHDFS" ;magic word for file system
; *** FSINIT: Initialise filesystem
FSINIT LDY #7 ;fill logical drive table with 00 (no drive)
LDA #$00
FSINIT0 STA DRIVES,Y
DEY
BPL FSINIT0
LDA #0 ;set up to read partition table (sector 0)
STA IDELBA0
STA IDELBA1
STA IDELBA2
STA IDELBA3
LDA #IDEBUF0
STA IDEBUFP
LDA #IDEBUF0/256
STA IDEBUFP+1
JSR IDERSEC ;read sector into buffer
LDX #6 ;check for 7-letter magic word
FSINIT1 LDA IDEBUF0,X
CMP MAGPART,X
BNE FSINIT5 ;fail
DEX
BPL FSINIT1 ;check next letter
LDX #16 ;offset of first partition entry
LDA #1 ;count partition number
STA ZTMP1
LDY #0 ;count logical drive number
FSINIT2 LDA IDEBUF0,X ;get filesystem type
BEQ FSINIT3 ;00 = no partition
CMP FS_HDFS ;check for HDFS
BNE FSINIT3
LDA ZTMP1
STA DRIVES,Y ;store drive code
JSR HDFSINIT ;initialise HDFS on this partition
INY
FSINIT3 INC ZTMP1 ;increment partition number
LDA ZTMP1
CMP #7 ;max 7 partitions
BEQ FSINIT5
TXA
CLC
ADC #16 ;move to next partition entry
TAX
JMP FSINIT2
FSINIT5
RTS
; *** HDFSINIT: Initialise HDFS filesystem on a given partition
; (called from FSINIT)
; X=offset of partition entry in IDEBUF0
; Y=logical drive number
HDFSINIT STX ZTMP2 ;save X and Y
STY ZTMP3
TYA
ASL ;offset in drive table = drive number * 16
ASL
ASL
ASL
STA ZTMP4 ;save for later
TAY ;use Y to index drive table
LDX ZTMP2 ;use X to index IDE buffer
LDA #15 ;will copy 16 bytes
STA ZTMP5 ;use ZTMP5 as loop counter
HDFSINI0 LDA IDEBUF0,X
STA DRIVETAB,Y
INX
INY
DEC ZTMP5
BPL HDFSINI0
LDY ZTMP4 ;offset in drive table
INY ;skip first two bytes
INY
LDA DRIVETAB,Y ;get LBA start sector of partition
STA IDELBA0
INY
LDA DRIVETAB,Y
STA IDELBA1
INY
LDA DRIVETAB,Y
STA IDELBA2
INY
LDA DRIVETAB,Y
STA IDELBA3
LDA #IDEBUF1
STA IDEBUFP
LDA #IDEBUF1/256
STA IDEBUFP+1
JSR IDERSEC ;read first sector of partition
LDA ZTMP4
CLC
ADC #15 ;index of last byte of drive table entry
TAY
LDX #6 ;check for 7-letter magic word
HDFSINI1 LDA IDEBUF1,X
CMP MAGHDFS,X
BNE HDFSINI2 ;fail
DEX
BPL HDFSINI1 ;check next letter
LDA #1 ;set flag to indicate test passed
JMP HDFSINI3
HDFSINI2 LDA #0 ;test failed - partition unformatted
HDFSINI3 STA DRIVETAB,Y
LDX ZTMP2 ;restore X and Y
LDY ZTMP3
RTS
; *** GETSAT: Look up a sector in the Sector Allocation Table
; input: DRIVE = logical drive number
; ZTMP0-ZTMP3 = sector number relative to partition (not preserved)
; output: A = 0 : sector free
; A = +ve : sector allocated
; A = -ve : error
; (A is set just before RTS, so flags can be tested on return)
; X,Y preserved
GETSAT TXA
PHA
TYA
PHA
LDY DRIVE
LDA DRIVES,Y ;get device code from drive table
BEQ GETSAT_E ;drive code = 0, no drive
CMP #8
BMI GETSAT_E ;drive code > 7, invalid
TYA
ASL ;offset in drive table = drive number * 16
ASL
ASL
ASL
TAY
LDA DRIVETAB,Y
CMP FS_HDFS
BNE GETSAT_E ;filesystem is not HDFS
JSR RDSAT ;calculate position in SAT and read the SAT sector
;ZTMP0-ZTMP3 = SAT sector number (LBA)
;ZTMP8-ZTMP9 = byte within sector (0-512)
;ZTMP10 = bit within byte (0-7)
;SAT sector has been read into IDEBUF0 (pointed to by IDEBUFP)
LDY ZTMP10
LDA POW2,Y ;convert bit-number to bit-mask
STA ZTMP10
LDA ZTMP9 ;test high-byte of byte-number...
BEQ GETSAT1
INC IDEBUFP+1 ;...if 1, advance to second page of buffer
GETSAT1 LDY ZTMP8
LDA (IDEBUFP),Y ;read relavent byte from SAT
AND ZTMP10 ;select relavent bit
BEQ GETSAT_F ;bit = 0 : sector free
JMP GETSAT_A ;bit = 1 : sector allocated
GETSAT_F PLA
TAY
PLA
TAX
LDA #0
RTS
GETSAT_A PLA
TAY
PLA
TAX
LDA #1
RTS
GETSAT_E PLA
TAY
PLA
TAX
LDA #$FF
RTS
; *** SETSAT: Set the status of a sector in the Sector Allocation Table
; input: DRIVE = logical drive number
; ZTMP0-ZTMP3 = sector number relative to partition (not preserved)
; A = 0 : mark sector free
; A != 0 : mark sector allocated
; output: A = -ve : error
; (A is set just before RTS, so flags can be tested on return)
; X,Y preserved
SETSAT STA ZTMP11 ;save A for later
TXA
PHA
TYA
PHA
LDY DRIVE
LDA DRIVES,Y ;get device code from drive table
BEQ SETSAT_E ;drive code = 0, no drive
CMP #8
BMI SETSAT_E ;drive code > 7, invalid
TYA
ASL ;offset in drive table = drive number * 16
ASL
ASL
ASL
TAY
LDA DRIVETAB,Y
CMP FS_HDFS
BNE SETSAT_E ;filesystem is not HDFS
JSR RDSAT ;calculate position in SAT and read the SAT sector
;ZTMP0-ZTMP3 = SAT sector number (LBA)
;ZTMP8-ZTMP9 = byte (0-512)
;ZTMP10 = bit (0-7)
;SAT sector has been read into IDEBUF0 (pointed to by IDEBUFP)
LDA ZTMP9 ;test high-byte of byte-number...
BEQ SETSAT1
INC IDEBUFP+1 ;...if 1, advance to second page of buffer
SETSAT1 LDX ZTMP10
LDA POW2,X ;convert bit-number to bit-value
STA ZTMP10
LDY ZTMP8 ;load Y with low-byte of buffer offset
LDX ZTMP11 ;read the set/clear argument
BEQ SETSAT2
;argument != 0 : set bit
LDA (IDEBUFP),Y ;read relavent byte from SAT
ORA ZTMP10 ;set the bit
STA (IDEBUFP),Y
JMP SETSAT3
;argument = 0 : clear bit
SETSAT2 LDA #$FF
EOR ZTMP10 ;invert bit pattern
LDA (IDEBUFP),Y ;read relavent byte from SAT
AND ZTMP10 ;AND with inverted bit pattern to clear bit
STA (IDEBUFP),Y
SETSAT3 LDA ZTMP9
BEQ SETSAT4
DEC IDEBUFP+1 ;restore pointer if we changed it earlier
SETSAT4 LDA ZTMP0 ;load LBA address (can't use old value because it
STA IDELBA0 ;may have been converted to CHS)
LDA ZTMP1
STA IDELBA1
LDA ZTMP2
STA IDELBA2
LDA ZTMP3
STA IDELBA3
JSR IDEWSEC ;write the updated sector
PLA
TAY
PLA
TAX
LDA #$00
RTS
SETSAT_E PLA
TAY
PLA
TAX
LDA #$FF
RTS
; *** RDSAT: Used by GETSAT and SETSAT to read the SAT sector from disk
RDSAT ;Calculate position in SAT for sector 's':
; sector = start_of_SAT + (s / 4096)
; byte = (s % 4096) / 8
; bit = (s % 4096) % 8
;s % 4096 == s & 0xFFF
LDA ZTMP0
STA ZTMP8
AND #7 ;(s % 4096) % 8 == (s % 4096) & 7
STA ZTMP10
LDA ZTMP1
AND #$0F
STA ZTMP9
;(s % 4096) / 8 == (s % 4096) >> 3
LDX #3
RDSAT1 LSR ZTMP9
ROR ZTMP8
DEX
BNE RDSAT1
;s / 4096 == s >> 12
LDX #12
RDSAT2 LSR ZTMP3
ROR ZTMP2
ROR ZTMP1
ROR ZTMP0
DEX
BNE RDSAT2
;now: ZTMP0-ZTMP3 = s / 4096
; ZTMP8-ZTMP9 = (s % 4096) / 8
; ZTMP10 = (s % 4096) % 8
;sector = SAT_sector + partition_start + 1
INY
INY
LDA DRIVETAB,Y
STA ZTMP4
INY
LDA DRIVETAB,Y
STA ZTMP5
INY
LDA DRIVETAB,Y
STA ZTMP6
INY
LDA DRIVETAB,Y
STA ZTMP7
JSR ADD32
INC ZTMP0
BNE RDSAT3
INC ZTMP1
BNE RDSAT3
INC ZTMP2
BNE RDSAT3
INC ZTMP3
;read the sector
RDSAT3 LDA ZTMP0
STA IDELBA0
LDA ZTMP1
STA IDELBA1
LDA ZTMP2
STA IDELBA2
LDA ZTMP3
STA IDELBA3
LDA #IDEBUF0
STA IDEBUFP
LDA #IDEBUF0/256
STA IDEBUFP+1
JSR IDERSEC
RTS
; *** DLPARTAB: Download partition table from serial port
DLPARTAB JSR LCDCLR
LDA #IDEBUF0 ;set up pointer to IDE buffer
STA IDEBUFP
STA ZTMP0
LDA #IDEBUF0/256
STA IDEBUFP+1
STA ZTMP1
;read 512 bytes
LDX #0 ;will count the 2 pages
LDY #0
DLPARTA0 JSR RXBYTE ;get byte from serial port
STA (ZTMP0),Y
INY
TYA
BNE DLPARTA0
INC ZTMP1 ;increment pointer high-byte
INX
CPX #2 ;done 2 pages?
BNE DLPARTA0
LDA #0 ;set sector number - partition table is sector 0
STA IDELBA0
STA IDELBA1
STA IDELBA2
STA IDELBA3
JSR IDEWSEC ;write to drive
RTS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -