Jump to content
senior_falcon

The Missing Link and CF7 compatibility

Recommended Posts

8 hours ago, senior_falcon said:

If I understand this correctly, you can do the equivalent of CALL FILES(1) and put all the disk information so that nothing above >1FFF is used at all. The downside to this is that the stack space will be reduced by 529 bytes. Normally there are 1460 bytes of stack space available; reducing that by 529 is a deal breaker.

That's just a number I chose - choose whatever values work for you. ;)

 

(edit: most of the CF7 is the standard TI DSR... so these statements are also true for it. They start with whatever is in >8370 when the powerup routine is called. This allows for multiple cards to reserve VDP RAM space. It just so happens that we all took what the TI Disk Controller did as the only gospel ;) )

 

Edited by Tursi

Share this post


Link to post
Share on other sites
7 hours ago, Lee Stewart said:

 

The TI disk controller specs require(?) an additional buffer for one Volume Information Block (VIB) + other stuff for a total of 534 bytes. That plus one buffer (518 bytes) for one open file would seem to require starting one byte above >3BE3 - (>3FFF - >1FFF) = >3BE3 - >2000 = >1BE3 rather than >1DF3. How do you get away with room for only one buffer?

 

...lee

The VDP stack area, (252 bytes) Disk drive info (4 bytes) , ??(6 bytes),Volume information block(256 bytes) and file name compare buffer (11 bytes) normally start at >3DEF and run to >3FFF. These are perfectly happy when left in their original location. Only the 5 byte header and 518 byte buffers have to be moved. I have no idea why this works, but it does, at least on the TI controller. As I remember, this technique did not work so well with the Myarc controller. The locations seemed to be hard coded. But it was still usable for 1 disk file and with some VDP shuffling I could get 2 disk files.

Edited by senior_falcon
  • Thanks 1

Share this post


Link to post
Share on other sites

If I understand the previous comments, there are 8 bytes inserted at >3FF8 to >3FFF used by the CF7. Then (for CALL FILES(3)) everything that is normally loaded from >37D8 to >3FFF is loaded 8 bytes lower in memory. So at >37D0 are the bytes >AA,>3F,>FF,>11,>03

Is this correct?

Share this post


Link to post
Share on other sites
2 hours ago, senior_falcon said:

If I understand the previous comments, there are 8 bytes inserted at >3FF8 to >3FFF used by the CF7. Then (for CALL FILES(3)) everything that is normally loaded from >37D8 to >3FFF is loaded 8 bytes lower in memory. So at >37D0 are the bytes >AA,>3F,>FF,>11,>03

Is this correct?

Yes (though the >11 is >10 in Classic99, as that's the CRU base of the disk device that created the buffer).

 

image.thumb.png.f495532e491031aa2be0b07fd184811a.png

Share this post


Link to post
Share on other sites

I may have found the reason the CF7 doesn't work with The Missing Link. Upon startup, TML moves the disk buffer(s) and then clears the VDP graphics tables above the disk buffers. I don't remember why I did it this way, but VDP is cleared all the way up to >3FFA. This overwrites the >AA03 header at >3FF8. Tursi didn't see that the header was checked by the DSR, but if it is, then that would explain why the CF7 does not work. I will have a new test program to post in the next day or two. The answer is binary-either it works or it does not. If not then I don't think there is anything else that can be done.

  • Like 3

Share this post


Link to post
Share on other sites
3 hours ago, senior_falcon said:

I may have found the reason the CF7 doesn't work with The Missing Link. Upon startup, TML moves the disk buffer(s) and then clears the VDP graphics tables above the disk buffers. I don't remember why I did it this way, but VDP is cleared all the way up to >3FFA. This overwrites the >AA03 header at >3FF8. Tursi didn't see that the header was checked by the DSR, but if it is, then that would explain why the CF7 does not work. I will have a new test program to post in the next day or two. The answer is binary-either it works or it does not. If not then I don't think there is anything else that can be done.

It'll be interesting if that's it, but I suspect not. When the CF7 DSR needs to access a disk, it needs to FIND that 8 byte header, and it does that (as far as I can tell) starting with >8370, which TML changes. I suppose what we could do is work backwards, set up the system for TML, do a disk access, and see where it reads to find the disk volume. That may give the missing insight. ;)

 

 

Edited by Tursi

Share this post


Link to post
Share on other sites

First, I ran the CF7 normally with a breakpoint on VDP reads from >3FFA, so I could see where the DSR does the lookup for DSK1. I don't follow the code that does the calculation, unfortunately, we'd have to work backwards, but the code that uses the calculation is here:

 

   55DE  D220  movb @>834c,R8
         834C
   55E2  0988  srl  R8,8
   55E4  0608  dec  R8
   55E6  0A18  sla  R8,1
   55E8  A220  a    @>8358,R8
         8358
   55EC  0228  ai   R8,>010d
         010D
>  55F0  06A0  bl   @>4628  

 

This puts the base address (>3FFA) into R8. The BL sets the VDP address and reads two bytes for return in R0.

 

So with that in mind, I started up TML and put a breakpoint at >55F0.

 

When I run TML with the CF7 in Classic99, I see all eight bytes at >3ff8 have been zeroed. That would of course be a problem... so in the debugger I manually added them back before the test. I should breakpoint anyway...

 

and the address is >3FFA! and the disk access worked (remember I manually poked the values back in).

 

So, I can take it back.. it likely IS the loss of those top bytes -- but they are all lost, not just the two header bytes. :)


 

  • Like 1

Share this post


Link to post
Share on other sites
14 minutes ago, Tursi said:

 I suppose what we could do is work backwards, set up the system for TML, do a disk access, and see where it reads to find the disk volume. That may give the missing insight. ;)

Your setup/test will most likely confirm once and for all if the volume ID byte location is static or if it is dependent upon 8370. Debugging CALL MOUNT might provide insight, too, as you should be able to tell where that subprogram is writing the new volume IDs.

  • Like 1

Share this post


Link to post
Share on other sites

One more question just to be sure I have all the information I need. Is the CF7 the only device that moves the top of the stack pointed to by >8370?

Share this post


Link to post
Share on other sites

I searched my work folder and found some info I pulled together a few years ago. I can't be certain it is 100% accurate and if I remember correctly, this research came out of my work with the Horizon RAMdisk ROS.  ROS was using VDP to store the last accessed filename and some other misc. info (for boot tracking).  However, if there wasn't a floppy controller in the system, the normal disk buffers were not reserved.  Thus XB programs were able to use that normally-reserved disk controller buffer space but ROS assumed there was a disk controller in the system, corrupting the XB program in the process.

  • TI, CorComp, and BwG disk controllers reserve VDP RAM during powerup.  0x8370 is set to 0x37D7.  (BwG may reserve additional bytes?)
  • Myarc disk controllers set 0x8370 to 0x37D7 for compatibility with the above cards.  VDP usage is minimal. For example, disk # boot tracking does not work in the same manner as the TI and CorComp.
  • Myarc Hard/floppy controllers set 0x8370 to 0x37D7 for legacy controller compatibility when used at CRU 0x1100; otherwise, the pointer is left untouched.  VDP usage is minimal.
  •     SCSI cards do not manipulate 0x8370.
  •     IDE cards do not manipulate 0x8370.
  •     The AVPC video card reserves 16 bytes from 0x3FF0 to 0x3FFF, based on a review of the OPA 3.0 DSR.
  •     The EVPC video card reserves 2 bytes at 0x3FFE-0x3FFF
  •     EVPC2 - untested/unknown
  •     The NanoPEB/CF7 devices reserve 8 bytes of video RAM from 0x3FF8-0x3FFF to store pointers and information related to the mounted diskettes.  0x8370 is set to 0x37CF.

 

