VolksForth

Atari8bit-blockio
Login

Forth Block IO

Requires: 6502 Assembler, Disk-IO (SIO)

\ Forth Block IO

\needs code   INCLUDE" D1:TAS65.FS"
\needs block@ INCLUDE" D1:SIO.FS"

CR .( load Block Interface )

$40 ' C/L 2+ !  \ redefine char/line
$10 ' L/S 2+ !  \ redefine lines/scr
1 OFFSET !      \ offset for boot sec
HERE CONSTANT BUFMEM  \ start of buf
4 B/BUF * ALLOT \ allocate 8 buffer
HERE ' LIMIT 2+ ! \ patch limit
VARIABLE BUFFERS 0 BUFFERS ! \ semaph

: DRV? ( blk -- drv# ) DROP DRV @ ;

DEFER R/W
DEFER DISKERR

: (DISKERR
  ." ERROR! R to retry "
  KEY DUP ASCII R = SWAP ASCII R =
  OR NOT ABORT" Aborted" ;
' (DISKERR  IS DISKERR   

| : THIS? ( blk file bufadr -- flag )
    DUP 4 + @ SWAP 2+ @ D= ;

| : (CORE? ( blk file -- dataddr / blk free )
    BEGIN
     OVER OFFSET @ + OVER PREV @
     THIS? IF
       RDROP 2DROP PREV @ 8 + EXIT 
     THEN
     2DUP >R OFFSET @ + >R PREV @
     BEGIN
      DUP @ ?DUP
     0= IF RDROP RDROP DROP EXIT 
      THEN
      DUP R> R> 2DUP >R >R ROT THIS?
     0= WHILE
      NIP 
     REPEAT
     DUP @ ROT !  PREV @ OVER !  
     PREV !
     RDROP RDROP
    REPEAT
    ; -2 ALLOT \ never reached!

| : BACKUP ( buffaddr -- )
    DUP 6 + @ 0<
    IF 2+ DUP @ 1+
     IF INPUT PUSH OUTPUT PUSH 
        STANDARDI/O 
        BEGIN
          DUP 6 + OVER 2+ @ 2 PICK
          @ 0 R/W
        WHILE ." Write" DISKERR
        REPEAT
     THEN
     $80 OVER 5 + CTOGGLE
    THEN DROP ;

| : EMPTYBUF ( bufaddr -- )
    2+ DUP ON 4 + OFF ;

| : FILE@ FILE @ ;

| : READBLK ( BLK FILE ADDR -- BLK FILE ADDR )
    DUP EMPTYBUF 
    INPUT PUSH OUTPUT PUSH
    STANDARDI/O >R
    BEGIN
     OVER OFFSET @ + OVER R@ 8 +
     -ROT 1 R/W 
    WHILE ." READ " DISKERR
    REPEAT
    R> ;

| : TAKE ( -- bufaddr )
    PREV
    BEGIN 
     DUP @ 
    WHILE
     @ DUP 2+ @ -1 = UNTIL
    BUFFERS LOCK  DUP BACKUP ;

| : MARK ( BLK FILE BUFADDR -- BLK FILE )
    2+ >R 2DUP R@ ! 
    OFFSET @ + R@ 2+ !
    R> 4 + OFF BUFFERS UNLOCK ;

| : UPDATES? ( -- bufaddr / flag )
    PREV BEGIN
          @ DUP
         WHILE DUP 6 + @ 0<
         UNTIL ;

| : FULL? ( -- flag )
    PREV BEGIN
          @ DUP @
    0= UNTIL 
    6 + @ 0< ;

: CORE? ( blk file -- addr / false )
  (CORE? 2DROP FALSE ;

: (BUFFER ( blk file -- addr )
  BEGIN (CORE? TAKE MARK REPEAT ;
  -2 ALLOT \ never reached

: (BLOCK ( blk file -- addr )
  BEGIN 
   (CORE? TAKE READBLK MARK 
  REPEAT ; -2 ALLOT \ never reached

: BUFFER ( blk -- addr )
  FILE@ (BUFFER ;

: BLOCK  ( blk -- addr )
  FILE@ (BLOCK ;

: UPDATE 
  $80 PREV @ 7 + C! ;

: SAVE-BUFFERS
  BUFFERS LOCK 
  BEGIN
   UPDATES? ?DUP
  WHILE
   BACKUP
  REPEAT
  BUFFERS UNLOCK ;

: EMPTY-BUFFERS
  BUFFERS LOCK
  PREV
  BEGIN 
   @ ?DUP
  WHILE
   DUP EMPTYBUF
  REPEAT
  BUFFERS UNLOCK ;

: FLUSH
  SAVE-BUFFERS EMPTY-BUFFERS ;

: ALLOTBUFFER ( -- )
  FIRST @ BUFMEM - B/BUF 2+ U< ?EXIT
  B/BUF NEGATE FIRST +! 
  FIRST @ DUP EMPTYBUF 
  PREV @ OVER ! PREV ! ;

: FREEBUFFER ( -- )
  FIRST @ LIMIT B/BUF - U< IF
   FIRST @ BACKUP PREV
   BEGIN
    DUP @ FIRST @ -
   WHILE
    @
   REPEAT
   FIRST @ @ SWAP ! 
   B/BUF FIRST +!
  THEN ;

: ALL-BUFFERS ( -- )
  BEGIN
   FIRST @ ALLOTBUFFER FIRST @ = 
  UNTIL ;

: INIT-BUFFERS ( -- )
  PREV OFF LIMIT FIRST ! ALL-BUFFERS ;

INIT-BUFFERS 
 
: LOAD ( blk -- )
  ?DUP 0= ?EXIT BLK PUSH BLK !
  >IN PUSH >IN OFF .STATUS INTERPRET ;

: +LOAD ( offset -- ) BLK @ + LOAD ;

: THRU  ( from to -- ) 
  1+ SWAP DO I LOAD LOOP ;

: +THRU ( off0 off1 -- )
  1+ SWAP DO I +LOAD LOOP ;

: --> ( -- ) 
  1 BLK +! >IN OFF .STATUS ; IMMEDIATE

: LIST ( blk -- )
  SCR ! ." SCR " SCR @ DUP u.
        ." DR " DRV? .
  L/S 0 DO
    CR I 2 .R SPACE SCR @ BLOCK 
    I C/L * + C/L -TRAILING TYPE
  LOOP CR ;

: (R/W ( addr block file rwf -- ior )
  SWAP ABORT" NO FILE BLOCK SUPPORT"
  IF BLOCK@ ELSE BLOCK! THEN
;

' (R/W IS R/W

| : NSRC ( -- addr len ) \ new SOURCE
    BLK @ ?DUP IF BLOCK B/BLK EXIT THEN
    TIB TIB# @ ;

\ patch "SOURCE" in Kernel
' NEWSRC ' SOURCE >BODY !

| : INIT INIT-BUFFERS PAGE
    ." Block Interface for SIO" CR
  ;

' INIT IS 'COLD

\ : .BUFFER ( addr -- )
\   CR DUP ." Next link:" @ U. CR
\   2+ DUP ." File     :" @ U. CR
\   2+ DUP ." Block num:" @ U. CR
\   2+ DUP ." Status   :" @ U. CR
\   2+ B/BUF DUMP ;

CR .( Block Interface loaded ) CR

\ LABEL THISBUFFER
\      2 # LDY         \ LDY #2
\      [[ 
\        N 4 + )Y LDA  \ LDA (N+4),Y  
\        N 2- ,Y  CMP  \ CMP N-2,Y
\      0= ?[[
\        INY           \ INY
\        6 # CPY       \ CPY #6
\      0= ]?
\      RTS