163 lines
2.7 KiB
Z80 Assembly
163 lines
2.7 KiB
Z80 Assembly
|
.global _start
|
||
|
|
||
|
_start:
|
||
|
call find_disk
|
||
|
ld a, 7
|
||
|
call 0xdffd
|
||
|
push hl
|
||
|
ld de, 0
|
||
|
ld a, 8
|
||
|
call 0xdffd
|
||
|
pop hl
|
||
|
ld (mailbox_num), hl
|
||
|
msg_loop:
|
||
|
call yield
|
||
|
yield_back:
|
||
|
ld hl, (mailbox_num)
|
||
|
ld a, 6
|
||
|
call 0xdffd
|
||
|
msg_read:
|
||
|
push bc
|
||
|
push de
|
||
|
push hl
|
||
|
ld b, c
|
||
|
ld c, 0xB
|
||
|
call set_frame
|
||
|
ld a, h
|
||
|
or 0xB0
|
||
|
ld h, a
|
||
|
ld c, (hl)
|
||
|
inc hl
|
||
|
ld b, (hl)
|
||
|
inc hl
|
||
|
ld e, (hl)
|
||
|
inc hl
|
||
|
ld d, (hl)
|
||
|
ld hl, 0xB000
|
||
|
jp read_bytes
|
||
|
ld hl, (0xB004) ; Load destination mailbox into HL
|
||
|
pop ix
|
||
|
pop de
|
||
|
pop bc
|
||
|
ld a, 5
|
||
|
call 0xdffd
|
||
|
halt
|
||
|
jp msg_loop
|
||
|
halt
|
||
|
|
||
|
read_buf: .ds.b 512
|
||
|
|
||
|
;Given a starting byte number in BC, a byte count in DE, and a destination address in HL, reads those bytes off the disk
|
||
|
read_bytes:
|
||
|
ld (start_byte), bc
|
||
|
ld (byte_count), de
|
||
|
ld (dest_addr), hl
|
||
|
ld c, 0
|
||
|
ld d, 0
|
||
|
ld e, b
|
||
|
ld hl, sec_buf
|
||
|
call read_sector
|
||
|
ld hl, sec_buf
|
||
|
ld b, 0 ; Load BC with lower byte of start_byte (sector offset)
|
||
|
ld a, (start_byte)
|
||
|
ld c, a
|
||
|
add hl, bc ; Add the offset to the buffer address
|
||
|
ld de, (dest_addr)
|
||
|
ld a, (start_byte) ; A = 255 - offset + 1 (256-offset)
|
||
|
ld b, a
|
||
|
ld a, 0xFF
|
||
|
sub b
|
||
|
inc a
|
||
|
ld b, 0 ; Load bc with the value in A
|
||
|
ld c, a
|
||
|
ldir
|
||
|
start_sec_trns_done:
|
||
|
ld (dest_addr), de
|
||
|
ld a, (start_byte) ; A = 255 - offset + 1 (256-offset)
|
||
|
ld b, a
|
||
|
ld a, 0xFF
|
||
|
sub b
|
||
|
inc a
|
||
|
ld b, 0 ; Load bc with the value in A
|
||
|
ld c, a
|
||
|
ld hl, (byte_count)
|
||
|
scf
|
||
|
ccf
|
||
|
sbc hl, bc
|
||
|
ld (rem_bytes), hl
|
||
|
ld b, h
|
||
|
ld c, 0
|
||
|
ld d, 0
|
||
|
ld a, (start_byte+1)
|
||
|
inc a
|
||
|
ld e, a
|
||
|
ld hl, (dest_addr)
|
||
|
sector_loop:
|
||
|
push bc
|
||
|
call read_sector
|
||
|
inc de
|
||
|
pop bc
|
||
|
djnz sector_loop
|
||
|
ld (dest_addr), hl
|
||
|
ld hl, (sec_buf)
|
||
|
call read_sector
|
||
|
ld hl, (sec_buf)
|
||
|
ld de, (dest_addr)
|
||
|
ld b, 0
|
||
|
ld a, (rem_bytes)
|
||
|
ld c, a
|
||
|
ldir
|
||
|
read_bytes_done:
|
||
|
ret
|
||
|
|
||
|
start_byte: .ds.b 2
|
||
|
byte_count: .ds.b 2
|
||
|
dest_addr: .ds.b 2
|
||
|
rem_bytes: .ds.b 2
|
||
|
sec_buf: .ds.b 256
|
||
|
|
||
|
; Given a sector number in C:DE and a buffer address in HL, reads the sector off disk.
|
||
|
; Clobbers A, BC, HL
|
||
|
read_sector:
|
||
|
push bc
|
||
|
ld c,0xFF ; Force the top half of the IO address to be the id of the card,
|
||
|
ld a, (disk_num) ; so the block transfer instructions can be used
|
||
|
out (c), a
|
||
|
pop bc
|
||
|
ld a, c
|
||
|
ld c, 0
|
||
|
out (c), e
|
||
|
inc c
|
||
|
out (c), d
|
||
|
inc c
|
||
|
out (c), a
|
||
|
ld b, 0x0 ; Setup a transfer of 256 bytes (1 sector) at a time
|
||
|
ld c, 0x3 ; from the storage device's data port
|
||
|
inir
|
||
|
ld c,0xFF ; Unforce the top half of the IO address
|
||
|
in a,(c)
|
||
|
read_sec_done:
|
||
|
ret
|
||
|
|
||
|
|
||
|
|
||
|
.global find_disk
|
||
|
; Clobbers A and HL
|
||
|
find_disk:
|
||
|
ld b,0x4
|
||
|
call find_first_card
|
||
|
ld a, l
|
||
|
ld (disk_num), a
|
||
|
ret
|
||
|
|
||
|
disk_num: .ds.b 1
|
||
|
mailbox_num: .ds.b 2
|
||
|
|
||
|
/* Start sector: Start byte / 256 */
|
||
|
/* Offset in start sector: Start byte % 256 */
|
||
|
/* Rem bytes: Byte count - (256 - Offset in start sector) */
|
||
|
/* Middle sectors start: start sector + 1 */
|
||
|
/* Middle sectors count: Rem bytes / 256 */
|
||
|
/* End sector: Middle sectors start + Middle sectors count */
|
||
|
/* End sector copy length: Rem bytes % 256 */
|