(edit: I found a copy of the same info with a few comments referencing Lee and Atrax helping with the research; I'm guessing there is an AA thread and/or wiki entry containing some of this intel.)

  • Like 2

Share this post


Link to post
Share on other sites
6 hours ago, InsaneMultitasker said:

I found a copy of the same info with a few comments referencing Lee and Atrax helping with the research; I'm guessing there is an AA thread and/or wiki entry containing some of this intel.

 

This topic: Programming challenge  (started by Tony Knerr @Gazoo) and a PM you started with me: 37d2 (7/5/2015)

 

...lee

  • Like 2

Share this post


Link to post
Share on other sites

Here is a test program to test whether the CF7 can be compatible with TML. Just run it like any XB program and follow the prompts. Don't use my file names; be sure your file names are compatible with the CF7. If all goes well you get the message "CF7 will be functional with The Missing Link"

Let me know the results...

TESTCF7.zip

  • Like 1

Share this post


Link to post
Share on other sites

Well, not sure if I did this properly, but here are the results I got.  On the "Disk buffer not OK" pic, that was after I reset the TI and tried again.

225B3DE0-9D0E-4E9D-AD80-F07AE1D8A6B2.jpeg

F1A229B4-372F-4233-B531-E2BC66F54BC0.jpeg

A17E16A3-627F-4C08-8BAF-6333A97E47B4.jpeg

Share this post


Link to post
Share on other sites

I'm just sticking my nose in here, but.. why are you doing RUN 500 instead of just RUN?

 

(Oh, I see, it's part of the test ;) )

 

Edited by Tursi

Share this post


Link to post
Share on other sites

If there's anything else I can do to help, please let me know!  I'm starting to get the feel for CF7 work again...  it is not an intuitive system, but once you get the hang of it, it's not so bad.  :) 

  • Like 2

Share this post


Link to post
Share on other sites
6 hours ago, Tursi said:

I'm just sticking my nose in here, but.. why are you doing RUN 500 instead of just RUN?

 

The test  first checks that the disk buffer has been moved. It then erases vdp memory in the areas used by TML (v2000 to v3DB6) It tries to open a DV80 file, write a line to it and close it. It then tries to open the file again and read the line. If successful it checks if the reserved vram has been corrupted. It then prompts you to save the program, erase it and load it. If you can run line 500 it shows that the program could be saved and loaded. Line 500 reports that, then checks whether the reserved vram is corrupted. Since it passes these tests it shows that TML and the CF7 should be compatible. 

 

Tursi asked  "Can you just set >8370 to the address that you want everything to be located under, then call the disk powerup routine followed by the equivalent of CALL FILES(1)?"  TML uses this code to do CALL FILES(n)

       MOVB @NFILES+1,@>834C  834C gets the # of files in MSB
       LI R0,>03E8       Unused area of VDP RAM
       LI R1,HMWS+6      R3-R5 used
       LI R2,5           5 bytes to write (only need 2 here next)
       LI R3,>0116       opcode for Allocate Disk Buffer Space
       BLWP @VMBW        Write PAB
       MOV R0,@>8356     >8356 gets address of PAB
       BLWP @DSRLNK
       DATA >000A        a subprogram

This doesn't seem to need a value in >8370. If >37d7 is there, then this routine with number of files=3 puts >37D7 into >8370. Maybe there is a lower level program that expects a value in >8370?

Thanks to all who helped troubleshoot this problem, Tursi and Opry99 in particular. I should be posting a revised version of TML that is CF7 compatible in the next few days. Even better, this information will make it possible to have a very nice Christmas present for those of you who are XB programmers...

  • Like 4

Share this post


Link to post
Share on other sites
10 hours ago, senior_falcon said:

This doesn't seem to need a value in >8370. If >37d7 is there, then this routine with number of files=3 puts >37D7 into >8370. Maybe there is a lower level program that expects a value in >8370?

 

There is, indeed, a lower level program that expects a value in >8370. It is the “subprogram” (>16) in the DSR that you call with DSRLNK. This routine starts at A5DAE in the DSR code disassembled by Thierry Nouspikel from the TI disk controller’s ROM (see spoiler below):

 

Spoiler
*====================================
*
* TI DISK CONTROLLER ROM   >4000-5FFF
*
*====================================
*
       AORG >4000
*
A4000  BYTE >AA               standard header mark
       BYTE >02               version 2
       DATA >0000             no programs
       DATA A4044             power-up chain ptr
       DATA >0000             programs chain ptr (none)
       DATA A404A             DSR chain ptr
       DATA A4010             subprograms chain ptr
       DATA >0000             ISR chain ptr (none)
       DATA >0000
 
A4010  DATA A4016             link to next subprogram
       DATA A5B38             address of that one
       DATA >0110             subprogram name: >10 (sector R/W)
A4016  DATA A401C
       DATA A5B48
       DATA >0111             subprogram >11 (format disk)
A401C  DATA A4022
       DATA A5B52
       DATA >0112             subprogram >12 (file un/protect)
A4022  DATA A4028
       DATA A5BAC
       DATA >0113             subprogram >13 (file rename)
A4028  DATA A402E
       DATA A5C78
       DATA >0114             subprogram >14 (file direct input)
A402E  DATA A4034
       DATA A5CE8
       DATA >0115             subprogram >15 (file direct output)
A4034  DATA A403A
       DATA A5DAE
       DATA >0116             subprogram >16 (number of files)
A403A  DATA >0000             no more
       DATA A5D5A
       BYTE >05
       TEXT 'FILES'           same as >16, called from Basic
 
A4044  DATA >0000             power-up chain (no more)
       DATA A4070             address of power-up routine
       DATA >0000             no name
 
A404A  DATA A4052             DSR chain
       DATA A504E             address of DSR
       BYTE >03               name size
       TEXT 'DSK'             DSR name
A4052  DATA A405C
       DATA A505C
       BYTE >04
       TEXT 'DSK1'
       EVEN
A405C  DATA A4066
       DATA A5062
       BYTE >04
       TEXT 'DSK2'
       EVEN
A4066  DATA >0000             no more
       DATA A5068
       BYTE >04
       TEXT 'DSK3'
       EVEN

*=====================================
* Power-up routine
*=====================================
A4070  MOV  11,7              save return address
       STWP 9                 get workspace (should be >83E0)
       AI   9,>FF20           point to top of scratch-pad mem (>8300)
       MOV  @>0070(9),0       highest free address in vdp mem (>8370)
       MOV  0,2               save it
       AI   0,>F7D8           we'll need >828 bytes
       MOV  0,@>0070(9)       update address
       INC  0
       BL   @A40DA            set VDP address
       LI   1,>0828
A4090  CLR  @>FFFE(15)        clear these >828 bytes
       DEC  1
       JNE  A4090
       BL   @A40DA            set VDP address (same)
       LI   3,>AA03
       MOVB 3,@>FFFE(15)      write buffer ID mark
       NOP
       MOVB 2,@>FFFE(15)      write old highest free address
       SWPB 2
       MOVB 2,@>FFFE(15)
       NOP
       MOVB 12,@>FFFE(15)     write CRU base of disk controller (1 byte)
       SWPB 3
       MOVB 3,@>FFFE(15)      write number of files (3)
       BL   @A4726            preparation routine
       BL   @A4658            call subroutine
       DATA A4554             reset all drives
       CLR  @>0054(9)         name length = 0 for power-up
       BLWP @>005A(9)         retrieve R7 (saved by A4726)
       DATA >0011             put it into R11
       MOV  @A40D8,@>006C(9)  ???
       B    *11               return
 
A40D8  DATA >0404
*
A40DA  ORI  0,>4000           set VDP for a write
       SWPB 0                 -------------------
       MOVB 0,*15             pass address
       SWPB 0
       MOVB 0,*15
       B    *11
 
*---------------------------------------
* Sector read/write
*---------------------------------------
A40E8  LI   4,>000A           try ten times
A40EC  MOVB @A4630,@>0050(9)  no error
       BL   @A4496            select drive
       BL   @A45F0            point to # of last track
       CLR  0
       MOVB @>FBFE(15),0      get # of last track accessed
       CI   0,>D700
       JH   A410C             too high: drive was reset
       BL   @A4524            seek track 0
       SETO 0                 inverted data bus" >FF will be >00
A410C  MOVB 0,@>5FFA          place >00 in track register
       MOV  @>004A(9),1       sector #
       SBZ  7                 side 0
       CLR  7
       CI   1,>02D0           max 720 (DS/SD)
       JHE  A41B6             error 7
       CI   1,>0168           on which side is it?
       JL   A413E             0-359: on side 0
       AI   1,-719            on side 1: sector # grow from in to out
       ABS  1                 719 - sector #
       CLR  0
       DIV  @A4632,0          sect/track (=9)
       AI   1,-8              invert: 8=0, 0=8, 7=1, etc
       ABS  1
       SBO  7                 side 1
       LI   7,>0100           side number = >01
       JMP  A414E
A413E  CI   1,>0001           is it sector 0 or 1?
       JH   A4148             no
       BL   @A4524            yes: seek track 0
A4148  CLR  0
       DIV  @A4632,0          R0=track #, R1=sector #
A414E  SWPB 0
       INV  0
       BL   @A4614            set VDP to write
       MOVB 0,@>FFFE(15)      save # of last track accessed
       MOVB 0,@>5FFE          pass to data register
       SWPB 1
       INV  1
       MOVB 1,@>5FFC          pass new sector # to sector register
       CB   0,@>5FF2          new track # same as current?
       JEQ  A417A             yes
       BL   @A45CA            send command
       DATA >E100             "seek" h=1 V=1 r1r0=10
       BL   @A4482            wait for command completion
       SLA  0,13              test "seek error" bit
       JOC  A41B0             try again, then error 11
A417A  BL   @A45CA            send command
       DATA >3F00             "read ID" E=0
       SBO  2                 enable hold
       MOVB @>5FF6,0          skip track #
       LI   6,>0004
       MOVB @>5FF6,5          side #
       INV  5
A4190  MOVB @>5FF6,0          skip next 4 bytes
       DEC  6
       JNE  A4190
       BL   @A4480            SBZ 2, wait for command completion
       SLA  0,13              test status bits
       JOC  A41BC             "not found": try again, then error 21
       JLT  A41C2             "crc error": try again, then error 22
       SLA  0,2
       JOC  A41C8             "lost data": try again, then error 23
       CB   7,5               side # matches?
       JEQ  A41CE             yes: sector found, now access it
 
A41AA  BL   @A45AC            no: error 6
       DATA >0600
A41B0  BL   @A4590            gracefull error 11
       DATA >1100
A41B6  BL   @A45AC            error 7
       DATA >0700
A41BC  BL   @A4590            gracefull error 21
       DATA >2100
A41C2  BL   @A4590            gracefull error 22
       DATA >2200
A41C8  BL   @A4590            gracefull error 23
       DATA >2300
 
A41CE  MOVB 1,@>5FFC          load sector register
       MOV  @>004E(9),2       data buffer address
       MOVB @>004D(9),0       read or write ?
       JEQ  A425C             write
       BL   @A4614            read: set VDP to write
A41E0  BL   @A45CA            ---- send command
       DATA >7700             "read sector" m=0 S=1 E=0 C=0
       LI   6,>0100           256 bytes / sector
       SETO 5
       SBO  2
       MOVB @>004D(9),0       read or write?
       JNE  A4214             read
       CLR  0                 write:  now we must verify
A41F6  MOVB @>5FF6,0          get a byte from FDC ------
       AB   @>FBFE(15),0      compare with byte in data buffer
       CI   0,>FF00
       JNE  A422E             mismatch
       SZCB @>5FF6,0          again
       SB   @>FBFE(15),0
       JNE  A422E             mismatch
       DECT 6
       JNE  A41F6             next byte
       JMP  A422C             done
A4214  MOVB @>5FF6,0          get 1 byte from FDC
       INV  0
       MOVB 0,@>FFFE(15)      save it to VDP
       MOVB @>5FF6,0          again
       INV  0
       MOVB 0,@>FFFE(15)
       DECT 6
       JNE  A4214             next byte
A422C  CLR  5                 clear flag
A422E  BL   @A4480            SBZ 2, wait for command completion
       SLA  0,13              test status bits
       JOC  A4244             "not found": try again, then error 21
       JLT  A424A             "crc error": try again, then error 22
       MOV  5,5
       JNE  A4256             try again, then error 28
       SLA  0,2
       JOC  A4250             "lost data": try again, then error 23
       B    @A4676            return
 
A4244  BL   @A4590            gracefull error 21
       DATA >2100
 
A424A  BL   @A4590            gracefull error 22
       DATA >2200
A4250  BL   @A4590            gracefull error 23
       DATA >2300
A4256  BL   @A4590            gracefull error 28
       DATA >2800
 
A425C  BL   @A461E            write: set VDP to read
       BL   @A45CA            ----- send command
       DATA >5700             "write sector" m=0 S=1 E=0 C=0 a=0
       LI   6,>0100           256 bytes / sector
       SBO  2                 enable holds
A426C  MOVB @>FBFE(15),0      get a byte from data buffer
       INV  0
       MOVB 0,@>5FFE          pass it to data register
       MOVB @>FBFE(15),0      again
       INV  0
       MOVB 0,@>5FFE
       DECT 6
       JNE  A426C             next
       BL   @A4480            SBZ 2, wait for command completion
       SLA  0,11              test status bits
       JOC  A429A             "write protect": error 34
       SLA  0,2
       JOC  A42A0             "not found": try again, then error 31
       SLA  0,2
       JOC  A42A6             "lost data": try again, then error 33
       BL   @A461E            now, set VDP to read
       JMP  A41E0             and verify sector
 
A429A  BL   @A45AC            error 34
       DATA >3400
A42A0  BL   @A4590            gracefull error 31
       DATA >3100
A42A6  BL   @A4590            gracefull error 33
       DATA >3300
 
*---------------------------------------
* Format disk
*---------------------------------------
A42AC  CLR  @>004A(9)         called by subprogram >11
       MOVB @>004C(9),8       DSR version + drive #
       SRL  8,12              keep version only
       JEQ  A42C4             0: standard format
       C    8,@A4630
       JEQ  A42C4             1: needs DSR version 2 (this one)
       BL   @A45AC            2: needs another version
       DATA >0700             returns with error 7
 
A42C4  SZCB @A4638,@>004C(9)  clear DSR version flags
       CB   @>0051(9),@A4657  double sided?
       JNE  A42D6             no
       SETO @>004A(9)         yes: set flag
A42D6  MOVB @A4630,@>0050(9)  no error
       BL   @A4496            select drive
       BL   @A4524            seek track 0
       CLR  3                 init track counter
A42E6  MOV  @>004A(9),@>004A(9) check # of sides flag
       JEQ  A42F8             single-side
       SBO  7                 set CRU bit for side 1
       LI   7,>0100           value for side 1 in sector ID
       BL   @A43AA            format one track
A42F8  SBZ  7                 set CRU bit for side 0
       CLR  7                 >00 = value for side 0 in sector ID
       BL   @A43AA            format one track
       BL   @A45CA            send command
       DATA >A500             "step-in" (T=1, h=1, V=0, r0r1=10)
       BL   @A4482            wait for command completion
       AI   3,>0100           one more track
       CB   3,@>004D(9)       all done?
       JNE  A42E6             no: format next one
       MOV  @>004A(9),@>004A(9) check # of sides
       JEQ  A437A             single-side
       SBO  7
       LI   4,>000A           try 10 times
A4322  BL   @A4524            seek track 0
       MOV  @>004E(9),2       data buffer address
       BL   @A4614            set VDP to write
       BL   @A45CA            send command
       DATA >3F00             "read ID" (E=0)
       LI   6,>0006           read 6 bytes
       SBO  2                 enable wait states
A433A  MOVB @>5FF6,0          read data register
       INV  0                 FDC has inverted data bus
       MOVB 0,@>FFFE(15)      write it to data buffer
       MOVB @>5FF6,0          again, why write this twice ?
       INV  0
       MOVB 0,@>FFFE(15)
       DECT 6
       JNE  A433A
       BL   @A4480            SBZ 2 then wait for command completion
       SLA  0,13              check status bits
       JOC  A4398             "not found"
       JLT  A439E             "CRC error"
       SLA  0,2
       JOC  A43A4             "lost data"
       MOV  @>004E(9),2       address of data buffer
       INC  2                 skip track #
       BL   @A461E            set VDP to read from it
       CLR  0
       MOVB @>FBFE(15),0      read one byte
       JEQ  A437A             side 0
       MOVB @>004D(9),0       side 1: get tracks/side
       SLA  0,1               times two (since 2 sides)
       JMP  A4384
A437A  MOVB @A4631,@>0051(9)  error code 1
       MOVB @>004D(9),0       get # of tracks
A4384  SRL  0,8               make it a word
       MPY  @A4632,0          times # of sectors per track
       MOV  1,@>004A(9)       pass total # of sectors per disk
       MOVB @A4633,@>004D(9)  pass # of sectors per track
       B    @A4676            return
*
A4398  BL   @A4590            try again, or error >21
       DATA >2101
A439E  BL   @A4590            try again, or error >22
       DATA >2201
A43A4  BL   @A4590            try again, or error >23
       DATA >2301
*
A43AA  MOV  11,8              format a track
       MOV  @>004E(9),2       --------------
       BL   @A4614            set VDP to write to data buffer
       LI   6,>0016           write 24 sync bytes >00
       CLR  2                 sector counter
       JMP  A43C0
A43BC  LI   6,>0006           write 6 sync bytes >00
A43C0  MOVB @A4630,@>FFFE(15)
       DEC  6
       JNE  A43C0
       MOVB @A4639,@>FFFE(15) write >FE (will be ID mark)
       NOP
       MOVB 3,@>FFFE(15)      write track #
       NOP
       MOVB 7,@>FFFE(15)      write side #
       MOVB 3,0               track number
       SRL  0,8               make it a word
       SWPB 7
       MPY  @A4635(7),0       times >00 for side 1, >06 for side 0
       SWPB 7
       A    2,1               add # of sectors prepared
       DIV  @A4632,0          divide by sectors/track
       MOVB @A464F(1),@>FFFE(15) sector #, according to interlacing pattern
       LI   6,>FFEC           write 20 times
A43F8  MOVB @A464E(6),@>FFFE(15) code for a CRC
       INC  6
       JNE  A43F8             one more
       LI   0,>E5E5           data to put in empty sectors
       BL   @A4474            write it 256 times
       DATA >0100
       MOVB @A464E,@>FFFE(15) write code to CRC
       SETO 0                 >FF filler bytes
       BL   @A4474            write it 45 times
       DATA >002D
       INC  2                 # of sectors prepared
       CI   2,>0009
       JNE  A43BC             one more
       BL   @A4474            write 231 more >FF at end  of track
       DATA >00E7
 
       LI   4,>0003           try 3 times
A442C  MOVB @>004E(9),2       top of data buffer
       BL   @A461E            set VDP to read from it
       BL   @A45CA            send command
       DATA >0B00             "write track" (E=1)
       LI   6,>0CA3
       SBO  2                 enable wait states
A4440  MOVB @>FBFE(15),0      read one byte from buffer
       INV  0                 FDC has an inverted data bus
       MOVB 0,@>5FFE          send it to data register
       MOVB @>FBFE(15),0      why on earth is it done like that???
       INV  0
       MOVB 0,@>5FFE          send next byte
       DECT 6
       JGT  A4440             next pair of bytes
       BL   @A4480            SBZ 2, then wait for command completion
       SLA  0,11              check "write protect" bit
       JNC  A4464
       B    @A429A            error code >34 ??
A4464  SLA  0,4               test "lost data" bit
       JNC  A4472             ok: return
       DEC  4                 shall we try again?
       JNE  A442C             yes
       BL   @A45AC            no: error code >33
       DATA >3300
A4472  B    *8                return
 
A4474  MOV  *11+,6            VDP repeated write
A4476  MOVB 0,@>FFFE(15)      ------------------
       DEC  6                 byte in R0
       JNE  A4476             number of repeats in data word
       B    *11
*
A4480  SBZ  2                 wait for command completion
A4482  MOVB @>5FF0,0          --------------------------- get status
       INV  0                 FDC has an inverted data bus
       JLT  A4490             drive not ready
       SRC  0,9
       JOC  A4482             FDC busy: keep waiting
       B    *11
A4490  BL   @A45AC            exit with error code 6, reseting all drives
       DATA >0600
*
A4496  MOV  11,7              select a drive
       MOV  @>0058(9),2       --------------
       AI   2,>FFF6           point to drive info
       BL   @A461E            set VDP to read
       MOVB @>FBFE(15),0      get # of last drive accessed
       CLR  5                 clear flag
       CB   0,@>004C(9)       same as the one to be formated?
       JEQ  A44B2             yes
       SETO 5                 no: set flag
A44B2  CLR  0
       MOVB @>004C(9),0       get drive #
       JEQ  A451E             can't be >00: error #7
       BL   @A4614            set VDP to write, address in R2
       MOVB 0,@>FFFE(15)      modify last drive accessed
       SWPB 0
       CI   0,>0003
       JH   A451E             drive number can't be higher than 3: error #7
       LI   2,>0080
       SLA  2,0               proper drive selection bit: >01 >02 or >04
       AI   12,>0008          CRU address of drive selection bits (4-6)
       MOV  5,5               test "same drive" flag
       JEQ  A4506
       LDCR @A4505,3          deselect all drives
       AI   12,>FFFA          selection bits are echoed in CRU bits 1-3
       STCR 0,3               load CRU bits 2-4
       AI   12,>0006          back to bits 4-6
       CZC  2,0               echoed properly?
       JEQ  A4506             yes: go on
       CLR  0
       MOV  @>0058(9),2       point to drive info
       AI   2,>FFF6
       BL   @A4614            set VDP to write to address in R2
       MOVB 0,@>FFFE(15)      clear "last drive accessed"
       AI   12,>FFF8          back to CRU base
       BL   @A45AC            exit with "device error"
       BYTE >06
A4505  BYTE >00
 
A4506  LDCR 2,3               select drive
       AI   12,>FFF8          back to cru base
       MOV  5,5               test "same drive" flag
       JEQ  A451C             same: return
       LI   0,>0BB8           different: wait while drive gets ready
A4514  SRC  5,4
       SRC  5,4
       DEC  0
       JNE  A4514             keep waiting
A451C  B    *7
 
A451E  BL   @A45AC            exit with error #7
       DATA >0700
*
A4524  MOV  11,8              seek track 0
       BL   @A45CA            ------------
       DATA >F500             send "restore" command (h=1, V=0, r0r1=10)
       BL   @A4482            wait for command completion
       BL   @A4544            test if track 0 reached, error it not
       BL   @A45F0            set VDP to read "last track #"
       BL   @A4614            set VDP to write at same address
       MOVB @A4640,@>FFFE(15) set "last track #" as >FF for this drive
       B    *8
*
A4544  MOVB @>5FF0,0          check if track 0 reached
       INV  0                 ------------------------
       SLA  0,6               test the "track 0" bit
       JOC  A4552
       B    @A4490            exit with error code 6, reseting all drives
A4552  B    *11
*
A4554  AI   12,>0008          reset all drives
       LDCR @A4630,4          ---------------- no drive selected
       AI   12,>FFF8
       SBZ  1                 motor strobe
       SBO  1
       MOVB @A45BC,@>5FF8     send "Force interrupt" with no interrupt flag set
       MOV  @>0058(9),2       ptr to VIB buffer
       AI   2,>FFF6           now points to drive info buffer
       BL   @A4614            set VDP to write to address in R2
       LI   0,>0004
A457A  MOVB 0,@>FFFE(15)      write four >00 (i.e. clear drive info)
       DEC  0
       JNE  A457A
       BL   @A4480            test status, reset drives if not ready
       MOVB @A4630,@>0050(9)  no error
       B    @A4676            get return address from stack
 
A4590  DEC  4                 gracefull error
       JEQ  A45AC             --------------- no more tries: error
       MOV  *11,11            try again: get data word
       SRC  11,1              test return flag
       JNC  A459E
       B    @A4322            back to "read ID" in format routine
A459E  CI   4,>0005
       JH   A45A8
       BL   @A4524            last 5 tries: seek track 0
A45A8  B    @A40EC            back to sector r/w routine
*
A45AC  MOV  *11,0             exit with error
       MOVB 0,@>0050(9)       --------------- place err code in >8350
       CI   0,>0600           check if "device error"
       JNE  A45C6             no: exit
       BL   @A45CA            yes: reset drives
A45BC  DATA >2F00             send force interrupt, no ints
A45BE  MOVB @>5FF0,0          get status
       SRC  0,9               test "busy" flag
       JNC  A45BE             wait until done
A45C6  B    @A4676            return to caller (address from stack)
*
A45CA  MOV  *11+,0            send command to FDC from data word
       MOVB @>5FF0,6          ------------- get status
       SLA  6,1               test "ready" bit
       SBZ  1                 strobe motor
       SBO  1
       JOC  A45E4             ready (inverted)
       LI   6,>7530           wait a long time
A45DC  SRC  5,4
       SRC  5,4
       DEC  6
       JNE  A45DC
A45E4  MOVB 0,@>5FF8          send command
       SBO  3                 signal head loaded (HLT pin)
       SRC  5,8               kill time
       SRC  5,8
       B    *11
 
A45F0  CLR  0                 get last track # for this drive
       MOVB @>004C(9),0       ---------------- get drive #
       JEQ  A460E             can't be 0
       SWPB 0
       CI   0,>0003
       JH   A460E             can't be higher than 3
       MOV  @>0058(9),2
       AI   2,>FFF6           point to "last drive accessed"
       A    0,2               point to "last track" for this drive
       B    @A461E            prepare VDP to read from address in R2
 
A460E  BL   @A45AC            exit with error code 7
       DATA >0700
*
A4614  ORI  2,>4000           set VDP address to write
       ANDI 2,>7FFF           ------------------------ not to a register
       JMP  A4622
A461E  ANDI 2,>3FFF           set VDP address to read
A4622  SWPB 2                 -----------------------
       MOVB 2,*15             write address
       SWPB 2
       MOVB 2,*15
       ANDI 2,>3FFF
       B    *11
*
A4630  BYTE >00
A4631  BYTE >01
A4632  BYTE >00               sectors per track
A4633  BYTE >09               "
       BYTE >00
A4635  BYTE >06
       DATA >0003
A4638  BYTE >F0
A4639  BYTE >FE
       DATA >01F7
       DATA >FFFF
       DATA >FFFF
A4640  DATA >FFFF
       DATA >FFFF
       DATA >FFFF
       DATA >FF00
       DATA >0000
       DATA >0000
       DATA >00FB
A464E  BYTE >F7               code for CRC
A464F  BYTE 0,7,5,3,1,8,6,4   sector interlace pattern
A4657  BYTE 2
*
A4658  DECT @>0066(9)         call subroutine, return address in stack
       MOV  @>0066(9),10      ---------------
       BLWP @>005A(9)         set VDP to write to address in R10
       DATA >0143
       MOV  *11+,10           get next data word
       SWPB 11                write return address to VDP
       MOVB 11,@>FFFE(15)
       SWPB 11
       MOVB 11,@>FFFE(15)
       B    *10               branch to address in data word
*
A4676  MOV  @>0066(9),11      get return address from VDP stack
       BLWP @>005A(9)         ---------------------------------
       DATA >0162             set VDP to read from address in R11
       MOVB @>FBFE(15),11
       SWPB 11
       MOVB @>FBFE(15),11
       INCT @>0066(9)
       B    *11
 
*---------------------------------------
* Custom routines, dealing with VDP memory
* Format is >pppr where r is routine number (0-3)
* and ppp contains parameters
* The workspace it >8300. Called by BLWP @>005A(9).
*---------------------------------------
A4690  MOV  13,10             save wregs ptr
       MOV  *14+,8            get next data word
       MOV  8,9               save it
       SRL  9,4               keep parameter
       ANDI 8,>0003           four possible operations
       A    8,8               make it a word ptr
       MOV  @>001E(13),11     get old R15, i.e. VDP port (>8C02)
       MOV  @A46A8(8),8       get vector for operation
       B    *8                branch to it
 
A46A8  DATA A46B0             save registers to VDP stack
       DATA A46DC             retrieve registers
       DATA A4712             set VDP address to read
       DATA A4708             set VDP address to write
*
A46B0  AI   10,>0016       0: save registers in VDP mem
A46B4  SRL  9,1               -------------- start with R12
       JNC  A46D8             bits in >ppp tell which register to save (R0-R11)
       DECT 12                previous address in VDP stack (grows down)
       MOV  *10,8             get register contents
       SWPB 12                set VDP address to write
       MOVB 12,*11            R12 is >8366: VDP stack ptr
       SWPB 12
       ORI  12,>4000
       MOVB 12,*11
       SWPB 8                 save register to VDP mem
       MOVB 8,@>FFFE(11)
       SWPB 8
       MOVB 8,@>FFFE(11)
       MOV  9,9               more to come?
       JEQ  A4706             no:return
A46D8  DECT 10                point to previous register
       JMP  A46B4
*
A46DC  SLA  9,4            1: retrieve registers from VDP mem
A46DE  SLA  9,1               ------------------ each bit tells whether to load
       JNC  A4702             don't retrieve that one
       SWPB 12                set VDP address to read
       MOVB 12,*11            R12 is >8366: VDP stack ptr
       SWPB 12
       ANDI 12,>3FFF
       MOVB 12,*11
       NOP
       MOVB @>FBFE(11),8      get a 2-byte value from VDP
       SWPB 8
       MOVB @>FBFE(11),8
       MOV  8,*10             save it to register
       INCT 12                increment ptr (stack grows downwards)
       MOV  9,9               more to come?
       JEQ  A4706             no: return
A4702  INCT 10                next register
       JMP  A46DE
A4706  RTWP
*
A4708  A    13,9           2: set VDP for a write
       MOV  *9,8              -------------------
       ORI  8,>4000           get address from reg in >..p2 (*2)
       JMP  A471A
 
A4712  A    13,9           3: set VDP for a read
       MOV  *9,8              ------------------
       ANDI 8,>3FFF           get register from reg in >..p3 (*2)
A471A  SWPB 8                 set VDP address
       MOVB 8,*11
       SWPB 8
       MOVB 8,*11
       RTWP
 
*---------------------------------------
* Preparation subroutine
* Sets up the 4 custom subroutines
* Gets a few pointers to VDP buffers
*  >8358: copy of VIB  >8366: VDP stack ptr (grows down from drive info)
*  >8354: PAB          >8356: ptr to end-of-buffer
*---------------------------------------
A4724  INCT 7                 stop scanning upon return
A4726  MOV  11,10             save return address
       STWP 9                 get workspace (should be >83E0)
       AI   9,>FF20           top of scratch/pad mem (>8300)
       LI   0,A4690           entry to 4 custom routines
       MOV  0,@>005C(9)       put it in >835C
       MOV  9,0
       AI   0,>004E           workspace for these four (>834E)
       MOV  0,@>005A(9)       put it in >835A
 
       MOV  @>0070(9),8       highest free address in VDP mem
A4744  INCT 8                 point to "end-of-buffer" word
       BL   @A4B76            read 2 bytes from VDP address R8, into R0
       MOV  8,2               save current R8
       MOV  0,8               get end-of-buffer word
       MOVB @>FBFE(15),1      get CRU of controller that reserved this mem
       CB   12,1              same as ours?
       JNE  A4744             no: use end-of-buffer to link to next buffer
       AI   8,>FEF6           yes: point to volume information block
       MOV  8,@>0058(9)       save it in >8358
       AI   8,>FFF6           point to disk drive info (drive #, last tracks)
       MOV  8,@>0066(9)       save in >8366: VDP stack ptr (DECT before writing)
       BLWP @>005A(9)         save R7 (return address)
       DATA >0100
       MOV  @>0056(9),7       ptr to PAB: end of DSR name
       MOV  7,3               save it
       S    @>0054(9),7       beg of DSR name
       MOV  2,@>0056(9)       >8356: ptr to "end-of-buffer" word in VDP mem
       DEC  7                 point to name length byte
       CLR  2
       BLWP @>005A(9)         set VDP to read from address in R2
       DATA >00E2
       MOVB @>FBFE(15),2      get name length byte
       SWPB 2                 make it a word
       S    @>0054(9),2       minus DSR name size: lenght of .parameters
       AI   7,>FFF7           point to top of PAB
       MOV  7,@>0054(9)       save it in >8354
       B    *10
*
*
A4798  BL   @A4658            create file
       DATA A4E02             ----------- find a FDR in disk
A479E  MOV  4,4               found?
       JNE  A47AA             no
       BL   @A4658            yes: delete old file
       DATA A48DE             free file sector in VIB bitmap
       JMP  A4834             clear its FDR
 
A47AA  BL   @A4B0A            new file: insert a FDR in sector 1
       SETO 1
       BL   @A4658            call subroutine
       DATA A4EF6             find a free sector in VIB bitmap
       MOV  0,0               found?
       JNE  A47C0             yes: # in R0
       BL   @A4C72            no: update data, then return with error
       DATA >8000             "memory full"
 
A47C0  BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write sector # for FDR in sector 1
       SWPB 0
       MOVB 0,@>FFFE(15)
       SWPB 0
       MOV  @>0056(9),1       ptr to FDR in VDP buffers
       AI   1,>FFFC           ptr to sector # for FDR
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      write sector # for FDR in VDP buffer
       SWPB 0
       MOVB 0,@>FFFE(15)
       AI   1,>0003           ptr to drive #
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 6,@>FFFE(15)      write drive # before FDR in VDP buffer
       CLR  2                 code for write
       INC  1
       BL   @A4658            call subroutine
       DATA A4D36             write sector 1
       MOV  @>0058(9),5       ptr to VIB in VDP buffers
       CLR  4                 sector 0
       BL   @A4658            call subroutine
       DATA A4D4E             write VIB to sector 0
       MOV  5,3               copy filename from compare buffer to FDR
       AI   3,>0101           ptr to file compare buffer
       LI   2,>000A           10 chars per filename
A4818  BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),0      get 1 char
       INC  3                 increment source ptr
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      copy 1 char
       INC  1                 increment destination ptr
       DEC  2                 # of chars in R2
       JNE  A4818             next
A4834  MOV  @>0056(9),1       FDR ptr
       AI   1,>000A           skip filename
       LI   2,>00F6           remaining bytes in FDR
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
A4846  MOVB 2,@>FFFE(15)      write >00
       DEC  2                 clear remainder of new FDR
       JNE  A4846             next byte
       JMP  A4870             write FDR to disk return to caller
*
A4850  MOV  @>0056(9),5       check if FDR must be updated
       BLWP @>005A(9)         ---------------------------- set VDP to read
       DATA >00A2             address in R5
       MOVB @>FBFE(15),4      get filename in file ctrl block
       JLT  A4862             flag: FDR was modified, update it
       JMP  A4876
A4862  ANDI 4,>7F00           clear flag bit
       BLWP @>005A(9)         st VDP to write
       DATA >00A3             address in R5
       MOVB 4,@>FFFE(15)      write back filename without flag bit
A4870  CLR  2                 code for write
       B    @A4D40            write FDR to disk
A4876  B    @A4676            return to caller
*
A487A  BL   @A4658            update FDR + data
       DATA A489A             ----------------- update data buffer if necessary
       BL   @A4658            call subroutine
       DATA A4850             update FDR if necessary
A4886  MOV  @>0056(9),5
       CLR  6
       BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 6,@>FFFE(15)      clr first byte of filename in FDR
       B    @A4CD2
*
A489A  MOV  @>0056(9),4       check if data buffer must be updated
       DEC  4                 ------------------------------------
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),1      get drive #
       JLT  A48AE             flag: must be updated
       JMP  A48DA             no need to update: return
A48AE  ANDI 1,>7F00           erase flag
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 1,@>FFFE(15)      write back drive # without flag
       AI   4,>FFFB           point to current logical record offset
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),3      get current logical record offset
       SWPB 3
       MOVB @>FBFE(15),3
       SWPB 3
       MOV  4,7
       AI   7,>0106           point to data buffer area
       JMP  A494E
