|
- ; tape blkdev read-only
- ; to be included as a kernel module.
- ; In the glue.asm devices list the PutB pointer has to be unsetZ
-
- ; defines:
- ; tap_buffer = 256-byte tape loading buffer in RAM
- ; buf_pos = read position in the buffer
- ; crossing the buffer boundaries require loading or rewinding+loading
- ; tap_pos = previous read position of the block device,
- ; then the difference btw current and previous positions, both in EDLH format as throughout the kernel code
-
- tapeblk_init:
- ; initialized CFS and a placeholder 1-block, 1-byte file in the buffer
- ; the tape fs is not default, has to be mounted
- ld hl, .plh
- ld de, tap_buffer
- ld bc, 6
- ldir
- ret
- .plh:
- .db "CFS",1,1,0,'@'
-
- tapeGetB:
- ; it gets the new position in DE/HL, has to return value in A
- push bc
- push ix
-
- ; First of all, is the difference between positions negative or positive?
- push hl ; store the position
- push de
- ld ix, tap_pos ; previous
-
- push de ; working copy, higher bytes
- ld e, (ix+2) ; lower bytes of previous position
- ld d, (ix+3)
- scf
- ccf
- sbc hl,de
- ld (ix+6), l
- ld (ix+7), h
- pop hl
- ld e, (ix+0) ; higher bytes
- ld d, (ix+1)
- sbc hl,de
- ld (ix+4), l
- ld (ix+5), h
- jp nc, .tblk_posdif
-
- .tblk_negdif:
- ; at this point we have the negative difference
- pop de ; restore the current position
- pop hl
- ; store it as 'the previous'
- ld (ix+0), e
- ld (ix+1), d
- ld (ix+2), l
- ld (ix+3), h
-
- ; let's set the buffer position while we're here
- ld a, (buf_pos)
- add a, (ix+6) ; l
- ; the difference bytes are negative, so e.g. add 255 = sub 1
- ld (buf_pos), a
- ; no carry would mean underflow in this case
- jp nc, .tblk_rewind
- ; we now have a chance that the higher bytes are FF (due to lower CY)
- xor a
- dec a
- and (ix+7)
- and (ix+4)
- and (ix+5)
- cp 255
- jp z, .tblk_readbyte ; a negative difference within the buffer
-
- ; we have to rewind the tape and load back to the current position,
- ; so it's safe to discard the difference and treat the current position as the positive difference
-
- .tblk_rewind:
- ; as we will rewind to zero, at least one additional block is to be loaded
- xor a
- inc h
- cp h
- jr nz, .tblk_store
- inc de
- .tblk_store:
- ld (ix+4), e ; diff
- ld (ix+5), d
- ld (ix+6), l ; diff
- ld (ix+7), h
-
- ; purple border means 'rewind the tape and press enter'
- di
- ld a, 3
- out (254), a
- .tblk_key:
- ld a, 191 ; waiting for enter
- in a,(254)
- rra
- jr c, .tblk_key
- ei
- jr .tblk_skip
- ; we don't have to set the buffer position, done it already
-
- .tblk_posdif:
- ; at this point we have the difference and know it is positive
- pop de ; restore the current position
- pop hl
- ; store it as 'the previous'
- ld (ix+0), e
- ld (ix+1), d
- ld (ix+2), l
- ld (ix+3), h
-
- .tblk_buffer:
- ; setting the buffer position for the positive difference
- ld a, (buf_pos)
- add a, (ix+6) ; l
- ld (buf_pos), a
- jr nc, .tblk_skip
-
- ; now we increase the higher difference bytes due to overflow
- xor a
- inc (ix+7) ; h
- cp (ix+7)
- jr nz, .tblk_skip
- inc (ix+4) ; e
- cp (ix+4)
- jr nz, .tblk_skip
- inc (ix+5) ; d
-
- .tblk_skip:
- ; Now, how many tape blocks do we have to load before the target block appears in the buffer?
- ; it is shown by the 3 higher bytes of the difference
- ; We've just set them up for the positive difference case.
-
- ; For the negative difference case, the L-byte has to be equal to the buf_pos we set earlier
-
- ; (ix+7) H, (ix+4) E, (ix+5) D is now the counter for blocks to be loaded
- ; if it's 0, the block is already at the buffer and we don't have to load anything
- xor a
- or (ix+7)
- or (ix+4)
- or (ix+5)
- jp z, .tblk_readbyte
-
- ; well, let's play the tape
- ld a, (ix+5)
- ld b,a ; this is the outer cycle
- inc b ; as we will djnz
- ld a, (ix+7)
- ld l, a ; lower byte of the inner counter
- ld a, (ix+4)
- ld h, a ; higher byte
- dec hl ; as we know at this point that at least one block is to be loaded
- ld c, 0 ; it's a 16-bit cycle flag used below
- xor a
- or h
- or l
- jp z, .tblk_load
- ld c, 1 ; hl=nonzero
-
- .tblk_load:
- push bc ; counters
- push hl
- ld ix, tap_buffer ; we don't need the ix value anymore
- ld de, 256
- ld a, 255
- call t_load
- pop hl
- pop bc
-
- ; counter
- xor a
- dec hl
- or h
- or l
- jr nz, .tblk_ccheck
- ld c, 0 ; on the next cycle, b has to be decremented
- jr .tblk_load
- .tblk_ccheck:
- xor a
- or c
- jp nz, .tblk_load
- inc c ; next 16-bit cycle
- djnz .tblk_load
-
- .tblk_readbyte:
- ld hl, tap_buffer
- ld b, 0
- ld a, (buf_pos)
- ld c, a
- add hl,bc
- ld a, (hl) ; here it is!
- pop ix
- pop bc
- cp a
- ret
-
- t_load:
- push iy
- ld iy, IYBAS
- scf
- ; one can not call directly, as RST8 is then called upon break
- inc d
- ex af,af'
- dec d
- di
- ld a, 15
- out (254), a
- call 1378 ; jump into LD-BYTES
- t_ldret:
- ld a, (23624) ; restore border
- and 0x38
- rrca
- rrca
- rrca
- out (254),a
- pop iy
- ei
- ret
-
- ;end
|