A48DA  B    @A4676            return to caller
*
A48DE  MOV  @>0056(9),2       free file sectors in VIB bitmap
       AI   2,>000C           -------------------------------
       BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),0      get file status byte from FDR
       ANDI 0,>0800           write protected?
       JEQ  A48FC             no
       BL   @A4C72            update data if needed, the return with error
       DATA >2000             "write protected"
 
A48FC  MOV  @>0056(9),8       get ptr to FDR
       AI   8,>001C           point to clusters list
       SETO 4                 previous offset
A4906  BL   @A4EB6            decode cluster info: sector in R1, offset in R2
       AI   8,>0003           next cluster ptr
       MOV  1,1
       JEQ  A492A             sector 0 = no more clusters
       MOV  2,0               total offset
       S    4,2               minus previous cluster offset = cluster size
       MOV  0,4               new "previous cluster offset"
       BL   @A4658            call subroutine
       DATA A4FC2             free sectors in bitmap (from R1, # in R2)
       MOV  8,1
       S    @>0056(9),1
       CI   1,>0100           end of FDR reached?
       JNE  A4906             not yet
A492A  B    @A4676            return to caller
*
A492E  BL   @A4B70            read a sector from offset in file
       DATA >000E             --------------------------------- get # of sectors
       C    0,3               is desired sector in file?
       JH   A493E             yes
       BL   @A4C72            no: update data, then return with error
       DATA >A000             "past end-of-file"
A493E  BL   @A4658            call subroutine
       DATA A4A4E             find sector from cluster list
       A    1,4               put sector in R4
       SETO 2                 code for read
A4948  MOV  7,5               buffer ptr
       B    @A4D4E            read/write sector
*
A494E  BLWP @>005A(9)         write sector to offset in file offset in R3
       DATA >8100             ------------------------------ save R0 and R7
       BL   @A4658            call subroutine
       DATA A4964             append enough sectors to reach that offset
       BLWP @>005A(9)         retrieve R0 and R7
       DATA >8101
       CLR  2                 code for write
       JMP  A4948             write sector
*
A4964  BL   @A4B70            append sector(s) to a file to get offset in R3
       DATA >000E             -------------------------- get # of sect from FDR
 
A496A  C    0,3               is desired sector in file?
       JH   A49FC             yes: find it and return
       MOV  0,0
       JEQ  A4974             empty file
       DEC  0                 last sector #
A4974  MOV  3,5               save desired sector offset
       MOV  0,3               last sector in file
       BL   @A4658            call subroutine
       DATA A4A4E             find sector # from offset in file
       BLWP @>005A(9)         save R1 (sector #)
       DATA >4000
       A    4,1               # of last sector in cluster
       MOV  5,4               offset of desired sector
A4988  BL   @A4658            call subroutine
       DATA A4EF6             find free sector in bitmap,  starting from R1
       MOV  0,0               found?
       JNE  A499A             yes: # in R0
       MOV  2,5               no: save # of sectors
       BL   @A4A08            update FDR
       JMP  A49D0             return with "memory full"
 
A499A  MOV  1,1
       JEQ  A49DE             empty cluster
       INC  1                 one more sector in cluster
       C    0,1               same as the one found in bitmap?
       JEQ  A49DC             yes: just increase cluster size
       BLWP @>005A(9)         no: retrieve R1 (sector #)
       DATA >4001
       BLWP @>005A(9)         save R0 + R2
       DATA >A000
       BL   @A4ED2            update current cluster info
       BLWP @>005A(9)         retrieve R0 + R2
       DATA >A001
       AI   8,>0003           ptr to next cluster info
       MOV  8,1
       S    @>0056(9),1       current FDR size
       CI   1,>0100           room enough?
       JNE  A49D4             yes
       BL   @A4658            no: call subroutine
       DATA A4FBC             free sector in bitmap
A49D0  B    @A4E28            return with "memory full"
 
A49D4  MOV  0,1               new sector #
       BLWP @>005A(9)         save R1
       DATA >4000
A49DC  JMP  A49EC             make a new cluster
 
A49DE  BLWP @>005A(9)         retrieve R1
       DATA >4001
       BLWP @>005A(9)         save R0
       DATA >8000
       SETO 2                 empty file: start from offset 0
A49EC  MOV  0,1               sector #
       INC  2                 increment cluster size
       C    2,4               enough?
       JNE  A4988             no: get one more sector
       MOV  4,5
       BL   @A4A08            add sector to FDR
       JMP  A4A04             done
 
A49FC  BL   @A4658            call subroutine
       DATA A4A4E             find a sector from offset in file
       A    1,4               last sector in cluster
A4A04  B    @A4676            return to caller
*
A4A08  MOV  11,10             add sector to FDR
       MOV  1,4               -----------------
       BLWP @>005A(9)         retrieve R1
       DATA >4001
       MOV  1,1               sector #
       JEQ  A4A4C             none: return
       BL   @A4ED2            write info for 1 cluster
       MOV  @>0056(9),2       pointer to FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),1      first char of filename
       ORI  1,>8000           flag
       BLWP @>005A(9)         set VDP to write
       DATA >0043             address in R2
       MOVB 1,@>FFFE(15)
       AI   2,>000E           ptr to # of sectors
       INC  5                 new # of sectors
       BLWP @>005A(9)         set VDP to write
       DATA >0043             address in R2
       MOVB 5,@>FFFE(15)      update # of sectors
       SWPB 5
       MOVB 5,@>FFFE(15)
A4A4C  B    *10
*
A4A4E  MOV  @>0056(9),8       find sector from offset in file
       AI   8,>001C           ------------------------------- cluster list
       MOV  3,4               desired sector offset is in R3
A4A58  BL   @A4EB6            decode info: sector in R1, offset in R2
       C    2,3               reached yet?
       JLT  A4A62             no
       JMP  A4A6E             yes: return
A4A62  AI   8,>0003           point to next cluster info
       MOV  3,4
       S    2,4
       DEC  4                 size of the desired cluster (if it's the next)
       JMP  A4A58             keep trying
A4A6E  B    @A4676            return to caller
*
*---------------------------------
* Opcode 7: Delete
* ----------------
* PAB 0: >07
*     1:            <--- error code
*   2-3:
*     4:
*     5:
*   6-7:
*     8:
*---------------------------------
A4A72  BL   @A4658            delete file
       DATA A4DA4             ----------- find file FDR in VDP buffers
       MOV  4,4               found?
       JEQ  A4A8A             yes
       BL   @A4658            no: call subroutine
       DATA A4E0C             find FDR on disk
       MOV  4,4               found?
       JEQ  A4AAC             yes
       B    @A4676            no: return to caller
 
A4A8A  INC  1                 FDR found, point to it
       MOV  1,@>0056(9)       save it for other routines
       BL   @A4658            call subroutine
       DATA A4D34             read sector 1
       BL   @A4B70            read 2 bytes from VDP at >8356+offset
       DATA >FFFC             i.e. get sector # of FRD in R0
       MOV  0,3               save it for later
       MOV  5,8               ptr to top of sector 1
A4AA0  BL   @A4B76            read 2 bytes from VDP at R8 into R0
       INCT 8                 next FDR ptr in sector 1
       C    0,3               is this the one we want?
       JNE  A4AA0             not yet
       DECT 8                 yes: point back to it
A4AAC  BLWP @>005A(9)         save R8
       DATA >0080
       BL   @A4658            call subroutine
       DATA A48DE             free file sectors in VIB bitmap
       BLWP @>005A(9)         retrieve R8
       DATA >0081
       BL   @A4ADA            remove FDR ptr from sector 1
       CLR  2                 code for write
       BL   @A4658            call subroutine
       DATA A4D36             write sector 1
       BL   @A4B70            get 2 bytes from VDP at >8356+offset in R0
       DATA >FFFC             i.e. sector # of FDR
       BL   @A4658            call subroutine
       DATA A4FBC             free sector in R0 in VIB bitmap
       B    @A4886            clear 1rst byte of filename in VDP
*
* Sector 1 contains an alphabetically sorted list of FDR pointers
* Each pointer is 2 bytes long and contains the sector # of this FDR
* The list must end with a >0000 mark. Thus there can be 127 files at most
*
A4ADA  MOV  @>0056(9),5       remove FDR ptr from sector 1
       AI   5,>0100           ----------------------------
       MOV  5,3               pointer to data buffer
       AI   3,>0100           point to next ctrl block
       MOV  8,2               shift up FDR list, erasing FDR pointed by R8
       INCT 2                 point to next FDR ptr in sector 1
A4AEC  BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),0      get 1 byte
       INC  2                 inc source ptr
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      copy 1 byte
       INC  8                 inc dest pointer
       C    2,3               done?
       JNE  A4AEC             not yet
       B    *11
*
A4B0A  MOV  11,10             insert a FDR in sector 1
       MOV  8,1               ------------------------
       BL   @A4B70            get 2 bytes from VDP at >8356+offset
       DATA >01FC             i.e. last FDR slot in sector 1 (list ends with 0)
       MOV  0,0
       JEQ  A4B1C
       B    @A4E28            "memory full" error
A4B1C  DEC  8                 previous byte
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),0      get 1 byte
       INCT 8
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      copy byte two bytes further down
       DECT 8
       C    8,1               done ?
       JNE  A4B1C             not yet
       B    *10
*
A4B3C  MOV  @>0058(9),2       compare filenames
       AI   2,>0100           -----------------
A4B44  BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R1 (ptr to filename)
       MOVB @>FBFE(15),0      get 1 char
       ANDI 0,>7FFF           clear flag (on drive #)
       BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2 (filename compare buffer)
       MOVB @>FBFE(15),3      get 1 char
       CB   0,3               compare chars
       JNE  A4B68             mismatch
       INC  1                 match: increment pointers
       INC  2
       DEC  4
       JNE  A4B44             next char
A4B68  B    *11               if complete match: ret with EQ set
*
A4B6A  MOV  @>0054(9),8       get two bytes from PAB
       JMP  A4B74             ----------------------
 
A4B70  MOV  @>0056(9),8       get two bytes from FDR
A4B74  A    *11+,8            ---------------------- offset in data word
 
A4B76  BLWP @>005A(9)         get two byte from VDP at R8
       DATA >0102             --------------------------- set VDP to read at R8
       MOVB @>FBFE(15),0      get two bytes of data
       SWPB 0
       MOVB @>FBFE(15),0
       SRC  0,8               why not swpb ?
       B    *11
 
A4B8A  MOV  @>0058(9),1       find disk from name (ptr in R3)
       AI   1,>0100           -------------------
       BL   @A4C14            copy filename from VDP at R3 to compare buffer
       BLWP @>005A(9)         save R2 + R3
       DATA >3000
       MOV  0,0               last char copied
       JLT  A4BA2             flagged
       JMP  A4BAC
A4BA2  MOV  0,6
       ANDI 6,>0300
       JEQ  A4C18             return with "file error"
       JMP  A4C0A             return to caller
A4BAC  CLR  6                 don't read any drive
       BL   @A4658            call subroutine
       DATA A4CD2             save current VIB
A4BB4  AI   6,>0100           next drive
       SETO 7                 error flags
       SETO 2                 code for read
       CLR  4                 sector 0
       BL   @A4658            call subroutine
       DATA A4D50             read sector 0
       MOV  7,7               ok?
       JNE  A4C02             no: try next drive
       LI   4,>000A           yes: diskname size
       MOV  @>0058(9),1       VIB ptr
       BLWP @>005A(9)         save R1-R3
       DATA >7000
       BL   @A4B3C            compare names (ptr in R1 + compare buffer)
       BLWP @>005A(9)
       DATA >7001             retrieve R1-R3
       MOV  4,4               name matched?
       JNE  A4C02             no: try next drive
       MOV  6,0               drive #
       ORI  0,>8000           add "update" flag
       BLWP @>005A(9)         set VDP to write
       DATA >0063             address in R3
       MOVB 0,@>FFFE(15)      copy drive+flag before diskname in source
       DEC  5                 before sector 0 copy
       BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 6,@>FFFE(15)      copy drive # before VIB
       JMP  A4C0A             done
 
A4C02  CI   6,>0300           did we do all drives?
       JNE  A4BB4             no: try next on
       JMP  A4C18             return with "file error"
 
A4C0A  BLWP @>005A(9)         retrieve R2 + R3
       DATA >3001
       B    @A4676            return to caller
*
A4C14  DEC  2
       JH   A4C1E
A4C18  BL   @A4C9E            return with error
       DATA >E000             "file error"
 
A4C1E  LI   0,>2000           copy (+check) filename in VDP from R3 to R1
       BLWP @>005A(9)         ---------------------- set VDP to write
       DATA >0023             address in R1
       LI   8,>000A           10 chars per filename
A4C2C  MOVB 0,@>FFFE(15)      fill filename with spaces
       DEC  8
       JNE  A4C2C
       LI   8,>000B           11 chars countring drive #
A4C38  INC  3                 increment source ptr
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),0      get a char
       JEQ  A4C18             >00: return with "file error"
       JLT  A4C68             flag bit set
       CI   0,>2E00
       JEQ  A4C68             '.'
       DEC  8
       JEQ  A4C18             name to long: return with "file error"
       CI   0,>2000
       JEQ  A4C18             name can't contain spaces: "file error" again
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      copy 1 char
       INC  1                 increment destination pointer
       DEC  2                 more?
       JNE  A4C38             yes
A4C68  CI   8,>000B           name can't be 0 chars long
       JEQ  A4C18             else return with "file error"
       B    *11
 
A4C70  DATA >AA00
 
A4C72  MOV  11,0              update data, then error
       MOV  @>0056(9),3       -----------------------
       DEC  3                 see what >8356 is pointing at
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),2      get 1 byte
       CB   2,@A4C70          is it >AA (disk buffer area mark)
       JEQ  A4C9C             yes: announce error (code in data word)
       BLWP @>005A(9)         no: >8356 points to a FDR. Save R0
       DATA >8000
       BL   @A4658            call subroutine
       DATA A487A             update FRD and data buffer if needed
       BLWP @>005A(9)         retrieve R0
       DATA >8001
A4C9C  MOV  0,11
 
A4C9E  MOV  @>0054(9),1       annouce error
       JEQ  A4CBE             ------------- no PAB
       INC  1                 for DSRs: ptr to status byte
       BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R2
       MOVB @>FBFE(15),2      get file status byte
       SOC  *11+,2            add error code
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R2
       MOVB 2,@>FFFE(15)      write back status byte
       JMP  A4CC2
A4CBE  MOV  *11+,@>0050(9)    for subs: error code in >8350
A4CC2  MOV  @>0058(9),8       get stack ptr
       AI   8,-12             point back to initial caller
       MOV  8,@>0066(9)       update pointer
       B    @A4676            return to caller
*
A4CD2  BLWP @>005A(9)         read VIB (drive # in R6)
       DATA >3000             -------- save R2 + R3
       MOV  @>0058(9),5       pointer to VIB in ctrl block
       DEC  5                 ptr to drive #
       BLWP @>005A(9)         set VDP for read
       DATA >00A2             address in R5
       MOVB @>FBFE(15),2      get drive #
       MOV  2,3
       CLR  4                 sector 0 for VIB
       ANDI 2,>0300           clear flag (>80 = update data)
       CB   2,6               wanted drive?
       JEQ  A4D28             yes: return
       MOV  3,3               no: shall we update VIB?
       JLT  A4CFA             yes
       JMP  A4D0E             no
A4CFA  BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 4,@>FFFE(15)      clr drive #
       INC  5                 point back to VIB buffer
       BL   @A4658            call subroutine
       DATA A4D52             write sector 0 to old drive (in R2)
       DEC  5                 point to drive #
A4D0E  SETO 2                 flag for read
       MOVB 6,2               add wanted drive
       JEQ  A4D1E             none
       INC  5                 point at VIB buffer
       BL   @A4658            call subroutine
       DATA A4D50             read sector (in R4) to buffer (in R5)
       DEC  5                 point at drive #
A4D1E  BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 6,@>FFFE(15)      write drive # in control block, before FDR
A4D28  INC  5                 point back to FDR
       BLWP @>005A(9)
       DATA >3001             retrieve R2 + R3 from stack
       B    @A4676            branch to address on stack
*
A4D34  SETO 2                 read sector 1
A4D36  LI   4,>0001           -------------
       LI   5,>0100           into data buffer area of current ctrl block
       JMP  A4D4A
 
A4D40  BL   @A4B70            read FDR
       DATA >FFFC             -------- get sector # of FDR from control block
 
A4D46  MOV  0,4               sector read/write
       CLR  5                 -----------------
A4D4A  A    @>0056(9),5       point to FDR or data buffer
A4D4E  CLR  7
A4D50  MOVB 6,2               add drive # for r/w flag
A4D52  BLWP @>005A(9)         save R0-R8
       DATA >FF80
       MOV  4,@>004A(9)       sector #
       MOV  2,@>004C(9)       drive | r/w flag
       MOV  5,@>004E(9)       buffer ptr
       BL   @A4658            call subroutine
       DATA A40E8             sector read/write
       BLWP @>005A(9)         retrieve R0-R8
       DATA >FF81
       MOVB @>0050(9),7       get error code | flags
       SWPB 7
       JEQ  A4D9C
       MOV  7,7
       JGT  A4D7E
       JMP  A4D94
A4D7E  ANDI 7,>00FF
       CI   7,>0034
       JNE  A4D8E
       BL   @A4C72
       DATA >2000             "write protected"
A4D8E  BL   @A4C72
       DATA >C000             "device error"
A4D94  MOVB @>004D(9),@>004D(9) read or write?
       JEQ  A4D7E             write
A4D9C  ANDI 7,>00FF
       B    @A4676            return to caller
*
A4DA4  MOV  @>0058(9),1       save filename in compare buffer and find its FDR
       AI   1,>0100           ------------------------------------------------
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1: filename compare buffer
       MOVB 6,@>FFFE(15)      write drive #
       INC  1
       BL   @A4C14            copy (+ check) filename from R3 to R1
       MOV  2,2               all chars copied (or was there a "." or a >00 ?)
       JEQ  A4DC4
A4DC0  B    @A4C18            return with "file error"
*
A4DC4  MOV  @>0056(9),1       find filename in buffered FDRs
       AI   1,>0003           ------------------------------
       BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R1
       MOVB @>FBFE(15),2      get # of files
       SRL  2,8               make it a word
       MOV  2,3               save it
       AI   1,>0006           ptr to drive #
A4DDE  LI   4,>000B           compare 11 bytes (drive + filename)
       BLWP @>005A(9)         save R1-R3
       DATA >7000
       BL   @A4B3C            compare with name in compare buffer
       BLWP @>005A(9)         retrieve R1-R3
       DATA >7001
       MOV  4,4               fully compared?
       JEQ  A4DFE             yes: done
       AI   1,>0206           move to next FDR in VDP mem
       DEC  2
       JNE  A4DDE             next file
A4DFE  B    @A4676            return to caller (R4=0 if successfull)
*
A4E02  BL   @A4658
       DATA A4DA4             save name in comp buffer, find FDR in VDP buffers
 
A4E08  MOV  4,4               find FDR on disk (from filename)
       JEQ  A4DC0             ----------------  "file error"
A4E0C  MOV  @>0056(9),5       ptr to top of disk buffer in VDP mem
       AI   5,>000A           ptr to drive # in first file control block
A4E14  BLWP @>005A(9)         set VDP to read
       DATA >00A2             address in R5
       MOVB @>FBFE(15),2      get drive #
       JEQ  A4E2E             free control block found
       AI   5,>0206           ptr to  file control block
       DEC  3
       JNE  A4E14             more files ?
A4E28  BL   @A4C72            no:
       DATA >8000             "memory full"
 
A4E2E  MOV  5,@>0056(9)       save ptr to free ctrl block (drive #)
       BL   @A4658            call subroutine
       DATA A4D34             read sector 1
A4E38  MOV  @>0056(9),8       entry point if sector 1 already read
       AI   8,>017E           point to middle of sector 1
       LI   2,>0040           distance: start with 1/4 sector
A4E44  SETO 4
       BL   @A4B76            read 2 bytes in R0 from VDP address in R8
       MOV  0,0
       JEQ  A4EAA             no file here: move up
       BLWP @>005A(9)         save R2
       DATA >2000
       SETO 2                 code for read
       BL   @A4658            call subroutine
       DATA A4D46             read FDR, sector # in R0
       MOV  5,1               A4D46 sets R5 as FDR ptr
       AI   5,>FFFC           point to "sector # of FDR" in ctrl block
       BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 4,@>FFFE(15)      A4D46 puts sector # in R4
       SWPB 4                 copy it to ctrl block
       MOVB 4,@>FFFE(15)
       MOV  1,5               FDR ptr
       DEC  1                 now point to drive #
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 6,@>FFFE(15)      save drive #
       LI   4,>000B           size to compare (drive # + filename)
       BL   @A4B3C            compare filenames
       BLWP @>005A(9)         retrieve R2
       DATA >2001
       JEQ  A4EA6             compared ok: return
       BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 4,@>FFFE(15)      remaining chars to compare
       C    0,3               what kind of mismatch occured?
       JH   A4EAA             too far down the alphabet
       A    2,8               too far up: move half-way down
       MOV  2,2
       JNE  A4EB0             then divide distance by 2
       INCT 8                 already checked: reset EQ
A4EA6  B    @A4676            return (from stack)
 
A4EAA  S    2,8               move half-way up
       MOV  2,2
       JEQ  A4EA6             can't: already checked
A4EB0  SRL  2,2               divide distance by 2
       A    2,2               but keep it even
       JMP  A4E44
*
* The cluster info list is located in the FDR, bytes >1C to >FF
* A cluster info consists in 3 bytes, i.e 6 nibbles
* 3 nibbles specify the beginning sector for that cluster, and
* 3 nibbles specify the total file offset in sectors, including this cluster.
* The nibbles are arranged as EG SB OF, to be combined as BEG OFS
*
A4EB6  MOV  11,10             decode cluster info
       BL   @A4B76            ------------------- read 2 bytes VDP at R8 in R0
       SWPB 0
       MOVB @>FBFE(15),2      get third byte from cluster list
       MOV  0,1
       ANDI 1,>0FFF           start sector in R1
       SZC  1,0               remove it from R0
       SRL  2,8
       SOC  0,2               combine offset nibbles
       SRC  2,12              offset in R2
       B    *10
*
A4ED2  SRC  2,4               write info for 1 cluster
       MOV  2,0               ------------------------
       ANDI 0,>F000           sector in R1, offset in R2
       SOC  0,1               copy nibble 3 of offset before nibble 1 of sector
A4EDC  BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       SWPB 1                 write cluster info
       MOVB 1,@>FFFE(15)      as 3 bytes
       SWPB 1
       MOVB 1,@>FFFE(15)
       SWPB 2
       MOVB 2,@>FFFE(15)
       B    *11
*
* The sector bitmap is located in the VIB (i.e. sector 0) at bytes >38 to >FF
* In each byte a bit defines a sector, from right to left: "0"=free, "1"=used
*
A4EF6  BLWP @>005A(9)         find a free sector in bitmap
       DATA >7800             ----------------------------
       BL   @A4658            call subroutine
       DATA A4CD2             load VIB for drive in R6
       MOV  1,1               first sector specified in R1 ?
       JNE  A4F0A             yes
       LI   1,>0021           no: start with sector 34
A4F0A  INC  1
       MOV  1,0
       SRL  1,3               div by 8 since 8 sect/byte in bitmap
       LI   2,>00FF
       ANDI 0,>0007           bit number in bitmap byte
       JEQ  A4F1C
       SLA  2,0               get that bit
A4F1C  MOV  1,3               byte #
       A    5,3               add VIB ptr
       AI   3,>0038           ptr to sector in bitmap
       CI   1,>00C8           end of VIB?
       JLT  A4F2C             no
       CLR  1                 yes: top of bitmap
A4F2C  A    5,1
       AI   1,>0038           make another bitmap ptr
       BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R1
A4F38  SETO 0
       MOVB @>FBFE(15),0      get bitmap byte
       MOV  0,4               save it
       SOC  2,0               mask previous sectors
       CLR  2
       INC  0                 get 1 more sector
       JNE  A4F68             ok
       INC  1                 byte full: try next
       MOV  1,0
       AI   0,>FF00           won't change if byte # became >100
       C    0,5               still in VIB?
       JNE  A4F5E             yes
       AI   1,>FF38           no: to top of bitmap
       BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R1
A4F5E  C    1,3               are we back to where we started?
       JNE  A4F38             no: seach that byte for a free sector
       MOV  4,0               get original byte
       INC  0                 try sectors just before ours (no mask this time)
       JEQ  A4FB2             full: return with EQ
A4F68  DEC  0                 restore original byte
       MOV  0,2
       CLR  0                 bit counter
       SWPB 2
A4F70  INC  0                 increment bit count
       SRC  2,1               find first "0" bit from the right
       JOC  A4F70             not yet
       LI   2,>0080
       SLA  2,0               make a mask for that bit
       DEC  0                 bit # (0-7)
       SOC  2,4               mark sector as used in bitmap byte
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 4,@>FFFE(15)      update bitmap
       AI   1,>FFC8
       S    5,1               byte # in bitmap
       SLA  1,3               times 8 (8 sect per byte)
       SOC  0,1               add bit #: = sector #
       MOV  1,0               save it
 
A4F96  DEC  5                 point to drive #
       BLWP @>005A(9)         set VDP to read
       DATA >00A2             address in R5
       MOVB @>FBFE(15),1      get drive #
       ORI  1,>8000           add flag: update VIB
       BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 1,@>FFFE(15)      write back flagged drive #
       INC  5                 point to VIB (& return with NEQ)
A4FB2  BLWP @>005A(9)         retrieve R1-R4
       DATA >7801
       B    @A4676            return to caller
*
A4FBC  MOV  0,1               free sector(s) in bitmap
       LI   2,>0001           ------------------------ 1 sector only
A4FC2  BLWP @>005A(9)         entry point if more than 1 sector
       DATA >7800             save R1-R4
       BL   @A4658            call subroutine
       DATA A4CD2             load VIB for drive in R6
       MOV  1,0               sector #
       ANDI 0,>0007           bit in bitmap byte (8 per byte)
       SRL  1,3               byte in bitmap
       A    5,1               add VIB buffer
       AI   1,>0038           add bitmap offset in VIB
       MOV  0,3
       NEG  0
       AI   0,>0008           change 0-7 into 8-1
       LI   4,>00FF           mask to erase
       C    2,0               how many to erase?
       JLT  A4FEE             less than in that byte
       JMP  A5004
 
A4FEE  LI   0,>0008           free sectors in first byte
       S    2,0
       SRC  4,0               adjust mask
       MOV  3,0               original bit # of starting sector
       JEQ  A4FFC
       SLA  4,0               don't erase before starting sector
A4FFC  JMP  A5000
 
A4FFE  SRL  9,3               what the heck is that???
 
A5000  SWPB 4
       JMP  A5036             goto erase last byte
 
A5004  SRC  4,0               adjust mask
A5006  S    0,2               that many will be freed
       BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R1
       MOVB @>FBFE(15),0      get bitmap byte
       SZC  4,0               mark sectors as free
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      write it back
       LI   4,>FF00           clear full byte
       INC  1                 next byte
       LI   0,>0008           i.e. 8 sectors
       C    2,0               how many more setors?
       JLT  A502E             less than 8
       JMP  A5006             8 or more: next byte
 
A502E  MOV  2,0               remaining sectors
       LI   4,>00FF
       SLA  4,0               coin mask
A5036  BLWP @>005A(9)         set VDP to read
       DATA >0022             address in R1
       MOVB @>FBFE(15),0      get bitmap byte
       SZC  4,0               mark sectors as free
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      write it back
       JMP  A4F96             done: flag drive # and return
*
*===================================
* DSR entry points
*===================================
A504E  MOV  11,7              DSK
       BL   @A4724            --- prepare file operations
       BL   @A4658            call subroutine
       DATA A4B8A             find disk in drive (name ptr in R3)
       JMP  A5072
 
A505C  LI   6,>0100           DSK1
       JMP  A506C             ----
 
A5062  LI   6,>0200           DSK2
       JMP  A506C             ----
 
A5068  LI   6,>0300           DSK3
*                             ----
A506C  MOV  11,7              save return address
       BL   @A4724            prepare file operations
A5072  MOV  @>0054(9),0       PAB ptr
       BLWP @>005A(9)         set VDP to  read
       DATA >0002             address in R0
       MOVB @>FBFE(15),1      get opcode
       SRL  1,8
       CI   1,>0009           check range
       JH   A50BA             illegal opcode
       CI   2,>0001           filename lenght (including . )
       JNE  A5098             no filename: dir
       AI   1,>000A           only allow open, close and read
       CI   1,>000C
       JH   A50BA             others are illegal
A5098  A    1,1               make it a word ptr
       MOV  @A50A0(1),1       get vector
       B    *1                branch to it
*
A50A0  DATA A50C0             open
       DATA A52D2             close
       DATA A52DC             read
       DATA A53C6             write
       DATA A567A             rewind
       DATA A56CE             load
       DATA A5770             save
       DATA A4A72             delete
       DATA A4C9E             scratch record: return with "bad attribute" error
       DATA A57F4             status
 
       DATA A58B4             open directory
       DATA A5912             close directory
       DATA A5928             read directory
*
A50BA  BL   @A4C72            return with error
       DATA >6000             "illegal opcode"
*---------------------------------
* Opcode 0: Open
* --------------
* PAB 0: >00
*     1: file type  <--- error code
*   2-3:
*     4: record length
*     5:
*   6-7: # of records (if output)
*     8:
*---------------------------------
A50C0  CLR  0
       MOVB @>FBFE(15),0      get file attributes
       BLWP @>005A(9)
       DATA >8000             save R0
       ANDI 0,>1600           keep fix/var and access mode
       CI   0,>0600
       JNE  A50DC
A50D6  BL   @A4C72            dis/fix, open as append: return with error
       DATA >4000             "bad attribute"
 
A50DC  JLE  A50F2
       MOV  0,1               var
       BL   @A4B6A            get 2 bytes from PAB into R0
       DATA >0004             rec len and char count
       CI   0,>FF00           is rec len 255?
       JHE  A50D6             yes: bad attribute
       MOV  1,0               retrieve attributes
       ANDI 0,>0600           keep only access mode
 
A50F2  CI   0,>0200           is it output?
       JNE  A51A6             no
       BL   @A4658            call subroutine
       DATA A4798             create file
A50FE  BL   @A5280            coin status byte in FDR style
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4: status byte in FDR buffer
       MOVB 2,@>FFFE(15)      write file status in FDR
       MOV  @>0054(9),3       PAB ptr
       AI   3,>0004           ptr to rec len
       CLR  5
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),5      get record length
       JNE  A5130
       LI   5,>5000           >00: default it 80
       BLWP @>005A(9)         set VDP to write
       DATA >0063             address in R3
       MOVB 5,@>FFFE(15)      write default rec len
A5130  AI   4,>0005           point to rec len byte in FDR
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 5,@>FFFE(15)      write rec len in FDR buffer
       LI   1,>0100           256 bytes/sector
       MOV  2,2               var or dis?
       JLT  A5148             var
       JMP  A514C             dis
A5148  A    1,5               var: rec len +1
       DEC  1                 254 bytes only (needs size byte)
A514C  SWPB 5                 make it a word
       CLR  0
       DIV  5,0               how many times in 254/255 bytes?
       AI   4,>FFFC           point to # of rec/sect in FDR
       MOV  0,1               save result for later
       SWPB 0
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 0,@>FFFE(15)      write # of rec/sect in FDR
       MOV  @>0056(9),8       point to filename in FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),0      get first char
       ORI  0,>8000           flag it: update FDR before leaving
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write it back
       BLWP @>005A(9)
       DATA >8001             retrieve R0 (access mode)
       BL   @A4B6A            get 2 bytes from PAB into R0
       DATA >0006             required size in records
       MOV  0,4
       JEQ  A51A2             no size specified
       JLT  A50D6             return with "bad attribute" error
       A    1,4               round up to record size
       DEC  4
       CLR  3
       DIV  1,3               how many sectors will this be?
       DEC  3                 offset start from 0
       BL   @A4658            call subroutine
       DATA A4964             add sectors to FDR to match offset in R3
A51A2  B    @A56A8            initialise file control block and return to caller
 
A51A6  BLWP @>005A(9)         not output
       DATA >8000             save R0
       BL   @A4658            call subroutine
       DATA A4E02             find FDR on disk
       BLWP @>005A(9)
       DATA >8001             retrieve R0 (access mode)
       MOV  4,4               found FDR?
       JEQ  A51CE             yes
       CI   0,>0400           no: is file open as input?
       JEQ  A51CA             yes: must exist
       BL   @A4658            no: call subroutine
       DATA A47AA             create file
       JMP  A50FE
 
A51CA  B    @A50D6            return with "bad attribute" error
 
A51CE  MOV  0,7               save access mode
       BL   @A5280            prepare status byte for FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4 (status byte in FDR)
       MOVB @>FBFE(15),0      get current file status
       MOV  0,3               save it
       ANDI 3,>0800           is file write protected?
       JEQ  A51F2             no
       CI   7,>0400           yes: is it open as input?
       JEQ  A51F2             no
       BL   @A4C72            yes: return with error
       DATA >2000             "write protected"
 
A51F2  ANDI 0,>8300           keep only file type bits (V/F, D/I, Prg/Data)
       XOR  2,0               compare with new (coined by A5280)
       JNE  A51CA             different: bad attribute
       MOV  @>0054(9),3       PAB ptr
       AI   3,>0004           ptr to rec len in PAB
       AI   4,>0005           ptr to rec len in FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),0      get rec len from FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),2      get rec len from PAB
       JEQ  A5220             0 = keep current one
       CB   0,2               are they identical?
       JNE  A51CA             no: "bad attribute"
A5220  BLWP @>005A(9)         set VDP to write
       DATA >0063             address in R3
       MOVB 0,@>FFFE(15)      update rec len in PAB (in case it was 0)
       BLWP @>005A(9)         retrieve R0 (open mode)
       DATA >8001
       ANDI 0,>0600           keep only access mode
       CLR  2
       SETO 3
       CI   0,>0600           is it "append"
       JNE  A5278             no
       MOV  @>0056(9),4       yes: get FDR ptr
       MOV  4,7               save it
       AI   4,>000E           ptr to # of sectors
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),3      get # of sectors in file
       SWPB 3
       MOVB @>FBFE(15),3
       SWPB 3
       MOVB @>FBFE(15),2      get eof offset
       DEC  3                 offset starts from 0
       JLT  A5278             file is empty (0 sectors)
       BLWP @>005A(9)
       DATA >3000             save R2 + R3
       AI   7,>0100           ptr to data buffer area for this file
       BL   @A4658            call subroutine
       DATA A492E             read a sector, from offset in R3
       BLWP @>005A(9)
       DATA >3001             retrieve R2 + R3
A5278  BL   @A52AA            update current record offset in file ctrl block
       B    @A4676            return to caller
*
A5280  BLWP @>005A(9)         prepare file status byte for FDR
       DATA >8001             -------------------------------- access mode in R0
       BLWP @>005A(9)
       DATA >8000             save it back
       LI   2,>0002           "int" in FDR status byte
       MOV  @>0056(9),4       FDR pointer
       SLA  0,4               fix or var?
       JNC  A529E             fix
       LI   2,>0082           "int var" in FDR
       MOV  0,0               dis or int?
A529E  JLT  A52A2             int
       DECT 2                 dis: remove the "int" from FDR status
A52A2  AI   4,>000C           point at file status byte in FDR
       SWPB 2
       B    *11
*
A52AA  MOV  @>0056(9),4       update sect + rec offsets in file control block
       AI   4,>FFFA           -----------------------------------------------
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 3,@>FFFE(15)      write current sect offset
       SWPB 3
       MOVB 3,@>FFFE(15)
       AI   4,>0004           point to logical rec offset (for var files)
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 2,@>FFFE(15)      write record offset
       B    *11
*
*----------------------------------
* Opcode 1: Close
* --------------
* PAB 0: >01
*     1:           <--- error code
*   2-3:
*     4:
*     5:
*   6-7:
*     8:
*----------------------------------
A52D2  BL   @A4658            call subroutine
       DATA A54D0             find file FDR
       B    @A487A            update FDR + data area, get VIB, return to caller
*
*----------------------------------
* Opcode 2: Read
* --------------
* PAB 0: >02
*     1: file type <--- error code
*   2-3: data buffer address in VDP mem
*     4:
*     5: bytes read
*   6-7: record #
*     8:
*
* Logical records organisation whithin sectors
*
* Fixed records (e.g. rec length = 6)
* 11 11 11 11 11 11 22 22 22 22 22 22 33 33 33 33 33 33 xx xx xx
* Where 11=data for record 1, 22=record 2, 33=record 3, xx=junk bytes
*
* Variable records:
* sz 11 11 11 11 11 11 11 sz 22 22 22 22 22 sz 33 33 FF xx xx xx
* Where sz=record size, 11,22,33=record data, FF=end-of-sector mark, xx=junk
*----------------------------------
*
A52DC  BL   @A4658            call subroutine
       DATA A54D0             find FDR in VDP buffers, get status from PAB
       ANDI 0,>0200           what type of access?
       JEQ  A52EC             "update" or "input": ok
A52E8  B    @A50BA            "append" or "output": error "illegal opcode"
A52EC  BL   @A54FC            get status byte in R0, from FDR
       JLT  A5306             var
       BL   @A5510            fix: get rec # compare to # of recs/file
       JL   A52FE             ok: in file
A52F8  BL   @A4C72            update data and return with error
       DATA >A000             "eof reached"
A52FE  BL   @A4658            call subroutine
       DATA A5576             load record from disk into FDR data buffer area
       JMP  A5328
 
A5306  BL   @A4658            var: call subroutine
       DATA A5362             load proper sector, point to rec in it
       JMP  A52F8             skipped if ok: return with "eof reached"
 
       INC  2                 next byte in data buffer
       A    4,0               add rec size to offset
       INC  0                 room for end-of-sector mark
       MOV  @>0056(9),5       FDR ptr
       DECT 5                 point to var record offset in sector
       SWPB 0
       BLWP @>005A(9)         set VDP to write
       DATA >00A3             address in R5
       MOVB 0,@>FFFE(15)      update var record offset in sector
       MOV  4,0               save # of bytes to be read
A5328  MOV  @>0054(9),4       PAB ptr
       AI   4,>0005           point to char count
       SWPB 0
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 0,@>FFFE(15)      write # of char to be read
       SWPB 0                 make it a word
 
A533E  MOV  0,0               check it
       JEQ  A535E             none: return
A5342  BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),3      read 1 byte from FDR data buffer area
       INC  2                 increment source ptr
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 3,@>FFFE(15)      write the byte in PAB data buffer
       INC  1                 increment destination ptr
       DEC  0                 more to read?
       JNE  A5342             yes
A535E  B    @A4676            return to caller
*
A5362  BL   @A5650            load sector, point to record in it
       MOV  3,3               ----------------------------------- sector offset
       JLT  A536C             -1: top of file
       JMP  A5390             in file
A536C  MOV  3,0
       INC  0                 next sector
       C    0,2               compare to # of sect/file
       JEQ  A535E             end-of-file reached: return to caller (JMP to err)
       BL   @A4658            call subroutine
       DATA A489A             update data buffer, if needed
       MOV  0,3               desired offset
       CLR  5
       BL   @A55EE            update sect + rec offsets in control block
       AI   7,>0100           point to data buffer area (R7 set by A55EE)
       BL   @A4658            call subroutine
       DATA A492E             read a sector, from offset in file (in R3)
       CLR  0
       JMP  A5398
 
A5390  MOV  0,0               in file: test var rec offset (from A5650)
       JNE  A5398             inside sector
       C    0,2               at beg of sector
       JEQ  A535E             file is empty: return
A5398  MOV  0,2               FDR data buffer will be added to R2 by A55CA
       BL   @A4658            call subroutine
       DATA A55CA             R2=byte in FDR data buf, R1=top of PAB data buf
       BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),4      get first byte (rec length)
       SRL  4,8               make it a word
       MOV  0,0               var rec offset
       JEQ  A53BC
       CI   4,>00FF           is it >FF (end of sector mark) ?
       JNE  A53BC             no
       BL   @A5650            yes: get sect + rec offsets from control block
       JMP  A536C             try again with next sector
 
A53BC  BLWP @>005A(9)
       DATA >0011             retrieve return address from stack in R11
       INCT 11                skip the JMP to "eof reached" error
       B    *11
*
*------------------------------------
* Opcode 3: Write
* --------------
* PAB 0: >03
*     1: file type <--- error code
*   2-3: data buffer address in VDP mem
*     4:
*     5: bytes to write
*   6-7: record #
*     8:
*------------------------------------
A53C6  BL   @A4658            call subroutine
       DATA A54D0             find FDR in VDP buffers
       ANDI 0,>0600           keep only access mode
       CI   0,>0400           is it "input"
       JEQ  A52E8             yes: return with error "illegal opcode"
       BL   @A54FC            get file status byte from FDR
       JLT  A5402             var
 
       BL   @A5510            fix: get rec # from PAB, sect # in R0
       JL   A53FA             less that total rec/file
       BLWP @>005A(9)         past eof: expand file
       DATA >D800             save R0, R1, R3, R4
       MOV  0,3               desired sector offset
       BL   @A4658            call subroutine
       DATA A4964             append enough sectors to reach offset in R3
       BLWP @>005A(9)
       DATA >D801             restore R0, R1, R3, R4
       BL   @A561A            update # of rec/file in FDR
 
A53FA  BL   @A4658            in file: call subroutine
       DATA A5576             fetch rec from disk into FDR data buffer area
       JMP  A54A8             set "update data" flag, write data, return
 
A5402  BL   @A5650            var: R2=sect/file R3=sect offset R0=rec offset
       MOV  3,3               sector offset in file
       JLT  A540C             -1: top of file
       JMP  A5422             in file
A540C  BLWP @>005A(9)         "next sector" loop
       DATA >3000             save R2 + R3
       BL   @A4658            call subroutine
       DATA A489A             update data buffer if needed
       BLWP @>005A(9)
       DATA >3001             retrieve R2 + R3
       INC  3                 next sector
       CLR  0                 init char offset in sector
 
A5422  C    3,2               did we reach last sector?
       JNE  A5438             no
       BLWP @>005A(9)         yes: expand file
       DATA >9000             save R0 + R4
       BL   @A4658            call subroutine
       DATA A4964             get last sector then append sectors to reach R3
       BLWP @>005A(9)
       DATA >9001             retrieve R0 + R4
 
A5438  MOV  @>0054(9),5       PAB ptr
       AI   5,>0005           point to char count
       BLWP @>005A(9)         set VDP to read
       DATA >00A2             address in R5
       MOVB @>FBFE(15),4      get # of chars to write
       SRL  4,8               make it a word
       MOV  4,5
       A    0,5               add current char offset in sector
       INC  5                 make room for size byte
       CI   5,>00FF           past end of sector?
       JH   A540C             yes: not enough room, try next sector
       SETO 2                 ok: rec will fit in sector
       MOV  @>0056(9),1       FDR ptr
       A    5,1               past-last-byte offset
       AI   1,>0100           ptr to data buffer area
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 2,@>FFFE(15)      write end-of-sect mark to FDR data buffer area
       BLWP @>005A(9)
       DATA >8000             save R0 (current byte offset in sector)
       MOV  3,0
       BL   @A55EE            update sect + rec offsets in control block
       AI   1,>0012           point to eof offset in FDR (R1 modified by A55EE)
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 5,@>FFFE(15)      update eof offset in last sector, in FDR
       BL   @A561A            update # of rec/file in FDR
       BLWP @>005A(9)
       DATA >2001             retrieve old R0 in R2 (current byte offset)
       MOV  4,0               record size
       BL   @A4658            call subroutine
       DATA A55CA             get FDR data buffer in R2, PAB data buffer in R1
       SWPB 4
       BLWP @>005A(9)         set VDP to write
       DATA >0043             address in R2
       MOVB 4,@>FFFE(15)      write size byte to FDR data buffer
       INC  2                 increment dest pointer
 
A54A8  MOV  2,3               invert source and dest
       MOV  1,2               so we can use the same read-write loop
       MOV  3,1               than the "read" opcode
       MOV  @>0056(9),4       FDR ptr
       DEC  4                 pointer to drive # for that file
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),5      get drive #
       ORI  5,>8000           add "update data area" flag
       BLWP @>005A(9)         set VDP to write
       DATA >0083             address in R4
       MOVB 5,@>FFFE(15)      write back flagged byte
       B    @A533E            to read-write loop
*
A54D0  BL   @A4658            find FDR in VDP buffer
       DATA A4DA4             ---------------------- find file FDR
       MOV  4,4               found?
       JEQ  A54E0             yes
       BL   @A4C72            no: return with error
       DATA >E000             "file error"
A54E0  INC  1                 point to filename in FDR
       MOV  1,@>0056(9)       new FDR ptr
       MOV  @>0054(9),4       get PAB ptr
       INC  4                 point to status byte
       CLR  0
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),0      get file status
       B    @A4676            return to caller
*
A54FC  MOV  @>0056(9),4       get status byte from FDR
       AI   4,>000C           ------------------------ point to status byte
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),0      read status byte
       B    *11
*
A5510  MOVB @>FBFE(15),5      get record # from PAB, check if valid
       SRL  5,8               -------------------------------------
       JNE  A551C             get # of rec/sector from FDR
       LI   5,>0100           0: default to 256
A551C  MOV  @>0054(9),3       PAB ptr
       AI   3,>0006           point to rec #
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),1      get record # from PAB
       SWPB 1
       MOVB @>FBFE(15),1
       SWPB 1
       MOV  1,0               save it
       JLT  A553C             too big
       JMP  A5542             ok
A553C  BL   @A4C72            update data then return with error
       DATA >8000             "memory full"
A5542  INC  0                 next record
       BLWP @>005A(9)         set VDP to write
       DATA >0063             address in R3
       MOVB 0,@>FFFE(15)      write back # of future record
       SWPB 0
       MOVB 0,@>FFFE(15)
       CLR  0
       MOV  1,3               save # of desired rec
       DIV  5,0               divide by # of rec/sector = sect # in R0
A555A  MOV  @>0056(9),2       FDR ptr
       AI   2,>0012           point to total # of rec (# of sectors for var)
       BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),2      get total # of recs/file (sect/file for var)
       SWPB 2
       MOVB @>FBFE(15),2      remember: bytes are swapped
       C    3,2               compare with desired record (ignored by var)
       B    *11
*
A5576  BLWP @>005A(9)         fetch record into FDR data buffer area
       DATA >4000             -------------------------------------- save R1
       AI   4,>FFEE           ptr to top of control block
       BLWP @>005A(9)         set VDP to read
       DATA >0082             address in R4
       MOVB @>FBFE(15),5      get current sector offset in file
       SWPB 5
       MOVB @>FBFE(15),5
       SRC  5,8
       JLT  A559E             -1: top of file
       C    5,0               compare with desired offset (from A5510)
       JEQ  A55AE             same
       BL   @A4658            call subroutine
       DATA A489A             update data buffer if needed
A559E  MOV  0,3               desired sector offset in file
       BL   @A55EE            update sect + rec offsets in control block
       AI   7,>0100           point to data buffer area (R7 set by A55EE)
       BL   @A4658            call subroutine
       DATA A492E             read a sector from offset in file (in R3)
A55AE  BLWP @>005A(9)
       DATA >4001             retrieve R1
       MOV  @>0056(9),3       FDR ptr
       AI   3,>0011           point to record length
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),0      get rec length in bytes
       SRL  0,8               make it a word
       MPY  0,1               calc file offset in bytes
A55CA  A    @>0056(9),2       add FDR ptr
       AI   2,>0100           point inside data buffer area
       MOV  @>0054(9),3       PAB ptr
       INCT 3                 point to data buffer address
       BLWP @>005A(9)         set VDP to read
       DATA >0062             address in R3
       MOVB @>FBFE(15),1      get PAB data buffer address
       SWPB 1
       MOVB @>FBFE(15),1
       SWPB 1
       B    @A4676            return
*
A55EE  MOV  @>0056(9),7       update sect + rec offsets in control block
       MOV  7,1               ------------------------------------------ FDR ptr
       AI   1,>FFFA           top of file control block
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      current sector offset in file
       SWPB 0
       MOVB 0,@>FFFE(15)
       AI   1,>0004           point to var rec offset in sector
       SWPB 5
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 5,@>FFFE(15)      first free byte in current sector
       B    *11
*
A561A  MOV  @>0056(9),2       update # of rec/file in FDR
       BLWP @>005A(9)         --------------------------- set VDP to read
       DATA >0042             address in R2 (FDR ptr)
       MOVB @>FBFE(15),10     get first char of filename
       ORI  10,>8000          set "was modified" flag
       BLWP @>005A(9)         set VDP to write
       DATA >0043             address in R2
       MOVB 10,@>FFFE(15)     write flagged char back
       AI   2,>0012           point to # of recs/file in FDR
       INC  3                 one more
       BLWP @>005A(9)         set VDP to write
       DATA >0043             address in R2
       SWPB 3                 update # of recs/file
       MOVB 3,@>FFFE(15)
       SWPB 3
       MOVB 3,@>FFFE(15)
       B    *11
*
A5650  MOV  @>0056(9),8       get rec offset, compare sect with total
       MOV  8,4               --------------------------------------- FDR ptr
       AI   4,>0100           point to data buffer area
       DECT 8                 point to var record offset
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),2      get var rec offset in current sector
       SRL  2,8               make it a word
       MOV  11,10             save return point
       BL   @A4B74            get 2 bytes from FDR (at R8-4) into R0
       DATA -4                current sector offset in file
       MOV  0,3               save it
       MOV  10,11             restore return point
       MOV  2,0               var record offset
       B    @A555A            get # of sect/file from FDR, return
*
*------------------------------------
* Opcode 4: Rewind
* --------------
* PAB 0: >04
*     1: file type <--- error code
*   2-3:
*     4:
*     5:
*   6-7: record #  <--- >0000 if sequential
*     8:
*------------------------------------
A567A  BL   @A4658            call subroutine
       DATA A54D0             find FDR in VDP buffers, read status from PAB
       BLWP @>005A(9)
       DATA >8000             save R0 (status from PAB)
       ANDI 0,>0600           keep only access mode
       JEQ  A5696             "update" is ok
       CI   0,>0400           is it "input"?
       JEQ  A5696             yes: ok
       B    @A50BA            "output" or "append": return with "illegal opcode"
A5696  BL   @A4658            call subroutine
       DATA A489A             update data buffer if needed
       BLWP @>005A(9)
       DATA >8001             retrieve R0 (status from PAB)
       ANDI 0,>0100           sequential or reloc?
       JNE  A56CA             reloc: don't do anything, return
 
A56A8  CLR  2                 rewind file: record offset = 0
       SETO 3                 -----------  current record = -1 (none)
       BL   @A52AA            update file control block
       CLR  0                 record 0
       MOV  @>0054(9),8       get PAB ptr
       AI   8,>0006           point to record #
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write record #
       NOP
       MOVB 0,@>FFFE(15)
A56CA  B    @A4676            return to caller
*
*------------------------------------
* Opcode 5: Load
* --------------
* PAB 0: >05
*     1: file type  <--- error code
*   2-3: data buffer address in VDP mem
*     4:
*     5:
*   6-7: maximum # of bytes (size of buffer)
*     8:
*------------------------------------
A56CE  BL   @A4658            call subroutine
       DATA A4E02             find FDR on disk
       MOV  4,4               found?
       JEQ  A56DE             yes
A56D8  BL   @A4C72            no: return with error
       DATA >E000             "file error"
A56DE  BL   @A4B70            get 2 bytes from FDR into R0
       DATA >000C             file status byte
       ANDI 0,>0100           is it "program"?
       JEQ  A56D8             no: file error
       INCT 8                 point to # of sect/file in FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),1      get # of sectors in file
       SWPB 1
       MOVB @>FBFE(15),1
       SRC  1,8
       JEQ  A56D8             0=empty file: return with "file error"
       BL   @A57C0            get data buffer address in R7, # of sectors in R2
       INCT 8                 point to eof offset in FDR
       CLR  4
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),4      get # of bytes in last sector
       C    1,2               compare # of sect with max in PAB
       JH   A56D8             file is too big: return with "file error"
       JNE  A571C             file is smaller
       C    0,4               same # of sect: check bytes in last sector
       JL   A56D8             file is too big: "file error"
A571C  CLR  3                 sector offset in file
       SWPB 4
A5720  DEC  1                 next sector
       JEQ  A573E             done
       BLWP @>005A(9)
       DATA >D900             save R0, R1, R3, R4, R7
       BL   @A4658            call subroutine
       DATA A492E             read a sector from offset in R3
       BLWP @>005A(9)         restore R0, R1, R3, R4, R7
       DATA >D901
       INC  R3                next sector
       AI   7,>0100           256 bytes further in PAB buffer
       JMP  A5720             keep going
 
A573E  MOV  4,4
       JNE  A574A
       BL   @A4658            call subroutine
       DATA A492E             read a sector from offset in R3
       JMP  A576C             done
 
A574A  MOV  7,5               save PAB data buffer ptr
       MOV  @>0056(9),7       FDR ptr
       AI   7,>0100           point to FDR data area
       BLWP @>005A(9)
       DATA >0D00             save R4, R5, R7
       BL   @A4658            call subroutine
       DATA A492E             read a sector from offset in R3
       BLWP @>005A(9)         restore R4 in R0, R5 in R1, R7 in R2
       DATA >E001
       BL   @A4658            call subroutine
       DATA A533E             write bytes from FDR data buffer to PAB data buf
A576C  B    @A487A            update FDR, data buffer, VIB and return to caller
*
*------------------------------------
* Opcode 6: Save
* --------------
* PAB 0: >06
*     1: file type  <--- error code
*   2-3: data buffer address in VDP mem
*     4:
*     5:
*   6-7: # of bytes to save
*     8:
*------------------------------------
A5770  BL   @A4658            call subroutine
       DATA A4798             create file
       BL   @A57C0            get PAB buffer ptr + # of bytes
       CLR  3                 sector offset 0
A577C  BLWP @>005A(9)
       DATA >B100             save R0, R2, R3, R7
       BL   @A4658            call subroutine
       DATA A494E             write sector to offset in R3
       BLWP @>005A(9)
       DATA >B101             retrieve R0, R2, R3, R7
       INC  3                 next sector
       AI   7,>0100           256 bytes further in PAB data buffer
       DEC  2                 next sector
       JNE  A577C             more to do
 
       MOV  @>0056(9),1       FDR ptr
       AI   1,>000C           point to file status byte
       LI   2,>0100           value for "program" file
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 2,@>FFFE(15)      write file status byte in FDR
       AI   1,>0004           point to eof offset byte in FDR
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      # of bytes in last sector
       B    @A487A            update FDR, data buffer, VIB then return to caller
*
A57C0  MOV  @>0054(9),0       get buffer address + # of bytes
       INCT 0                 ------------------------------- data buffer in PAB
       BLWP @>005A(9)         set VDP to read
       DATA >0002             address in R0
       MOVB @>FBFE(15),7      get data buffer address
       SWPB 7
       MOVB @>FBFE(15),7
       SWPB 7
       AI   0,>0004           point to # of bytes to transfer
       BLWP @>005A(9)         set VDP to read
       DATA >0002             address in R0
       MOVB @>FBFE(15),2      get # of bytes to be transfered
       SRL  2,8               make it # of sectors (256 bytes each)
       CLR  0
       MOVB @>FBFE(15),0      see if one more is needed
       JEQ  A57F2             no
       INC  2                 yes: one more sector
A57F2  B    *11
*
*-------------------------------------
* Opcode 9: Status
* --------------
* PAB 0: >09
*     1:
*   2-3:
*     4:
*     5:
*   6-7: record #
*     8:           <--- file status
*
* Status bits, returned in PAB byte 8:
* >80: file not found
* >40: file is protected
* >20:
* >10: internal (else display or program)
* >08: program file
* >04: variable (else fixed or program)
* >02: memory full
* >01: end-of-file reached
*-------------------------------------
A57F4  BL   @A4658            call subroutine
       DATA A4DA4             save filename in comp buf, then find FDR in VDP
A57FA  MOV  4,4               found?
       JEQ  A581E             yes
 
       BL   @A4658            no: call subroutine
       DATA A4E0C             find FDR on disk
       LI   0,>8000           value for "file not found"
       MOV  4,4               found?
       JNE  A589E             no: return with that value
       MOV  @>0056(9),1       yes: ptr to FDR
       CLR  2
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 2,@>FFFE(15)      invalidate that FDR (file not open)
       JMP  A588A             transfer FDR status to PAB status byte
 
A581E  BL   @A4658            file is open: call subroutine
       DATA A54E0             adjust FDR ptr, get PAB file type into R4
       BL   @A54FC            get status byte from FDR
       JLT  A582C             var
       JMP  A5838             fix
 
A582C  BL   @A4658            var: call subroutine
       DATA A5362             load wanted sector, point to wanted rec in buffer
       JMP  A585A             out of range
       CLR  2                 ok: clear flag
       JMP  A588A             copy status byte from FDR into PAB, return
 
A5838  MOVB @>FBFE(15),5      fix: get rec/sect byte
       SRL  5,8               make it a word
       JNE  A5844
       LI   5,>0100           00 (program files) means 256
A5844  BL   @A4B6A            get 2 bytes from PAB into R0
       DATA >0006             # of wanted record
       MOV  0,3               save it
       JLT  A5886             too big: set memory full bit in PAB status byte
       BL   @A555A            get # recs/file into R2, comp with R3
       CLR  2
       JL   A588A             in file: copy file type bits, return
       DIV  5,2               how many sectors do we need?
       MOV  2,3               save result
 
A585A  BL   @A4B70            get 2 bytes from FDR into R0
       DATA >000E             # of sectors/file
       INC  3                 plus 1 sector for FDR
       LI   2,>0100           value for "eof reached" in PAB status
       S    0,3               are there enough sectors in file for these recs?
       JGT  A586C
       JMP  A588A             yes: we reached the eof
A586C  BL   @A4658            call subroutine
       DATA A4CD2             load VIB (sector 0)
       MOV  3,4               number of sectors that will be needed
       MOV  5,8               VIB ptr
       AI   8,>000A           skip 10 bytes (required by A5A68)
       BL   @A5A68            count free sectors in bitmap, into R3
       LI   2,>0100           value for "eof reached"
       C    3,4               are there that many free sectors?
       JHE  A588A             yes
A5886  LI   2,>0200           value for "memory full"
 
A588A  BL   @A4B70            get 2 bytes from FDR into R0
       DATA >000C             file status byte
       ANDI 0,>8F00           mask irrelevant bits
       JGT  A589A
       ORI  0,>0080           var: put var bit in PAB status style
A589A  SLA  0,3               get rid of var bit in FDR style
       SOCB 2,0               add "eof" and "mem full" bits
 
A589E  MOV  @>0054(9),1       PAB ptr
       AI   1,>0008           point to bias/status return byte
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      write file status to PAB
       B    @A4676            return to caller
*
*---------------------------------
* Disk directory access
* ---------------------
* The directory is accessed by omiting the filename in the DSR name: "DSK1."
* It must be opened for input only, as an Int/Fix 38 file.
* It consists in upto 128 records, the first one contains the disk informations,
* the others the informations for upto 127 files (in alphabetical order).
* Each record consists in an ascii string and three floating point numbers.
*
* Record 0 contains:
* - Diskname (an ascii string of upto 10 chars).
* - The number zero.
* - The number of sectors on disk.
* - The number of free sectors on disk.
*
* Other records contain:
* - Filename (an ascii string of upto 10 chars).
* - Filetype: 1=D/F, 2=D/V, 3=I/F, 4=I/V, 5=Prog, 0=end of directory.
*   If the file is protected, this number is negative (-1=D/F, etc).
* - File size in sectors (including the FDR itself).
* - File record length (0 for programs).
*---------------------------------
 
*---------------------------------
* Open disk directory pseudo-file
*---------------------------------
A58B4  MOVB @>FBFE(15),0      get file type from PAB
       ANDI 0,>1E00           mask irrelavant bits (rel/seq)
       CI   0,>0C00           is it "int/fix" in "output" mode?
       JEQ  A58C8             yes
A58C2  BL   @A4C9E            return with error
       DATA >4000             "bad attributes"
A58C8  BL   @A4B6A            get 2 bytes from PAB into R0
       DATA >0004             rec length
       SRL  0,8               make it a word
       JEQ  A58D8             >00= default: set it to 38
       CI   0,>0026           is it 38?
       JNE  A58C2             no: return with "bad attributes" error
A58D8  LI   0,>2600           set rec len to 38
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8 (from A4B6A)
       MOVB 0,@>FFFE(15)      write rec len to PAB
 
       CLR  7
       BL   @A5AA2            find matching drive in file control blocks
       DATA A58F4             go there if not found
A58EE  BL   @A4C72            update data then return with error
       DATA >E000             "file error"
A58F4  MOV  7,7               did we find a free slot?
       JNE  A58FE             yes
       BL   @A4C9E            no: return with error
       DATA >8000             "memory full"
A58FE  BLWP @>005A(9)         set VDP to write
       DATA >00E3             address in R7
       MOVB 3,@>FFFE(15)      write drive #
       SWPB 3
       MOVB 3,@>FFFE(15)      and a space as filename (illegal, indicates dir)
       B    @A4676            return to caller
*
*---------------------------------
* Close disk directory
*---------------------------------
A5912  BL   @A5AA2            find matching drive in file control blocks
       DATA A58EE             go there if not found: return with "file error"
       CLR  0
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      clear drive #
       B    @A4676            return to caller
*
*---------------------------------
* Read a record from disk directory
*---------------------------------
A5928  BL   @A5AA2            find matching drive in file control blocks
       DATA A58EE             go ther it not found: return with "file error"
       INC  8
       MOV  8,5               save ptr to FDR
       BL   @A4B6A            get 2 bytes from PAB into R0
       DATA >0006             record #
       MOV  0,2               save it
       INC  2
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 2,@>FFFE(15)      write record number in FDR
       SWPB 2                 after first char of filename!
       MOVB 2,@>FFFE(15)
       SLA  0,1               since two byte per file ptr
       MOVB 0,0               is rec # greater than 128?
       JEQ  A5958             no
       BL   @A4C72            yes: update data then return with error
       DATA >A000             "past eof"
A5958  SETO 2                 code for read
       MOV  0,4               record #
       JEQ  A59D4             0=disk parameters
       LI   4,>0001           sector #1
       BL   @A4658            call subroutine
       DATA A4D4E             read sector into buffer in R5
       MOV  5,8               buffer ptr
       AI   5,>00FF           point to data buffer area in this ctrl block
       DECT 0                 don't count record 0
       A    0,8               point to desired file ptr
       BL   @A4B76            get two byte from VDP at R8 into R0
       MOV  0,4               sector where that FDR is to be found
       JEQ  A59CA             no more
       BL   @A4658            call subroutine
       DATA A4D4E             read FDR sector into data buffer area
       BL   @A4B70            get 2 bytes from FDR into R0
       DATA >010E             # of sect/file
       MOV  0,6               save it to output file size
       INC  6                 include the FDR itself
       MOVB @>FBFE(15),3      ignore eof offset
       LI   2,>0A00           10 chars per filename
       MOVB @>FBFE(15),3      get rec length
       SRL  3,8               make it a word
       DECT 8                 point to status byte in FDR
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),0      get file status byte
       MOV  0,7
       ANDI 0,>0800           keep only "write protected" bit
       SZCB 0,7               clear "write protected" bit (if it was set)
       SRL  7,8               make it a word
       INC  7                 types are numbered from 1
       CI   7,>0002           is it a "program" file?
       JNE  A59BA             no
       AI   7,>0003           yes: make it type 5
A59BA  CI   7,>0008           is it var?
       JL   A59C4             no
       AI   7,>FF81           yes: add 1 and clear "var" bit
A59C4  SLA  0,4               "write protect" bit will be >80
       SOC  0,7               add it to file type
       JMP  A59D2
 
A59CA  CLR  2                 no more files: filename size = 0
       CLR  6                 file size = 0
       CLR  3                 rec length = 0
       CLR  7                 type = 0
A59D2  JMP  A59F2             output that
 
A59D4  AI   5,>00FF           disk info: point to data buffer area in ctrl block
       BL   @A4658            call subroutine
       DATA A4D4E             read sector 0
       BL   @A4B70            get 2 bytes from FDR into R0
       DATA >010A             # of sectors on disk
       MOV  0,6               duplicate it
       DECT 6                 minus directory itself (sect 0 + 1)
       BL   @A5A68            count free sectors in bitmap, result in R3
       CLR  7                 filetype is not used
       LI   2,>0A00           diskname is 10 chars
 
A59F2  BL   @A4B6A            get 2 bytes from PAB into R0
       DATA >0002             data buffer address
       MOV  0,8               duplicate it
       INC  8                 skip first byte
       SRL  2,8               filename length (or diskname)
       JEQ  A5A2C             0: skip filename copying
       CLR  1
A5A02  BLWP @>005A(9)         set VDP to read
       DATA >00A2             address in R5 (FDR ptr)
       MOVB @>FBFE(15),1      get 1 char from filename in FDR
       CI   1,>2000           is it a space?
       JEQ  A5A24             yes: end of name
       BLWP @>005A(9)         no: set VDP to write
       DATA >0103             address in R8 (PAB data buffer ptr)
       MOVB 1,@>FFFE(15)      copy char in PAB data buffer
       INC  5                 increment source ptr
       INC  8                 increment destination ptr
       DEC  2                 next char
       JNE  A5A02
A5A24  NEG  2                 number of trailing spaces
       AI   2,>000A           number of chars in filename
       SWPB 2
A5A2C  BLWP @>005A(9)         set VDP to write
       DATA >0003             address in R0 (beg of PAB data buffer)
       MOVB 2,@>FFFE(15)      write string length byte
 
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOV  7,1               file type + protection
       BL   @A5AE6            make it a float number
       MOV  6,1               file size in sectors, including FDR
       BL   @A5AE6            make it a float number
       MOV  3,1               record length
       BL   @A5AE6            make it a float number
       MOV  @>0054(9),8       get PAB ptr
       AI   8,>0005           point to character count
       LI   0,>2600           always 38 bytes
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write # of characters in record
       B    @A4676            return to caller
*
A5A68  AI   8,>002E           count free sectors in VIB bitmap
       LI   2,>00C8           -------------------------------- bitmap size
       CLR  3                 free sectors counter
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
A5A78  MOVB @>FBFE(15),1      get a byte from bitmap
       AI   1,>0100
       SRL  1,8
       JEQ  A5A9C             was >FF: no free sectors, next byte
       DEC  1                 was it >00?
       JNE  A5A8E             no: count bits
       AI   3,>0008           yes: 8 more free sectors
       JMP  A5A9C             next byte
A5A8E  LI   0,>0008           8 bits per byte
A5A92  SRL  1,1               test a bit
       JOC  A5A98             was 1: sector is used
       INC  3                 was 0: one more free sector
A5A98  DEC  0                 next bit in byte
       JNE  A5A92             more to come
A5A9C  DEC  2                 next bitmap byte
       JNE  A5A78             more to come
       B    *11
*
A5AA2  MOV  *11+,10           find drive in file control blocks
       MOV  11,5              --------------------------------- save 2 returns
       MOV  @>0056(9),8       "top of mem" word in VDP buffers header
       AI   8,>0003           point to max # of files
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),2      get # of files
       SRA  2,8               make it a word
       AI   8,>0006           point to drive # in file ctrl block
       LI   3,>0020           filename begin with space (illegal: flag for dir)
       MOVB 6,3               add drive #
A5AC4  BL   @A4B76            read 2 bytes from VDP at R8 into R0
       C    3,0               match with that control block?
       JEQ  A5ADE             yes
       ANDI 0,>00FF           keep only first char of filename
       JNE  A5AD4             valid filename: a FDR is loaded here
       MOV  8,7               this space is free: save ptr
A5AD4  AI   8,>0206           point to next file control block
       DEC  2                 next file
       JNE  A5AC4             more to come
       B    *10               not found: return to address passed in data word
A5ADE  INC  8                 drive matches: point to FDR
       MOV  8,@>0056(9)       save ptr
       B    *5                return to caller after data word
*
A5AE6  LI   2,>0800           write an integer in floating point format
       MOVB 2,@>FFFE(15)      ----------------------------------------- size=8
       MOV  1,5               integer is in R1: save it for sign processing
       ANDI 1,>7FFF           clear sign bit
       CI   1,100             is it less than 100?
       JL   A5B08             yes
       CLR  0                 100 or over
       LI   4,100
       DIV  4,0               divide by 100
       ORI  0,>4100           add exponent 2 to hundreths
       JMP  A5B12
 
A5B08  MOV  1,0               is it 0?
       JEQ  A5B10             yes: exponent is 0
       ORI  0,>4000           no: add exponent 1
A5B10  CLR  1                 next digits will be 0
 
A5B12  MOV  5,5               test sign bit
       JLT  A5B18             negative
       JMP  A5B1A             positive or zero
A5B18  NEG  0                 negate first word
A5B1A  MOVB 0,@>FFFE(15)      write exponent to VDP at preset address
       SWPB 0
       MOVB 0,@>FFFE(15)      write first first 2 digits (or hundreths)
       SWPB 1
       MOVB 1,@>FFFE(15)      write last 2 digits (if any)
       LI   2,>0005           the remaining bytes are all 0 with integers
A5B2E  MOVB 2,@>FFFE(15)      write 0 to VDP
       DEC  2                 next byte
       JNE  A5B2E             more to do
       B    *11
*--------------------------------------
* Floating point format
* ---------------------
* Float numbers are 8 bytes long: EE 12 34 56 78 9A BC
* EE is the exponent in radix 100 (not in radix 10 as usual!). It is biased
* by 64: >40=0, 41=1 (i.e *100), >42=2 (i.e * 10,000) >3F= -1 (i.e /100), etc
*
* 12 ... BC are the mantissa in binary coded decimal: each byte encodes two
* decimal digits from 00 to 99
*
* For negative numbers, the first word is negated
* For zero, the first word is >0000 the others are irrelevant
*
* Examples: 40 08 00 00 00 00 00 00 is 8.0
*           41 02 37 00 00 00 00 00 is 255.0 (>37 hex = 55 decimal)
*           BF F8 00 00 00 00 00 00 is -8.0
*           43 01 02 03 04 05 06 07 is 1020304.050607
*--------------------------------------
*
*---------------------------------------
* Subprogram >10: sector R/W
* --------------
* >834A: (n/a)      <--- sector #
* >834C: drive #
* >834D: R/W code (write if >00)
* >834E: VDP buffer
* >8350: sector #   <--- error code
*---------------------------------------
A5B38  MOV  11,7
       BL   @A4724            prepare disk operations
       MOV  @>0050(9),@>004A(9) copy sector #
       B    @A40E8
*
*---------------------------------------
* Subprogram >11: format disk
* --------------
* >834A: (n/a)      <--- # of sectors on disk
* >834C: DSR+drive # (DSR >0x old version >1x new, >2x unknown)
* >834D: # of tracks
* >834E: VDP buffer
* >8350: density    <--- error code
* >8351: # of sides <--- ditto
*---------------------------------------
A5B48  MOV  11,7
       BL   @A4724            prepare disk operations
       B    @A42AC
*
*---------------------------------------
* Subprogram >12: file (un)protect
* --------------
* >834C: drive #
* >834D: protect code (>00 unprotect)
* >834E: ptr to filename
* >8350: (n/a)      <--- error code
*---------------------------------------
A5B52  MOV  11,7
       BL   @A4724            prepare disk operations
       MOVB @>004D(9),0       get protection code
       ANDI 0,>0800           keep the bit that will be needed
       BLWP @>005A(9)         save R0 on stack
       DATA >8000
       MOV  @>004E(9),0       get pointer to filename
       BL   @A4658            call subroutine
       DATA A5C54             load FDR in VDP buffer
       BLWP @>005A(9)         retrieve old R0, in R2
       DATA >2001
       BL   @A4B70            read two bytes in R0 from top of FDR + offset
       DATA >000C             file status byte
       ANDI 0,>F700           clear protection flag
       SOCB 2,0               set it if needed
       BLWP @>005A(9)         set VDP for write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write back file status to FDR
 
A5B8C  MOV  @>0056(9),8       FDR address in VDP mem
       BLWP @>005A(9)         set VDP for read
       DATA >0102             address in R8
       MOVB @>FBFE(15),0      get drive # in ctrl block
       ORI  0,>8000           flag it
       BLWP @>005A(9)         set VDP for write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write it back
       B    @A487A            update FDR, load VIB
*
*---------------------------------
* Subprogram >13: file rename
* --------------
* >834C: drive #
* >834E: ptr to new name
* >8350: ptr to old name <--- error code
*---------------------------------
A5BAC  MOV  11,7
       BL   @A4724            prepare disk operations
       MOV  @>004E(9),0       get ptr to new filename
       BLWP @>005A(9)         save R0 on stack
       DATA >8000
       MOV  @>0050(9),0       get ptr to old filename
       BL   @A4658            call subroutine
       DATA A5C54             put FDR in VDP buffer
       BL   @A4ADA            remove FDR ptr from sector 1
       BL   @A4B70            get 2 bytes from FDR
       DATA >000C             file status byte
       ANDI 0,>0800           protected?
       JEQ  A5BDC             no
       BL   @A4C72            yes: return with error
       DATA >2000             "write protected"
A5BDC  BL   @A4B70            get 2 bytes from FDR
       DATA >FFFC             sector # of FDR
       MOV  0,1
       BLWP @>005A(9)         retrieve R0 from stack
       DATA >8001             ptr to new filename
       BLWP @>005A(9)         save R1 on stack
       DATA >4000             sector # of FDR
       BL   @A5E9C            write drive # and filename in compare buffer
       BL   @A4658            call subroutine
       DATA A4E38             find FDR from filename
       MOV  4,4               found?
       JEQ  A5C6E             yes: return with "file error" (name already exist)
       BL   @A4B0A            insert a FDR in sector 1
       BLWP @>005A(9)         retrieve sect # of FDR in R4
       DATA >0801
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 4,@>FFFE(15)      write sector # of FDR
       SWPB 4
       MOVB 4,@>FFFE(15)
       SWPB 4                 sector #
       SETO 2                 code for read
       CLR  5                 buffer offset: VDP at >8356
       BL   @A4658            call subroutine
       DATA A4D4A             read FDR
       MOV  5,1
       MOV  @>0058(9),0
       AI   0,>0101
       DEC  1
       BL   @A5EB2            copy filename in compare buffer to FDR
       CLR  2                 code for write
       BL   @A4658            call subroutine
       DATA A4D4E             write FDR (with new name in it)
       BL   @A4658            call subroutine
       DATA A4D36             write sector 1 (with new FDR ptr in it)
       MOV  @>0056(9),1       FDR ptr
       BLWP @>005A(9)         prepare VDP to write
       DATA >0023             address in R1
       MOVB 4,@>FFFE(15)      clear first char of FDR in buffer
       B    @A4676            return to caller
*
A5C54  CLR  6                 put FDR in VDP buffer
       MOVB @>004C(9),6       --------------------- get drive #
       BL   @A5E9C            update filename compare buffer
       BL   @A4658            call subroutine
       DATA A4DC4             look if FDR already in VDP buffer
       BL   @A4658            call subroutine
       DATA A4E08             file FDR on disk
       MOV  4,4               found?
       JEQ  A5C74             yes
A5C6E  BL   @A4C9E            no: return with error code in >8350
       DATA >E000             "file error"
A5C74  B    @A4676            return to caller
*
*-------------------------------------
* Subprogram >14: file raw read
* --------------
* >834C: drive #                          <--- >00
* >834D: # of sectors (>00=get file info) <--- sectors read
* >834E: ptr to filename
* >8350: file info buffer (>83xx)         <--- error code
*                              |
* >83xx  : VDP buffer       <--'
* >83xx+2: first sector # (total # of sect when get file info)
* >83xx+4: status flag
* >83xx+5: recs/sector
* >83xx+6: eof offset
* >83xx+7: rec size
* >83xx+8: # of recs
*-------------------------------------
A5C78  MOV  11,7
       BL   @A4724            prepare disk operations
       BL   @A5ED4            load filename and ptrs
       BL   @A5EFA            find file FDR, load some info
       MOV  2,2               # of sectors to read
       JEQ  A5CC6             >00: get file info
       S    3,0               sectors in file -  first sector to read
       JGT  A5C92             in file
       CLR  2                 past eof
       JMP  A5CC0
A5C92  C    2,0               sectors past first one vs sectors to load
       JL   A5C98
       MOV  0,2               load what's left
A5C98  BLWP @>005A(9)
       DATA >2000             save R2
A5C9E  BLWP @>005A(9)
       DATA >3100             save R2, R3, R7
       BL   @A4658            call subroutine
       DATA A492E             read sector from offset in file
       BLWP @>005A(9)
       DATA >3101             retrieve R2, R3, R7
       INC  3                 next sector
       AI   7,>0100           increment VDP buffer ptr by 256 bytes
       DEC  2                 more to do?
       JNE  A5C9E             yes
A5CBA  BLWP @>005A(9)
       DATA >2001             retrieve R2 (# of sectors read)
A5CC0  MOV  2,@>004C(9)       update # of sectors in parameters
       JMP  A5CDA
 
A5CC6  MOV  0,*4+             get file info: sectors in file
       DECT 8
       INCT 2                 copy 2 bytes (status + recs/sector)
       BL   @A5F2E            from VDP at R8 to file info structure
       LI   2,>0004           copy 4 bytes
       A    2,8
       BL   @A5F2E            eof offset, rec len, # of recs (or # of sect)
A5CDA  BL   @A4658            call subroutine
       DATA A487A             updata FDR (+ data) if needed, read VIB
       CLR  @>0050(9)         clear error flag
       B    @A4676            return to caller
*
*--------------------------------------
* Subprogram >15: file raw write
* --------------
* >834C: drive #                                  <--- >00
* >834D: # of sectors (>00=create file from info) <--- # of sectors written
* >834E: ptr to filename
* >8350: file info buffer (>83xx)                 <--- error code
*                              |
* >83xx  : VDP buffer       <--'
* >83xx+2: first sector # (total # of sectors when creating file)
* >83xx+4: status flag
* >83xx+5: recs/sector
* >83xx+6: eof offset
* >83xx+7: rec size
* >83xx+8: # of recs
*--------------------------------------
A5CE8  MOV  11,7
       BL   @A4724            prepare disk operations
       BL   @A5ED4            load drive + filename, + a few info
       JEQ  A5D1C             sectors to write=0: create file
       BL   @A5EFA            find file FDR
       BLWP @>005A(9)
       DATA >2000             save R2 (# of sectors to write)
A5CFE  BLWP @>005A(9)
       DATA >3100             save R2, R3, R7
       BL   @A4658            call subroutine
       DATA A494E             write sector from offset in file
       BLWP @>005A(9)
       DATA >3101             retrieve R2, R3, R7
       INC  3                 next sector
       AI   7,>0100           increment VDP ptr by 256 bytes
       DEC  2                 more to do?
       JNE  A5CFE             yes
       JMP  A5CBA             update # of sectors written, in param. Then return
 
A5D1C  BL   @A4658            create file
       DATA A4DC4             find file FDR in VDP buffers
       BL   @A4658            call subroutine
       DATA A4E08             find file FDR on disk
       BL   @A4658            call subroutine
       DATA A479E             create file
       BLWP @>005A(9)
       DATA >0801             retrieve R4 (file info ptr)
       MOV  @>0056(9),8       FDR ptr
       INCT 4                 skip 2 bytes
       MOV  *4+,3             # of sector to create
       AI   8,>000A           skip filename
       BL   @A5F3E            write 2 bytes in VDP at R8+2
       DATA >0002             i.e. status + recs/sector
       BL   @A5F3E            write 4 bytes in VDP at new R8+4
       DATA >0004             i.e. eof offset, rec len, # of recs (or # of sect)
       DEC  3                 offset = # of sectors-1 (starts from 0)
       JLT  A5D56             create an empty file, FDR only
       BL   @A4658
       DATA A4964             append enough sectors to reach offset
A5D56  B    @A5B8C            modify FDR, write it, load VIB, return
*
*---------------------------------------
* Subprogram FILES: number of files
*---------------------------------------
A5D5A  MOV  11,7
       BL   @A4724            prepare disk operation
       MOV  @>002C(9),8       ptr to next basic token
       AI   8,>0007           skip "FILES"
       BL   @A4B76            get next two bytes in R0
       CI   0,>C801           >C8=unquoted string, size=1 char
       JNE  A5DAA             return (with error) if different
       INCT 8                 increment pointer
       BL   @A4B76            get next two bytes
       SWPB 0
       AI   0,>49D0           substact >B630: # of files  >B6=closed parenthesis
       CI   0,>0009           only 9 files allowed in Basic !
       JH   A5DAA             return with error if more
       SWPB 0
       MOVB 0,@>004C(9)       put new # of files in scratch-pad memory
       BL   @A4658            call subroutine
       DATA A5DB4             subprogram >16 (private entry point)
       MOVB @>0050(9),@>0050(9) test result
       JNE  A5DAA             error
       MOV  @>002C(9),8       ok: get ptr to Basic token
       AI   8,>000C           skip the whole statement
       MOV  8,@>002C(9)       update ptr
       SZCB @>0042(9),@>0042(9) clear current token
A5DAA  B    @A4676            return to caller (i.e. Basic)
*
*---------------------------------------
* Subprogram >16: number of files
* --------------
* >834C: # of files
* >8350: (n/a)      <--- error code
*---------------------------------------
A5DAE  MOV  11,7              entry point from assembly
       BL   @A4724            prepare disk operations
A5DB4  CLR  0                 entry point from "call files"
       MOVB @>004C(9),0       get # of files
       JEQ  A5E94             return with error
       MOV  @>0056(9),8       ptr to "end of buffer" word
       AI   8,>0003           point to "# of files" byte
       CLR  3
       BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),3      get current # of files
       LI   5,>0206           size of 1 file control block
       CB   0,3               compare required with current
       JEQ  A5E8E             same: return with no error
       JLE  A5E30             less
       MOV  0,6               more files needed
       CI   0,>1000           maximum is 16
       JH   A5E94             return with error
       S    3,0               how many to add
       SRL  0,8               make it a word
       MPY  5,0               # of bytes to add
       MOV  1,4               result in R0:R1
       NEG  4
       MOV  @>0070(9),2       highest free address in VDP mem
       MOV  2,0
       S    1,0               what it would become
       CI   0,>0800           is there room enough for VDP?
       JLT  A5E94             no: return with error
       MOV  0,1               ok: new base
A5DFC  INC  2                 increment source ptr
       INC  0                 increment destination ptr
       BLWP @>005A(9)         set VDP to read
       DATA >0042             address in R2
       MOVB @>FBFE(15),3      get a byte
       BLWP @>005A(9)         set VDP to write
       DATA >0003             address in R0
       MOVB 3,@>FFFE(15)      copy a byte
       C    2,8               did we copy the whole header?
       JNE  A5DFC             not yet
       BLWP @>005A(9)         set VDP to write
       DATA >0003             address in R0
       MOVB 6,@>FFFE(15)      new # of files
       CLR  6
       S    0,2
A5E26  MOVB 6,@>FFFE(15)      clear byte
       DEC  2
       JNE  A5E26
       JMP  A5E64
 
A5E30  BLWP @>005A(9)         less files needed
       DATA >0103             set VDP to write to address in R8
       MOVB 0,@>FFFE(15)      new # of files in buffer header
       S    0,3               how many to remove
       SRL  3,8               make it a word
       MPY  5,3               # of bytes to remove
       MOV  4,1               result in R3:R4
       A    8,1               new address for buffer header
       MOV  @>0070(9),2       highest free address in VDP mem
A5E48  BLWP @>005A(9)         set VDP to read
       DATA >0102             address in R8
       MOVB @>FBFE(15),0      read a byte
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 0,@>FFFE(15)      write byte back
       DEC  1                 decrement destination ptr
       DEC  8                 decrement source ptr
       C    8,2               did we copy the whole header?
       JNE  A5E48             not yet
 
A5E64  MOV  1,@>0070(9)       new first free address
       MOV  1,8
A5E6A  INCT 8                 point to "end of buffer" word
       BL   @A4B76            read it in R0
       MOVB @>FBFE(15),1      get CRU base byte
       CB   12,1              same as current controller?
       JEQ  A5E8E             yes: return with no error
       A    4,0               no: coin address of next buffer
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8
       MOVB 0,@>FFFE(15)      write new "end of buffer" word
       MOV  0,8               and make it new address
       SWPB 0
       MOVB 0,@>FFFE(15)
       JMP  A5E6A             now, try again
 
A5E8E  CLR  @>0050(9)         clear error flag
       JMP  A5E98
A5E94  SETO @>0050(9)         set error flag
A5E98  B    @A4676            return to caller
*
*-----------------------------------------------------------
*
A5E9C  CLR  @>0054(9)         write drive # and filename in compare buffer
       MOV  @>0058(9),1       --------------------------------------------
       AI   1,>0100           ptr to filename compare buffer
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 6,@>FFFE(15)      write drive #
A5EB2  LI   2,>000A           filename must be exactly 10 chars
A5EB6  INC  1                 next char in compare buffer
       BLWP @>005A(9)         set VDP to read
       DATA >0002             address in R0
       MOVB @>FBFE(15),3      get 1 char from filename
       INC  0                 next char in provided filename
       BLWP @>005A(9)         set VDP to write
       DATA >0023             address in R1
       MOVB 3,@>FFFE(15)      write 1 char to compare buffer
       DEC  2
       JNE  A5EB6             next char
       B    *11
*
A5ED4  MOV  11,10             load compare buffer and ptrs
       CLR  6                 ----------------------------
       MOVB @>004C(9),6       drive #
       MOV  @>004E(9),0       ptr to filename
       BL   @A5E9C            write them in compare buffer
       MOVB @>0050(9),4       file info structure ptr
       SRL  4,8
       A    9,4               make it a PAB address
       MOVB @>004D(9),0       # of sectors (>00=get file info)
       BLWP @>005A(9)
       DATA >0800             save R4
       SRL  0,8
       B    *10               EQ set for get file info
*
A5EFA  BLWP @>005A(9)         find file FDR
       DATA >8010             ------------- save R0 + R11
       BL   @A4658            call subroutine
       DATA A4DC4             find file FDR in VDP buffers
       BL   @A4658            call subroutine
       DATA A4E08             find FDR on disk
       MOV  4,4               found ?
       JEQ  A5F16             yes
       BL   @A4C72            no: return with error
       DATA >E000             "file error"
A5F16  BL   @A4B70            get two bytes from FDR into R0
       DATA >000E             # of sectors in file
       BLWP @>005A(9)
       DATA >2011             retrieve R0 in R2 (# of sect to read), and R11
       BLWP @>005A(9)
       DATA >0801             retrieve R4 (ptr to file info structure)
       MOV  *4+,7             VDP buffer
       MOV  *4,3              first sector
       B    *11
*
A5F2E  BLWP @>005A(9)         copy VDP bytes to scratch-pad
       DATA >0102             ----------------------------- read from VDP at R8
A5F34  MOVB @>FBFE(15),*4+    read bytes into scratch-pad at R4
       DEC  2                 # of byte in R2
       JNE  A5F34             next byte
       B    *11
*
A5F3E  MOV  *11+,2            copy scratch-pad bytes to VDP
       A    2,8               -----------------------------
       BLWP @>005A(9)         set VDP to write
       DATA >0103             address in R8 + offset in data word
A5F48  MOVB *4+,@>FFFE(15)    write byte from scratch-pad at R4
       DEC  2                 # of bytes in R2, was in data word
       JNE  A5F48             next byte
       B    *11
*-----------------------------------------
*
* The remaining bytes (>5F52 to >5FEF) all contain >FFFF
* Bytes >5FF0 to >5FFE map to the FDC registers
*
*-----------------------------------------
* Th.N. April 1999
 
       END

 

 

The above code has registers listed as 0 – 15, which can be a bit difficult to read for those of us accustomed to seeing them as R0 – R15.

 

[EDIT: It may be helpful to note that the >16 routine uses the GPL workspace, in which R9 has been set to the start of Scratchpad RAM (>8300) and R15 always contains the VRAM write address (>8C02).]

 

...lee

 

Edited by Lee Stewart
clarification
  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...